Groovy で AST 変換してみた

初めまして、田中と申します。"Groovy" と聞けば、まず「気分はグルービー」という青春漫画を思い出す、そんな世代の人間です。

さて、Groovy ですが、「Gradle を使うために仕方なく覚える言語」と思っていませんか?

私は、古いシステムの改修の一環として Ant を Gradle に置き換えることになり、最近 Groovy を使い始めたのですが、当初はそのように思っていました。しかし、実際に使ってみると、結構便利だし、なかなか興味深い言語だと感じます。とりわけ、すごいと思ったのが「AST 変換」です。

AST 変換とは

Groovy のコードは、最終的には Java バイトコードに変換されますが、ソースコードからいきなりバイトコードに変換されるわけではなく、まず文法構造をツリー形式で表した AST (Abstract Syntax Tree:抽象構文木) と呼ばる中間表現が作成されます。この AST を操作してプログラムの構造を書き換えるのが AST 変換です。

AST 変換はコンパイル時に行われるので実行時にオーバーヘッドがかからないというメリットがあります。

Groovy の AST 変換には「グローバル AST 変換」と「ローカル AST 変換」があります。プログラム全体を対象とするのがグローバル AST 変換、アノテーションを付けた要素だけを対象とするのがローカル AST 変換です。

ローカル AST 変換のためのアノテーションは、Groovy の API に標準で含まれています。例えば、アノテーション @Singleton ですが、

クラスに付けるだけで AST 変換が行われ、そのクラスの唯一のインスタンスがフィールド instance に格納され、new でインスタンスを生成しようとすると RuntimeException が発生するようになります。

やってみた

とにかく、実際にやってみないと良く分からないので、
「メソッドの開始時と終了時に文字列(デフォルトで "ほげほげ" )と出力させる」
だけの全く無意味なローカル AST 変換を行うアノテーションを作成してみました。

まず、アノテーションのクラスです。

● HogeHoge.groovy

AST 変換の実装クラスを指定するメタアノテーション @GroovyASTTransformationClass 以外は、Java で独自アノテーションを作る場合と同じです。
(注:@Target の引数が { } ではなく、[ ] になっているのは、Groovy の文法の都合です。)

次が AST 変換の実装クラスです。

● HogeHogeTransformation.groovy

要するに、AST を探索するメソッド visit をオーバーライドして、アノテーションを付けたメソッドを表すノードの前後に「println 文字列」というコードを表すノードを挿入しているだけです。

以上です。では、試してみましょう。

● HogeHogeExample.groovy

【実行結果】 (Groovy 2.3.0,  CentOS7)

(注:AST 変換の実行時に HogeHoge.class と HogeHogeTransformation.class が作成されている必要があるので、予め groovyc でコンパイルしています。)

Compile Phase

上記プログラム中の CompilePhase.SEMANTIC_ANALYSIS について解説しておきます。

Groovy のコンパイルは 9 段階(phase)で実行され、それぞれの段階を指定するための Enum 型 CompilePhase が用意されています。

① INITIALIZATION (初期化)
② PARSING (構文解析)
③ CONVERSION (変換)
④ SEMANTIC_ANALYSIS (意味解析)
⑤ CANONICALIZATION (正規化)
⑥ INSTRUCTION_SELECTION (命令選択)
⑦ CLASS_GENERATION (クラス生成)
⑧ OUTPUT (出力)
⑨ FINALIZATION (終了)

③ の 「変換」とは、② でソースコードを分解したトークンで作成された構文木(まだ抽象化されていない)を AST に変換する、という意味です。上記プログラムでは、AST ができた後の状態に介入するので、③ の次の ④ SEMANTIC_ANALYSIS を指定している、というわけです。

最後に

なんとなく AST 変換について分かったような気になりました、よね?
勿論、実際に役立ち、かつ安全なコードを書くには、AST の構造についてやコンパイルの詳細について、もっと勉強しなければなりませんが......

現状では今ひとつパッとしない Groovy ですが、実は結構すごいヤツなんだ、ということが分かって頂ければ幸いです。

尚、以下を参考にさせて頂きました。
http://glaforge.appspot.com/article/groovy-ast-transformations-tutorials で紹介されている記事
・関谷和愛・上原潤二・須江信洋・中野靖治 (2011)『プログラミングGROOVY』技術評論社

Comments are closed, but you can leave a trackback: Trackback URL.