2009-12-26 72 views
12

我说“实时代码”,因为我的意思不是来自文本源文件或源字符串,而是来自partialFunctions/lambda。 (我知道ruby1.8的的分析树和C#LINQ可以做到这一点)我可以从实时scala代码获取AST吗?

考虑partialFunction F:

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

我希望有一些工具的工作原理是这样的:

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

我不不关心语义的事情(上下文解析和隐含过于复杂,对我来说不必要),我只需要从实时代码中得到语法树,这有可能吗?

检查其他人的代码可能存在问题,但我自己的代码呢?下列事情可能吗?

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

这似乎需要一些黑客到编译器,hmmmm ...

回答

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))))))) 

这是否有助于或不...你可能要检查米格尔·加西亚的“The Scala Compiler Corner”。

相关问题