2007-12-14
■ [biwascheme] Syntaxを導入した
マクロ展開を実装した。
例えば (and a b c) を (if a (if b c #f)) に展開するとか。
実装方法は、評価前に式を再帰的に調べて、(and ...) のような呼び出しがあれば 「and」に関連付けられた展開器*1を使ってif文に展開する…という感じ。
このとき注意しないといけないのは、展開結果にさらにマクロが含まれる可能性があるということ(例えばletの中でandを使うとか)。 なので、結果が変化しなくなるまで結果に対してもうマクロ展開を試み続ける必要がある。
関数的にやるなら「展開前の式と展開後の式の構造を再帰的に調べ、同一かどうか判定する」とか、 「展開が起こったかどうかを表すフラグを式といっしょに返す」とかいう手段がありそうだけど、 前者は重そうだし、後者は書くのがめんどくさかったので(笑) 展開が起こったら引数で渡されたフラグオブジェクトを 破壊的に変更することにした。これだと、expand関数に引数を一つ増やすだけなので楽ちん。
この方法でandとorとletを定義した。あとはcaseとかcondとかか。
いずれはSchemeのコードでも展開器を定義できるようにしたい。 それができればdefine-macroが実装できるはず。
*1 今はJavascriptの関数で書いている