繁体   English   中英

AST Transformation对象如何工作?

[英]How does AST Transformation object works?

有人可以帮助我掌握可在scala中修改AST的转换对象吗?

网上有很多例子,但是我很难理解递归是如何发生的。

例如,如果我有此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

您原来的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

因此,您应该使用Block(createPrintln, t)替换//Manage functions without block

我猜你的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调用父实现。 有关代码,请参见内部实现

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM