我可以从实时scala代码中获取AST吗?

时间:2009-12-26 08:39:54

标签: scala abstract-syntax-tree

我说“实时代码”因为我的意思不是来自文本源文件或源字符串,而是来自partialFunctions / lambdas。 (我知道Ruby1.8的parseTree和C#linq可以做到)

考虑一个partialFunction f:

val f = (i: Int, j: Int) => (i + j) * 2

我希望有一些工具可以这样:

getBodyAstFrom(f) //=> (Infix('*'), (Infix('+'), Id('i'), Id('j')), Val('2'))

我不关心语义事物(上下文解析和implicits太复杂,对我来说不必要),我只需要实时代码的语法树,是否可能?

检查其他人的代码可能存在问题,但我自己的代码呢?以下是否可能?

val f = AstFunction(i: Int, j: Int){(i + j) * 2}
f(5, 6) //=> 22
f.ast   //=> (Infix('*'), (Infix('+'), Id('i'), Id('j')), Val('2'))

似乎需要对编译器进行一些攻击,嗯......

1 个答案:

答案 0 :(得分:17)

编译器本身是一个可以调用的库。事实上,这就是REPL的工作方式。但是,虽然您可以获取树(在不同阶段)获取一串代码,但您无法获得编译代码。

当然,除非你使用的实验性内容随时都可以改变或者只是停止存在。在这种情况下,您可以尝试:

scala.reflect.Code.lift(f).tree

得到:

res17: scala.reflect.Tree = Select(Select(Select(Ident(Field(line26$object,PrefixedType(ThisType(RootSymbol),Class(line26$object)))),Field($iw,PrefixedType(ThisType(Class(line26$object)),Class($iw)))),Field($iw,PrefixedType(ThisType(Class($iw)),Class($iw)))),Method(f,PolyType(List(),List(),AppliedType(PrefixedType(ThisType(Class(scala)),Class(scala.Function2)),List(PrefixedType(ThisType(Class(scala)),Class(scala.Int)), PrefixedType(ThisType(Class(scala)),Class(scala.Int)), PrefixedType(ThisType(Class(scala)),Class(scala.Int)))))))

这是否有帮助......您可能想查看Miguel Garcia的“The Scala Compiler Corner”。