从Scala编译器插件生成Scala代码树

Yan*_*ang 7 compiler-construction plugins code-generation scala

这里有一些 资源是书面的Scala编译器插件对代码模式匹配启发在网络上,但这些并不在生成代码(构建符号树)帮助.我应该在哪里开始弄清楚如何做到这一点?(如果有一种比手动构建符号树更简单的方法,我也会感兴趣.)

例如,我想编写一个插件,用这个表达式的简单AST替换一些代码,其中变量(从原始程序代码中提取)可以是任何类型:

"" + hello + ", " + world + "!"
Run Code Online (Sandbox Code Playgroud)

我意识到这可能是棘手的,因为拳击toString,例如,如果 hello是一个对象,并且world是一个int,这应该是这样的:

"".+(hello.toString().+(", ".+(new Integer(world).toString().+("!"))))
Run Code Online (Sandbox Code Playgroud)

ret*_*nym 3

如果您在编译器阶段之前生成树erasure,则可以键入helloand worldwith Any,然后调用toString它们。

 ~: cat test.scala 
object test {
  def f(hello: Any, world: Any) = "" + hello + ", " + world + "!"
  f("1", "2")
  f(1, 1)
}
 ~: scalac -Xprint:typer test.scala 
[[syntax trees at end of typer]]// Scala source: test.scala
package <empty> {
  final object test extends java.lang.Object with ScalaObject {
    def this(): object test = {
      test.super.this();
      ()
    };
    def f(hello: Any, world: Any): java.lang.String = "".+(hello).+(", ").+(world).+("!");
    test.this.f("1", "2");
    test.this.f(1, 1)
  }
}

~: scalac -Xprint:erasure test.scala 
[[syntax trees at end of erasure]]// Scala source: test.scala
package <empty> {
  final class test extends java.lang.Object with ScalaObject {
    def this(): object test = {
      test.super.this();
      ()
    };
    def f(hello: java.lang.Object, world: java.lang.Object): java.lang.String = "".+(hello).+(", ").+(world).+("!");
    test.this.f("1", "2");
    test.this.f(scala.Int.box(1), scala.Int.box(1))
  }
}
Run Code Online (Sandbox Code Playgroud)