Let's start Scheme

2011-04-14

syntax-case再び

RacketのR6RS Test Suiteを導入しようと思ったらテストを実行するのにレコードが必要で、レコードはdefine-record-typeなんてので定義されてて、その定義にはsyntax-caseが必要っぽいので再びチャレンジすることにした。
(長い一文だ)

とりあえず気づいたことというか、これはひどいなぁと思ったことについて。
R6RSの仕様書的にはsyntax-caseはライブラリであると明記されているのに、コンパイラにマクロ展開のタイミングを強制すること。たとえばこんなコード。
(define-syntax test
  (lambda (x)
    (define (hoge x) (syntax-case x () ...))  ;; (2)
    (syntax-case x () ;; (1)
      ((_ x)
       (hoge #'x)))))
これで何がおきてほしいかというと、(1)のsyntax-caseはxがパターンマッチにマッチしたら、(2)のdefineを呼ぶ必要がある。でhogeが構文オブジェクトを返して、コンパイラはその構文オブジェクトをコンパイルする。
でも、hogeを呼び出すためにはコンパイラがすでに内部defineをコンパイルしている必要がある。

あぁ、でももう少し考えればいけそうな気がしてきたなぁ。
問題は現状では構文オブジェクトを返してもコンパイラはそいつをコンパイルしてくれないことか。

ちょっと気づいたことメモ。
(syntax x)とした際に、環境を捕捉する必要がありそうだ。
結局上の式は、
(define-syntax test
  (lambda (x)
    (define (hoge x) (let ((expr x)) ...)) ;; something
    (let ((expr x))
      (if (match? x)
          (hoge (syntax x))))))
こんな感じに展開されればいいのか。(まぁ、実際にはhogeはletrecな何かだろうけど)

No comments:

Post a Comment