読者です 読者をやめる 読者になる 読者になる

Haxeの@:buildマクロを使えばコードにDSL混ぜ放題、かも

Haxeではclass宣言の前に@:buildマクロを書けば、class内の関数とかをビルド時に受け取って、その内容を書き換えるマクロが作れる。

なので、こういうインタプリタ作って、

コードを書いて、

package ;
import neko.Lib;
using totsubefu.Interpreter;
@:build(totsubefu.Interpreter.parse(":b"))
class Main {
	function new() {
		hello();
	}
	@:b function hello() {'
v @_       v
>0"!dlroW"v 
v  :#     < 
>" ,olleH" v
   ^       <
	';}
	static function main() {
		Interpreter.setPrint(Lib.print);
		new Main();
	}
}

ビルドして、

% haxe -main Main.hx -neko Main.n
totsubefu/Interpreter.hx:20: 
_人人 人人 人人_
> 突然のBefunge <
 ̄Y^Y^Y^Y^Y^Y^Y ̄

v @_       v
>0"!dlroW"v 
v  :#     < 
>" ,olleH" v
   ^       <
	

実行できる。

% neko Main.n
Hello, World!

今回はBefunge (wikipedia:Befunge)を混ぜた。

マクロ内でContext.getBuildFields()を呼び出せばクラス内の関数などがArrayで取り出せるので、中身を解析して書き換えてArrayを返せば、関数の中身などをビルド時に書き換えることができる。メタプログラミングによるDSL構築の一種。

この仕組みを使いこなせば、例えばHaxeには無いコルーチン的な仕組みを、後付けで無理やり作ったりできる。

ただ、ExprDef (http://haxe.org/api/haxe/macro/exprdef)を見ると分かるけど、Haxeの持ついろんな構文を解析して書き換えるのは結構大変そう。Haxe自体と密結合できるDSLを混ぜ込むのは手間がかかるかも。