我说“实时代码”因为我的意思不是来自文本源文件或源字符串,而是来自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'))
似乎需要对编译器进行一些攻击,嗯......
答案 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”。