views:

330

answers:

1

I said "live code" because I mean not from text source files or source strings, but from partialFunctions / lambdas. (I know Ruby1.8's parseTree and C# linq can do it)

consider a partialFunction f:

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

I hope there is some tool works like this:

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

I don't care the semantic things (context parsing and implicits are too complex, and unnecessary for me), I just need the syntax tree from live code, is it possible?

There may be issues with inspecting other people's code, but what about my own code? Is the following things possible?

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

It seems to need some hacking into the compiler, hmmmm...

+11  A: 

The compiler itself is a library, which you can call. That's how REPL works, in fact. But while you can get the tree (at various stages) for a string of code, you can't get it for compiled code.

Except, of course, if you use experimental stuff that can change at any moment or simply cease to exist. In that case, you can try:

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

And get:

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

Whether that helps or not... You may want to check Miguel Garcia's "The Scala Compiler Corner".

Daniel