Scalaでは、コンパイル時に独自の処理を走らせることができて、この機構をCompiler Pluginとして提供しています。
クイックスタートは本家サイトにのっていて、すぐに試せると思います。
Writing Scala Compiler Plugins
のように、ゼロでの割り算をコンパイル時にエラー検出するプラグインを作るには、DivByZero.scalaをコンパイルして、
と一緒にjarして、
とやると、該当行がコンパイルエラーになる。というもの。このとおりやってみると動きます。プラグインがうまくインストールできてるか確認するには、次のようにします。
※continuationsは、scala2.8のデフォルトプラグインのようです。
何をやるものかは、Onion開発しつつ、PEGEXを開発する日記:限定継続を実現するScalaコンパイラプラグインを試してみるに説明がありました。
DivByZeroの形がCompiler Pluginの定型のようで、
コンパイルフェーズは、以下のコマンドで出力されるいずれかの値です。
プラグインは、これらのフェーズに「独自のフェーズを追加する」という考え方になるようです。各フェーズとコンパイラプラグインの関係はこちらにドキュメントがあります。
Scala Compiler Phase and Plug-In Initialization
上記の本家では、"ほんの一例"として
* コンパイル時のチェックを追加したいとき(DivByZeroのように)
* よく使うAPIを最適化したいとき
* Scalaの文法を書き換えたいとき(ただし依存関係など注意してね)
などを挙げています。
■コンパイル時にいろいろチェックをするタイプ
varhunter (Step by step Scala Compiler plug-in)
var(可変変数)を使ったら即アウトにするプラグイン(カッケーw
noboxing-plugin
アノテーションを使ってboxingを検出してくれるプラグイン
Scala Compiler Plugin for Unique References
アノテーションを使って重複参照を排除するプラグイン
■コンパイル時にコードに機能追加するタイプ
autoproxy-plugin
別オブジェクトへプロキシメソッドを自動追加してくれるプラグイン
Nonnull-check generator
パラメータに@Nonnullをつけると、"if( param == null ) throw new Exception" をコードに付与してくれるプラグイン。
■コンパイル時に別のコードを自動生成するタイプ
avro-scala-compiler-plugin
Apache Avro用のシリアライズクラスを生成してくれるプラグイン
s2js
ScalaソースをJavaScriptソースに変換してくれるプラグイン
何に使うんだこれ!?っていうのも正直ありますが、特にNonnull-checkなどは、コンパイラわからない私でも理解しやすかったりして、上記のサンプルのコードを見てみるとなんとかなるかもしれないっという気にはなります。
ちゃんと実装しようと思ったらもちろんコンパイラの生成物を理解しなければならないと思いますが ;x; 、いろいろと用途はありそう。
ちょっと思い立っただけですが、たとえば、
・nullを返してしまう可能性のあるメソッドを検出して警告を挙げる(Optionの利用を促す)。
・自由にコーディングしてしまいがちなScalaでチーム開発する際のルール付けとか、やばそうなコードの検出に使えないかな?
・APTの代替策。
などと想像は膨らみます。
by @ScalaTohoku(thx!)
過去にScalaWatchで以下の plugin がでてきてました。
* ScalaCL Compiler Plugin
for 式や collection の foldLeft 等を while ループに変換する。
* Scala enhanced Strings plugin
文字列中に直接 Scala の式を書けるようにする。
* Beans Scalac Plugin
* a compiler plugin which generates cross-linked HTML files of the source files.