有人可以帮助我掌握允许在scala中修改AST的转换对象吗?
网络上有很多例子,但我很难理解递归是如何发生的。
E.g。如果我有这个AST:
def foo = {
true
}
或
def foo = true
并希望将其转换为
def foo = {
println("foo")
true
}
转换函数应该如何显示。在这一点上,我有这样的事情:
override def transform(tree: Tree) = tree match {
case defdef @ DefDef(_,_,_,_,_,rhs) => rhs match{
case b: Block => treeCopy.Block(b, createPrintln :: b.stats, b.expr)
case _ => //Manage functions without block
}
case t => super.transform(t)
}
private def createPrintln = Apply(Select(Ident("System.out"), newTermName("println")), List(Literal(Constant("foo"))))
但是不起作用,说实话我只是应用我在示例中看到的但却无法弄清楚树是如何构建的。 “傻瓜”的解释将不胜感激。
[编辑]
Senia的例子很不错,但是当我有一个更复杂的树时,我仍然感到困惑:
imports bla.bla
class MyObject{
val x = 0
def foo = true
def foo2 = { 1 }
}
object MyObject
预期结果:
import bla.bla
class MyObject{
val x = 0
def foo = { println("foo"); true }
def foo2 = { println("foo"); 1 }
}
object MyObject
答案 0 :(得分:5)
您的原始Tree
如下所示:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> showRaw{ reify { def foo = { true } }.tree }
res0: String = Block(List(DefDef(Modifiers(), newTermName("foo"), List(), List(), TypeTree(), Literal(Constant(true)))), Literal(Constant(())))
没有外Block
:
scala> showRaw{ reify { def foo = { true } }.tree match { case Block(List(defdef), _) => defdef } }
res1: String = DefDef(Modifiers(), newTermName("foo"), List(), List(), TypeTree(), Literal(Constant(true)))
因此,您的rhs
变量不是Block
。
因此,您应该将//Manage functions without block
替换为Block(createPrintln, t)
我猜你的transform
方法应该返回DefDef
,而不是Block
。
def addPrintln(t: Tree): Block = t match {
case b :Block => treeCopy.Block(b, createPrintln :: b.stats, b.expr)
case t => Block(createPrintln, t)
}
override def transform(tree: Tree) = tree match {
case defdef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
treeCopy.DefDef(defdef, mods, name, tparams, vparamss, tpt, addPrintln(rhs))
case t => super.transform(t)
}
测试:
scala> def createPrintln = Apply(Select(Ident("System.out"), newTermName("println")), List(Literal(Constant("foo"))))
createPrintln: reflect.runtime.universe.Apply
scala> def addPrintln(t: Tree): Block = t match {
| case b :Block => treeCopy.Block(b, createPrintln :: b.stats, b.expr)
| case t => Block(createPrintln, t)
| }
addPrintln: (t: reflect.runtime.universe.Tree)reflect.runtime.universe.Block
scala> def transform(tree: Tree) = tree match {
| case defdef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
| treeCopy.DefDef(defdef, mods, name, tparams, vparamss, tpt, addPrintln(rhs))
| }
transform: (tree: reflect.runtime.universe.Tree)reflect.runtime.universe.DefDef
scala> val defdef = reify { def foo = { true } }.tree match { case Block(List(defdef), _) => defdef }
defdef: reflect.runtime.universe.Tree = def foo = true
scala> transform(defdef )
res0: reflect.runtime.universe.DefDef =
def foo = {
System.out.println("foo");
true
}
<强> UPD:强>
super.transform
调用父实现。有关代码,请参阅internal implementation。