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

lui*_*ore 12 scala abstract-syntax-tree

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

考虑一个partialFunction f:

val f = (i: Int, j: Int) => (i + j) * 2
Run Code Online (Sandbox Code Playgroud)

我希望有一些工具像这样:

getBodyAstFrom(f) //=> (Infix('*'), (Infix('+'), Id('i'), Id('j')), Val('2'))
Run Code Online (Sandbox Code Playgroud)

我不关心语义事物(上下文解析和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'))
Run Code Online (Sandbox Code Playgroud)

它似乎需要一些黑客入侵编译器,嗯......

Dan*_*ral 17

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

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

scala.reflect.Code.lift(f).tree
Run Code Online (Sandbox Code Playgroud)

得到:

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)))))))
Run Code Online (Sandbox Code Playgroud)

是否有帮助......您可能想查看Miguel Garcia的" The Scala Compiler Corner ".