Gauche:MultiPhaseMacro

Gauche:MultiPhaseMacro

Shiro(2009/02/24 13:51:19 PST):

現在のSchemeマクロのセマンティクスは、 メタプログラミングとして可能な領域の一部しかカバーしてないんじゃないかと もやもや思っているのでアイディアをメモしておく。

Schemeマクロの限界

マクロはトップダウン、あるいは「外から内へ」、あるいはpreorderで 展開が進むことになっている。

(foo (bar x) (baz x))

この式でfooがマクロであった場合、内側のサブフォーム(bar x), (baz x)は手つかずのままfooの 展開ルーチンに渡される。fooの展開ルーチンは(bar x)や(baz x)をそのまま 出力フォームに埋め込むかもしれないし、bar, baz xなどに分解して処理するかもしれない。 (bar x), (baz x)がそのまま出力フォームに埋め込まれた場合、それはfooの展開後に 処理されることになる。

preorderは、サブフォームの構造を変えるマクロ(例:let)を書くのに必要だ。 しかし、preorderはサブフォームを、ソースに与えられた「生の」形でしか見ることができない。 これには次のような欠点がある。

pre-post orderの可能性

preorderで起動される展開ルーチンと、postorderで展開されるルーチンを くっつけておいたら、これらの欠点はカバーできるだろうか。

あーでもメタ情報は一旦木全体を見ないとつけられないのか。 サブツリーを見終わった時点でもまだ訪れてないsibilngがあると メタ情報は確定しないなあ。

結局マルチパス?

そうなると複数パスが必要になるかな。pass1を2つに分ける:

うーん、pass1.2と現在のpass2がやってるのは概念的には同じことかなあ。 しかし、現在のpass2は入力時点で既にソースがコンパイラの内部形式(IForm)に 変換されちゃってるから、マクロのような形で簡単にフックをかけるのは難しい。

pass1.2はpreorderであるべきか、postorderであるべきか。preorderなら 1.2のpostorderでIFormへと変換できる。でも何となく意味的マクロ展開は postorderの方がいろいろできそうな気がする。だがそうなると1.2の出力を さらにIFormへと変換する必要がある。

いっそのことIFormをannotated S-exprの形にしちゃったら、 1.2と2を融合してpass3まで持ってける? むむむ。

資料

Typed Schemeの実装ではlocal-expandでマクロ展開ルーチンがサブフォームの 展開を部分的にキックしているようだ: http://www.ccs.neu.edu/scheme/pubs/scheme2007-ctf.pdf

More ...