Создание деревьев кода Scala из подключаемого модуля компилятора Scala

Есть несколько ресурсы в Интернете, которые поучительны для написания подключаемых модулей компилятора Scala, которые сопоставляют шаблон с кодом, но не помогают в генерации кода (построении деревьев символов). С чего мне начать разбираться, как это сделать? (Если есть более простой способ, чем создание деревьев символов вручную, мне тоже было бы интересно.)

Например, я хотел бы написать плагин, который заменяет некоторый код простым AST для этого выражения, где переменные (извлеченные из исходного кода программы) могут быть любого типа:

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

Я понимаю, что это может быть сложно из-за бокса и toString, например. если hello был объектом, а world был целым числом, это действительно должно было бы выглядеть примерно так:

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

person Yang    schedule 12.02.2010    source источник
comment
Я не знаю ответа на ваш вопрос, но Мигель Гарсия собрал Scala Compiler Corner, который, вероятно, является лучшей доступной компиляцией ресурсов о компиляторе Scala.   -  person Jorge Ortiz    schedule 12.02.2010


Ответы (3)


Если вы сгенерируете дерево до erasure фазы компиляции, вы можете ввести hello и world с 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))
  }
}
person retronym    schedule 12.02.2010
comment
Спасибо за ответ, но на самом деле это не говорит мне, как сгенерировать AST. - person Yang; 13.02.2010

вы можете найти что-нибудь в этом проекте: http://github.com/scala-incubator/autoproxy-plugin

person BenjaminJackman    schedule 14.02.2010
comment
К сожалению, этот плагин не очень помогал создавать AST. - person Yang; 29.11.2010

Эта цепочка выглядит актуальной: Преобразование Scala AST в исходный код

В частности, вы можете создать Scala AST с упомянутым TreeDSL. http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/compiler/scala/tools/nsc/ast/TreeDSL.html.

person pdxleif    schedule 02.09.2011
comment
Обновление: есть проект, который расширяется на TreeDSL и выглядит вполне пригодным для использования: github.com/eed3si9n/treehugger - person pdxleif; 06.02.2012