我在哪里可以学习构buildAST的Scalamacros?

在哪里我可以学习如何构buildScala的macros生成的AST?

Scaladoc没有我想要的那么有帮助。 例如:

abstract def Apply(sym: Universe.Symbol, args: Universe.Tree*): Universe.Tree A factory method for Apply nodes. 

但是,我怎么知道一个Apply节点是什么? 我在哪里可以findAST的节点types列表,以及它们如何组合在一起?

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

Mirko Stocker撰写了关于Scala重构的硕士论文 。 在附录D(p。95)中,他描述了AST的架构。 它还包括一个graphics化的概述:

斯卡拉AST

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

如果需要了解特定的源代码片段是如何在内部表示的,则需要具体化:

 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(()))) 

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

这是我通常做的。 我写了一个名为parse的简单脚本,它将Scala代码作为参数,然后使用-Xprint:parser -Ystop-after:parser -Yshow-trees-stringified -Yshow-trees-compact编译它( parse使用另一个助手脚本: adhoc-scalac 。 点击这里查看它的来源以及)。

这种方法比showRaw优势,它不需要代码进行types检查。 您可以编写一小段代码,它指向不存在的variables或类,它仍然会成功运行并向您显示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)))))))) 

还有一个叫typecheck的脚本,它也是一样的,但是在typer后停下来。 这对于理解typechecker如何转换parsing器树有时很有用。 但是,工具箱和macros都使用parsing器树,所以我很less使用typecheck进行树构build。