我是Rust的初学者,我正在尝试为我的简单编译器实现访问者模式,在那里我实现AST实体并让访问者遍历AST以生成代码。
这个过程的核心部分是visitor
(trait)的visit_response()
函数,它接受不同类型的AST实体,访问者调用不同的函数作为响应。
我现在遇到的问题是,我想将匹配的对象传递给各种visit_<>()函数,这些函数具有对应于各种AST实体类型的函数签名。
当我简单地传入匹配对象时,我得到错误“mismatched types expected &ASLvalExpression
,found ASEntitiesKind
“。
有没有一种方法可以将匹配对象v转换为各种匹配类型,以便我可以将它们用作匹配臂中的匹配类型?可以做到吗?谢谢!
enum ASEntitiesKind {
ASSimpleLval(i32, i32),
}
pub trait Visitable {
fn get_struct_name(&self) -> &'static str;
fn to_string(&self) -> &'static str;
fn visit<'a, T: Visitor<&'a Self>>(&'a self, v: Box<T> ) {
v.visit_response(self);
}
}
pub trait Visitor<M> {
fn visit_response<'a>(&self, v: M );
}
pub struct ASSimpleLval {
m_pos: i32,
m_value: i32,
}
impl Display for ASSimpleLval {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.m_value)
}
}
impl Visitor<&ASEntitiesKind> for ASPrintAbsyn {
fn visit_response<'a>(&self, v: &ASEntitiesKind ) {
match v {
ASEntitiesKind::ASSimpleLval(i1,i2) => {
self.visit_simple_var(ASSimpleLval{m_pos: *i1, m_value: *i2});
}
}
}
}
pub struct ASPrintAbsyn {}
impl ASPrintAbsyn {
fn visit_simple_var(&self, v: ASSimpleLval) {
println!("{}", v.to_string());
}
}
字符串
我期望匹配对象可以在匹配臂中用作匹配类型的对象。
更新:我已经更新了作为mre的代码。这段代码工作,但有点东西我不喜欢它。
1.在每一个arm上,我都需要销毁枚举类型并重新构造一个完整的新结构体,以传递给各个visit_<>函数。
1.作为1的结果,我将在visit_response函数中向visit_<>函数(在本例中是新创建的ASSimpleLval{}结构)传递一个局部变量的引用,而不是v:& ASSimpleLval {}结构。
有没有更好的方法来写这篇文章来解决上述两点?谢谢!!
1条答案
按热度按时间5lhxktic1#
虽然你可以在每个
match
分支内部重构类型,但最好是对每个枚举变量进行模式匹配,并将内部参数给予给函数。例如,你可以像这样重构代码:字符串
其中a是
i32
,B是Symbol
,c是i64
。您也可以使用相同的名称,但在这里选择有意义的名称更符合习惯。