递归计算Scala抽象语法树

递归计算Scala抽象语法树,scala,abstract-syntax-tree,Scala,Abstract Syntax Tree,假设我有一个lambda,我使用reify将其转换为一个缠绕在树上的Expr。比如说 val expr = reify{x: Int => 3*(4+x)} 我可以对一个特定的x进行如下评估 val toolbox = currentMirror.mkToolBox() val fun = toolbox.eval(expr.tree).asInstanceOf[Int => Int] println(fun(10)) 我的目标是打印出整个树,并在每个子表达式上用值进行注释。如何

假设我有一个lambda,我使用reify将其转换为一个缠绕在树上的Expr。比如说

val expr = reify{x: Int => 3*(4+x)}
我可以对一个特定的x进行如下评估

val toolbox = currentMirror.mkToolBox()
val fun = toolbox.eval(expr.tree).asInstanceOf[Int => Int]
println(fun(10))
我的目标是打印出整个树,并在每个子表达式上用值进行注释。如何确定所有子表达式及其值?例如,确定当x为10时,存在一个子表达式

(4+x)
总数为14。Traverser类允许我访问树中的每个节点,但我不知道如何计算每个节点上的子树

例如,使用以下

class TestTraverser extends Traverser {
  override def traverse(tree: Tree): Unit = {
    val toolbox = currentMirror.mkToolBox()
    tree match {
      case app @ Apply(fun, args) =>
        val f = toolbox.eval(app.fun)
      case _ =>
    }
    super.traverse(tree)
  }
}
召唤

new TestTraverser().traverse(expr.tree)
导致此异常

scala.tools.reflect.ToolBoxError: reflective compilation has failed:

ambiguous reference to overloaded definition,
both method * in class Int of type (x: Char)Int
and  method * in class Int of type (x: Byte)Int
match expected type Any

我自己解决了这个问题。为了在子树上调用
toolbox.eval
,您需要用指示它是名为
x
Int
函数的信息重新包装子树。下面是一个有效的
遍历器的示例

class WorkingTraverser extends Traverser {
  val toolbox = currentMirror.mkToolBox()
  override def traverse(tree: Tree): Unit = {
    tree match {
      case app @ Apply(fun, args) =>
        val newfun = Function(List(ValDef(Modifiers(PARAM), TermName("x"), Ident(TypeName("Int")), EmptyTree)), Apply(app.fun, app.args))
        val f = toolbox.eval(newfun)
        val f2 = f.asInstanceOf[Int => Int]
        println(app.fun + "(" + app.args + ")" + " evaluates to " + f2(10))
        super.traverse(fun)
        super.traverseTrees(args)
      case _ => super.traverse(tree)
    }
  }
}

为子树调用eval?你可能认为有某种方法可以在子树上调用eval,但我还没有找到一种方法。我已经添加了一个遍历器,它尝试了这一点,但不起作用。完全脱离主题,但是,您知道“@”语法是如何调用的吗?我不明白怎么读它,它的意思是什么,我还能在哪里使用它,等等。