在Rust中使用匹配臂中匹配的对象作为匹配类型?可以吗?

ibrsph3r  于 2023-11-19  发布在  其他
关注(0)|答案(1)|浏览(75)

我是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 {}结构。
有没有更好的方法来写这篇文章来解决上述两点?谢谢!!

5lhxktic

5lhxktic1#

虽然你可以在每个match分支内部重构类型,但最好是对每个枚举变量进行模式匹配,并将内部参数给予给函数。例如,你可以像这样重构代码:

enum ASEntitiesKind {
  ASSimpleLval(i32, Symbol),
  ASIntConstant(i32, i64),
  ...
}

impl Visitor<ASEntitiesKind> for ASPrintAbsyn {
  fn visit_response<'a>(&self, v: ASEntitiesKind ) {
    match v {
      ASEntitiesKind::ASSimpleLval(a, b) => {
        self.visit_simple_var(a, b);
      },
      ASEntitiesKind::ASIntConstant(a, c) => {
        self.visit_int_constant(a, c);
      },
      ...
    }
  }
}

字符串
其中a是i32,B是Symbol,c是i64。您也可以使用相同的名称,但在这里选择有意义的名称更符合习惯。

相关问题