gpt4 book ai didi

scala - AST 转换对象如何工作?

转载 作者:行者123 更新时间:2023-12-02 05:04:46 25 4
gpt4 key购买 nike

谁能帮我掌握scala中允许ASTs修改的转换对象?

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

例如如果我有这个 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

最佳答案

你原来的看起来像这样:

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
}

更新:

super.transform 调用父实现。参见 internal implementation用于代码。

关于scala - AST 转换对象如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16432588/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com