Grass言語用アセンブラ

昔書いたGrass言語用アセンブラwwww in Ruby*1


http://codepad.org/mSVlTFg3


easyGrass.rbという名前で保存して、test.egというファイルにDSLを書いて

 ./easyGrass.rb test.eg

のように渡すと、Grass言語に変換されます。

仕様wwww

関数定義は defun というメソッドに関数名と引数名を指定して、ブロック内に処理を書く感じ。例えば

 defun(:hoge, :arg1, :arg2) {
   out[arg1]
   x = succ[succ[arg2]]
   out[x]
 }

定義した関数の呼び出し(関数適用)は

関数名[引数1, 引数2, ..]

という感じ。もちろん

関数名[引数1][引数2]

とか

x = 関数名[引数1] ; x[引数2]

でも同じ(Curry化)。

defunしたものなら「 関数名(引数1, ..) 」でも呼び出せるけど、関数を返す関数から受け取って変数に代入した場合は[]でないとうまく行かない*2


初期環境にあるプリミティブは [:out, :succ, :w, :inp] という名前です*3


おまけ機能で

defineY

というメソッドをソース中から呼び出すと、その場所にYコンビネータを"y"という名前で定義してくれます。

例えば ASCII文字0-255の文字コードを(wから)ずらっと一周表示するソースだと、再帰のためにYコンビネータを使って

defun(:loop0, :f, :x) {
	out[x]
	nx = succ[x]       # nx = x+1
	w[nx, w, f, nx]    # if (nx==w) then w(nx) else f(nx)
}

defineY
y[loop0,w]

とか書けます。

*1:アセンブラというかGrass言語を吐くDSLというか。

*2:method_missingを使っているため。

*3:それぞれ1文字出力、次を返す、wという文字 & wかどうか判定、1文字入力