我可以从实时 Scala 代码中获取 AST 吗?

发布于 2024-08-16 06:18:11 字数 631 浏览 6 评论 0原文

我说“实时代码”是因为我的意思不是来自文本源文件或源字符串,而是来自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'))

似乎需要对编译器进行一些修改,嗯......

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

她如夕阳 2024-08-23 06:18:11

编译器本身是一个库,您可以调用它。事实上,这就是 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 的“Scala 编译器角落”。

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".

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文