views:

298

answers:

3

There are a few resources on the web that are instructive in writing Scala compiler plugins that pattern-match against the code, but these don't help in generating code (constructing symbol trees). Where should I start to figure out how to do this? (If there's an easier way than to manually build symbol trees, I'd be interested as well.)

For instance, I'd like write a plugin that replaces some code with a simple AST for this expression, where the variables (extracted from the original program code) could be of any type:

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

I realize this may be tricky because of boxing and toString, e.g. if hello were an object and world were an int, this should really be something like:

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

I don't know the answer to your question, but Miguel Garcia has put together the Scala Compiler Corner which is probably the best available compilation of resources about the Scala compiler.

Jorge Ortiz
Interesting link, thanks for that. Unfortunately, it doesn't seem to be instructive on constructing ASTs.
Yang
+3  A: 

If you generate the tree before the erasure compiler phase, you can type hello and world with Any, and call toString on them.

 ~: 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))
  }
}
retronym
Thanks for the reply, but this doesn't really tell me how to generate an AST.
Yang
+2  A: 

you might find something in this project: http://github.com/scala-incubator/autoproxy-plugin

King Cub