12

「ライブ コード」と言ったのは、テキスト ソース ファイルやソース文字列からではなく、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'))

セマンティックなことは気にしません (コンテキストの解析と暗黙は複雑すぎて、私には不必要です)。ライブ コードから構文ツリーが必要なだけです。それは可能ですか?

他の人のコードを検査すると問題が発生する可能性がありますが、自分のコードはどうでしょうか? 以下のことは可能ですか?

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

コンパイラへのハッキングが必要なようです、うーん...

4

1 に答える 1

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」を確認してください。

于 2009-12-26T16:05:05.470 に答える