2009-12-26 25 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」。

相關問題