我在哪里可以学习如何构建AST的Scala的宏产生?
该Scaladoc并不像我想的帮助。 例如:
abstract def Apply(sym: Universe.Symbol, args: Universe.Tree*): Universe.Tree
A factory method for Apply nodes.
但我怎么找出一个应用节点? 我在哪里可以找到AST的节点类型的列表,以及它们是如何结合在一起的?
我在哪里可以学习如何构建AST的Scala的宏产生?
该Scaladoc并不像我想的帮助。 例如:
abstract def Apply(sym: Universe.Symbol, args: Universe.Tree*): Universe.Tree
A factory method for Apply nodes.
但我怎么找出一个应用节点? 我在哪里可以找到AST的节点类型的列表,以及它们是如何结合在一起的?
没有很多的编译器提供的内部文件,但是可用的东西应该足够上手。
米尔科·斯托克 ,已经写了他的硕士论文约斯卡拉重构 。 在附录d(第95页)他所描述的AST的结构。 它还包括一个图形概览:
查找有关AST信息的另一种方式是直视来源reflect.internal.Trees ,其中包含了AST。
如果一个人需要找出一个特定的源代码片段是如何表示内部有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(())))
你可以看看的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))))))))
还有一个叫脚本typecheck
,这不相同,但后停止typer
。 这有时是有用的了解typechecker究竟是如何转变的解析器树。 但是,这两个工具箱和宏与解析器树工作,所以我使用typecheck
对树构建的目的非常罕见。