Skip to content

Instantly share code, notes, and snippets.

@yujiorama
Last active December 17, 2015 05:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yujiorama/5558689 to your computer and use it in GitHub Desktop.
Save yujiorama/5558689 to your computer and use it in GitHub Desktop.
Compile-time Metaprogramming - AST Transformation (http://docs.codehaus.org/display/GROOVY/Compile-time+Metaprogramming+-+AST+Transformations) 勝手訳です。

AST 変換

新たなフィーチャーを実装するために Groovy の構文を拡張する、ということがよいアイデアに思えることもある (複数回の代入がいい例だ)。 だけど、ほとんどの場合文法規則にキーワードを追加することはできないし、新しい概念を表現するための構文を作ることもできない。 でも AST 変換を使えば文法規則を変えることなく革新的なアイデアに挑戦することができる。

Groovy コンパイラが Groovy スクリプトや Groovy クラスをコンパイルするとき、ソースコードはいくつかの過程を経てメモリ上に完全構文木 (Concrete Syntax Tree) を構築してそれを抽象構文木 (Abstract Syntax Tree) に変換する。 AST 変換はコンパイルプロセスによって AST がバイトコードに翻訳される前に開発者が介入できるようにするためのものだ。

AST 変換によって非常に柔軟で強力で実行時性能のペナルティの無いコンパイル時メタプログラミングが言語レベルで可能になった。

アノテーション AST 変換

AST 変換はアノテーションで利用できる。 アノテーションによってあなたのクラスがコンパイル時に AST 変換をするための印を付けるのだ。 状況によるがコンパイラフェーズの段階に応じた AST プロセッサが使われる。

次に示す標準的なアノテーションは AST 変換される。

  • Standard Annotations
  • Bindable and Vetoable transformation
  • Building AST Guide
  • Category and Mixin transformations
  • Compiler Phase Guide
  • Delegate transformation
  • Immutable AST Macro
  • Immutable transformation
  • Lazy transformation
  • Newify transformation
  • PackageScope transformation
  • Singleton transformation

Grape は @Grab によって自分自身を変換する。

自分で AST 変換を実装する

変換には 2 種類ある。グローバル変換とローカル変換だ。

グローバル変換はコンパイラがコードをコンパイルする際ならどんな変換も適用される。 コンパイル済みのグローバル変換を実装したクラスとサービスロケーターファイル (META-INF/services/org.codehaus.groovy.transform.ASTTransformation) は、コンパイラのクラスパス上にある JAR ファイルに配置する。 グローバル変換クラスには引数無しのコンストラクタと org.codehaus.groovy.transform.ASTTransformationinterface の実装が必要である。 グローバル変換はそれぞれのソースコードをコンパイルするたびに実行されるので、時間のかかりそうなこと (AST を全てスキャンするなど) はしないのがマナーである。 コンパイラができる限り速く動けるようにしよう。

ローカル変換は局所的なコード辺を対象として適用される。 ローカル変換クラスの実装には他のアノテーションを再利用できる。そして org.codehaus.groovy.transform.ASTTransformation を実装しなければならない。

参照

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment