Compile Time Grass to D CompilerでGrassを実行可能バイナリにコンパイル
みどりの日恒例 Grass Hackathon (2年ぶり2回目、そして記事は2日遅れ)
D言語版のGrassインタプリタと、コンパイル時にGrassコードをD言語に変換し、結果をmixinするという流れでGrassを実行可能バイナリにコンパイルするモノを作ってみました。
https://github.com/youz/grasses/tree/master/D
grass.dが普通のインタプリタ、grassctc.d がコンパイル時Grass to Dコンパイラです。
grassctc.d コンパイル方法
grassのコードを"source.grass"というファイル名でgrassctc.dと同じ場所に保存して以下のコマンドでコンパイルします。
$ dmd -J. -of実行ファイル名 grassctc.d
あるいはwindowsならgrassc.bat, linux&Mac(or msys)ならgrassc(シェルスクリプト)にgrassファイルを渡せば良きに計らってくれます。
また、-pオプションを付けて呼び出すとstderrに変換結果を表示しつつコンパイルします。
$ cat w.grass wWWwwww $ path/to/grassc -p w.grass (new F(delegate V(V f1) { return f1(f1); }))(new F(delegate V(V f0) { return writer(w); })); $ ./w.exe w
変換サンプル
wwWWwWWWwvWwWwWwwwwWwwwwwww
↓
(new F(delegate V(V f3) { return (new F(delegate V(V f4) { return (new F(delegate V(V f5) { return (new F(delegate V(V f6) { return (new F(delegate V(V f7) { return f7(f7); }))(f6(w)); }))(f5(writer)); }))(f4(f4)); }))(f3(f3)); }))(new F(delegate V(V f0) { return new F(delegate V(V f1) { return (new F(delegate V(V f2) { return f0(f2); }))(f0(f1)); }); }));
wwWWWWwWwwwWwwwWwwwvwwWWwWWWwvWwWwvwWWWWWwWWWwWwwwvwvWwwwwwWwwwWWwWWWwWWWWWWWWwWWWWWWwwwwwwwwwwwwwwWWWWWWWWwWWWWWwWWWWWwwwWWWWWWwwwWWWWWWWWWwWWWWWWWWWWwwwWWWWWWWWWwWWWWWWWWWWwwwWWWWWWWWWWwwwwWWWWWWWWWWWWWwWWWWWWWWWWWWwwWWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWWWWWWWWWWWWWwvwWWWWWWWWWWWWWWWWWWWWWWWWWWWWwvWwwwwwwWWwwwwwwwwwwWWWwwwwwwwwwwwwwWWWWwWWWWWwwwwwwwwwwwwwwwwwWWWWWWwwwwwwwwwwWWWWWWWwwwwwwwwwvwWWWWWWWWWwvWwwwwwwwwwwwwwwwwwwwwwwwwWWwwwwwwwwwwwwwwwwwwwwwwWWWwwwwwwwwwwwwwwwwwwwwwwwwWWWWwwwwwwwwWWWWWwwwwwwwwwwwwwwwwwwwwWWWWWWwwwwwwwwwwwwwww
↓
(new F(delegate V(V f5) { return (new F(delegate V(V f9) { return (new F(delegate V(V f10) { return (new F(delegate V(V f11) { return (new F(delegate V(V f15) { return (new F(delegate V(V f17) { return (new F(delegate V(V f18) { return (new F(delegate V(V f19) { return (new F(delegate V(V f20) { return (new F(delegate V(V f21) { return (new F(delegate V(V f22) { return (new F(delegate V(V f23) { return (new F(delegate V(V f24) { return (new F(delegate V(V f25) { return (new F(delegate V(V f26) { return (new F(delegate V(V f27) { return (new F(delegate V(V f28) { return (new F(delegate V(V f29) { return (new F(delegate V(V f30) { return (new F(delegate V(V f31) { return (new F(delegate V(V f32) { return (new F(delegate V(V f33) { return (new F(delegate V(V f34) { return (new F(delegate V(V f35) { return (new F(delegate V(V f36) { return (new F(delegate V(V f37) { return (new F(delegate V(V f39) { return (new F(delegate V(V f40) { return (new F(delegate V(V f41) { return (new F(delegate V(V f42) { return (new F(delegate V(V f43) { return (new F(delegate V(V f44) { return (new F(delegate V(V f45) { return (new F(delegate V(V f46) { return (new F(delegate V(V f48) { return (new F(delegate V(V f49) { return (new F(delegate V(V f50) { return (new F(delegate V(V f51) { return (new F(delegate V(V f52) { return (new F(delegate V(V f53) { return (new F(delegate V(V f54) { return f54(f54); }))(f48(f37)); }))(f48(f31)); }))(f48(f43)); }))(f48(f25)); }))(f48(f26)); }))(f48(f23)); }))(new F(delegate V(V f47) { return f39(f47); })); }))(f39(f36)); }))(f39(f34)); }))(f39(f26)); }))(f39(f42)); }))(f39(f28)); }))(f39(f30)); }))(f39(f33)); }))(new F(delegate V(V f38) { return writer(f38); })); }))(succ(f36)); }))(f21(f35)); }))(f20(f34)); }))(f22(f32)); }))(f20(f32)); }))(f22(f28)); }))(f21(f28)); }))(f21(f29)); }))(f19(f26)); }))(f19(f27)); }))(f21(f24)); }))(f21(f23)); }))(f20(f24)); }))(f15(f23)); }))(f17(w)); }))(f10(f21)); }))(f18(f20)); }))(f18(f19)); }))(f18(f15)); }))(f17(f9)); }))(new F(delegate V(V f16) { return f16; })); }))(new F(delegate V(V f12) { return (new F(delegate V(V f13) { return (new F(delegate V(V f14) { return f14(f12); }))(f11(f13)); }))(f5(f12)); })); }))(f10(f10)); }))(f9(f9)); }))(new F(delegate V(V f6) { return new F(delegate V(V f7) { return (new F(delegate V(V f8) { return f6(f8); }))(f6(f7)); }); })); }))(new F(delegate V(V f0) { return new F(delegate V(V f1) { return (new F(delegate V(V f2) { return (new F(delegate V(V f3) { return (new F(delegate V(V f4) { return f4(f2); }))(f3(f1)); }))(f2(f0)); }))(succ(f1)); }); }));
ベンチマーク
wを (2^2)^(3^2) = 262144回succした結果を印字するコードでインタプリタとコンパイルした奴の速度を比較してみる。
$ cat 262144.grass wwWWwWWWwvwwWWwWWWwWWWWwvWWwwWWWwwWwwWwwwwwwwWwwwwwwwwwWWWWWWWWw $ time grass.exe 262144.grass w real 0m0.520s user 0m0.015s sys 0m0.000s $ grassc 262144.grass $ time ./262144.exe w real 0m0.265s user 0m0.015s sys 0m0.046s
もうちょっと重い処理をさせてみたいけど簡単に書ける重いコードってのがなかなか難しい…