我在哪里可以学习为Scala宏构建AST?

Bil*_*ill 39 macros scala scala-macros

在哪里我可以学习如何构建Scala的宏生成的AST?

Scaladoc不像我想的那样有用.例如:

abstract def Apply(sym: Universe.Symbol, args: Universe.Tree*): Universe.Tree
A factory method for Apply nodes.
Run Code Online (Sandbox Code Playgroud)

但是我如何弄清楚Apply节点是什么?我在哪里可以找到AST的节点类型列表,以及它们如何组合在一起?

kir*_*uku 39

可用的编译器内部没有很多文档,但可用的东西应该足以开始.

Mirko Stocker撰写了关于Scala Refactoring的硕士论文.在附录D(第95页)中,他描述了AST的架构.它还包括一个图形概述:

Scala AST

查找AST信息的另一种方法是直接查看包含AST 的reflect.internal.Trees的源代码.

如果需要了解内部如何表示特定的源代码片段,则reify:

scala> import reflect.runtime.universe._
import reflect.runtime.universe._

scala> showRaw(reify{val i = 0}.tree)
res8: String = Block(List(ValDef(Modifiers(), newTermName("i"), TypeTree(),
  Literal(Constant(0)))), Literal(Constant(())))
Run Code Online (Sandbox Code Playgroud)


Eug*_*ako 22

您可以查看scaladoc(http://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html#trees)或幻灯片(http://scalamacros.org/talks/ 2012-04-28-MetaprogrammingInScala210.pdf,"学习学习"部分).

这就是我通常做的事情.我编写了一个名为的简单脚本parse,它将Scala代码作为参数然后编译它-Xprint:parser -Ystop-after:parser -Yshow-trees-stringified -Yshow-trees-compact(parse使用另一个帮助脚本:adhoc-scalac.点击此处查看其源代码).

这种方法的优点showRaw是它不需要代码进行类型检查.您可以编写一小段代码,它引用不存在的变量或类,它仍然会成功运行并向您显示AST.这是输出的一个例子:

09:26 ~$ parse 'class C { def x = 2 }'
[[syntax trees at end of parser]]// Scala source: tmp36sVGp
package <empty> {
  class C extends scala.AnyRef {
    def <init>() = {
      super.<init>();
      ()
    };
    def x = 2
  }
}
PackageDef(Ident(TermName("<empty>")), List(ClassDef(Modifiers(), TypeName("C"), List(), Template(List(Select(Ident(scala), TypeName("AnyRef"))), emptyValDef, List(DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(), Block(List(pendingSuperCall), Literal(Constant(())))), DefDef(Modifiers(), TermName("x"), List(), List(), TypeTree(), Literal(Constant(2))))))))
Run Code Online (Sandbox Code Playgroud)

还有一个名为的脚本typecheck,它也是一样的,但在之后停止typer.这有时候有助于理解typechecker如何转换解析器树.但是,工具箱和宏都使用解析器树,因此我typecheck很少用于树构造.