我在哪里可以了解构建AST的斯卡拉宏?(Where can I learn about constr

2019-07-19 16:27发布

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

该Scaladoc并不像我想的帮助。 例如:

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

但我怎么找出一个应用节点? 我在哪里可以找到AST的节点类型的列表,以及它们是如何结合在一起的?

Answer 1:

没有很多的编译器提供的内部文件,但是可用的东西应该足够上手。

米尔科·斯托克 ,已经写了他的硕士论文约斯卡拉重构 。 在附录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(())))


Answer 2:

你可以看看的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-compactparse使用其他辅助脚本: 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对树构建的目的非常罕见。



文章来源: Where can I learn about constructing AST's for Scala macros?