Где я могу узнать о создании AST для макросов Scala?

Где я могу узнать, как создать AST, генерируемые макросами Scala?

Скаладок не так полезен, как хотелось бы. Например:

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

Но как мне понять, что такое узел «Применить»? Где я могу найти список типов узлов в AST и как они сочетаются друг с другом?


person Bill    schedule 09.02.2013    source источник


Ответы (2)


Документации по внутреннему устройству компилятора не так много, но того, что есть, должно быть достаточно для начала.

Мирко Стокер написал свой Магистерская диссертация по рефакторингу Scala. В Приложении D (стр. 95) он описывает архитектуру AST. Он также включает графический обзор:

Scala AST

Другой способ найти информацию об AST - это посмотреть прямо в источники identify.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(())))
person kiritsuku    schedule 09.02.2013
comment
Спасибо! Этот тезис - отличный ресурс. - person Bill; 10.02.2013
comment
Как мы можем нарисовать такой график? - person Freewind; 28.02.2015

Вы можете взглянуть на файл 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. Иногда бывает полезно понять, как именно проверка типов преобразует деревья синтаксического анализатора. Однако и наборы инструментов, и макросы работают с деревьями синтаксического анализатора, поэтому я очень редко использую typecheck для построения дерева.

person Eugene Burmako    schedule 10.02.2013
comment
Спасибо, Евгений! Призыв скаляра очень помогает. - person Bill; 12.02.2013