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

8

在网络上有一些关于编写Scala编译器插件进行代码模式匹配的资源,但这些并不能帮助生成代码(构造符号树)。我该从哪里开始学习如何做到这一点?(如果有比手动构建符号树更简单的方法,我也很感兴趣。)

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

"" + hello + ", " + world + "!"

我意识到这可能会很棘手,因为涉及到装箱和toString,例如,如果hello是一个对象,而world是一个整数,那么这应该是:

"".+(hello.toString().+(", ".+(new Integer(world).toString().+("!"))))

我不知道你问题的答案,但Miguel Garcia已经整理了Scala Compiler Corner,这可能是关于Scala编译器最好的资源汇编。 - Jorge Ortiz
3个回答

3

如果在erasure编译器阶段之前生成树,则可以使用Any类型键入helloworld,并对它们调用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))
  }
}

谢谢回复,但这并没有真正告诉我如何生成AST。 - Yang

2

不幸的是,这个插件并没有真正教授如何构建AST。 - Yang

1

更新:有一个扩展TreeDSL并且看起来非常可用的项目:https://github.com/eed3si9n/treehugger - pdxleif

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接