Let's start Scheme

2011-06-18

ぐぬぬ

syntax-rulesが遅いのでsyntax-caseで実装したものを試してみたら、動かない。いや、動くんだけど、正しく動かない。
その理由も分かったのだが、解決できる気がしない・・・

理由は分かれば単純なのだが、例えばこんなの。
;; testはR6RSテストスイートのマクロ
(test (let ((x 'outer))
   (let-syntax ((m (syntax-rules () ((m) x))))
     (let ((x 'inner))
       (m))))
 'outer)
これは割りと典型的な例で、マクロの中でマクロを生成すると起きる。(実は違うかもしれない)
この例だと(m)が返す値はouterじゃないとまずいのだけど、innerの方を返す。何故か?
syntax-caseがパターンとテンプレートをコンパイルする際にすべてのシンボルを識別子へと変換する。その際に、すべてのxが同一の識別子に変換されるので、let-syntax内にあるxとinnerそ束縛しているxが同一のものになってしまう。
これを回避するうまい方法が思いつかない。マクロの展開フェーズとコンパイルのフェーズが分かれていれば、マクロを展開する際に使用する環境やらマクロ展開フェーズやらがいろいろ知っていればいいのだが、現状の実装ではletが変数を束縛するということを知っているのはletに束縛された構文オブジェクトだけなんだよね。
また、マクロを展開してからコンパイルするわけではないので、マクロ展開中に変数束縛を作るマクロが出現した際に結局おかしくなる。
こうなってくると僕の足りない脳みそでが悲鳴を上げてくる。
現在の実装はYpsilonのものをSagittariusでも動くように適当にいじったものだが、根本的な理解をしていなかったため結構穴がある(例えば上記のものとか)。
この穴をふさぐためには実装のしなおしだろうか?しかし、そもそも今のモデルで上記のような問題を解決できるのだろうか?

・・・

考えるか・・・

No comments:

Post a Comment