Let's start Scheme

2011-02-18

syntax-caseをexplicit renaming macroで実装するには

どうしたらいいのだろう?

自前の処理系にはer-macro-transformerがある。というか、R6RSに準拠することをとりあえずの目標にしているのだが、syntax-caseを実装するのが(個人的に)無理だったので、(まぁ、psyntaxとか他のexpanderに頼ってもよかったのだが)、とりあえず、explicit renaming macroを実装して、それを使ってsyntax-caseを実装するという手をとろうと考えたわけだ。
正直、ここまでは悪くない手だと自分では思っている。Gaucheの川合史朗さんのBlogのエントリーにsyntax-case、explicit renaming macro、それ以外の衛生的マクロ(Syntactic Closureとか)のどれか一つがあれば他のマクロはポータルに実装できるとあるので、後はその実装だけかなぁとは思ってたりするのだが、いかんせん頭が足りない。
Chibi schemeにer-macro-transformerを使ったsyntax-rulesの実装があってそれをとりあえず走らせて見たのだが、どうも動きがおかしい。
例えば、以下のコード
(define-syntax test
  (syntax-rules ()
    ((_ o)
     (display o)
     (test)
    ((_)
     (newline))))
(test 'a)
(今ちょっと思い出して書いただけなので、間違いがあるかも)、通常のsyntax-rulesなら実行結果は単に「a」と改行をプリントするのだが、Chibi scheme由来のsyntax-rulesを自前の処理系で走らせると、「unbound variable o」となる。
実際、VMのインストラクションを吐かせてみたら、
;; 略
GREF_PUSH o          ;; グローバル変数oに束縛された値をスタックに積む 
GREF_CALL(1) display ;; displayをコール
;; 略
なんてことになってて、そりゃ「o」なんてどこにも定義してないからなぁと納得はするのだが、どうしてそうなるのかさっぱり分からない。
マクロを展開を試してみて、途中でこける。途中のどこかがおかしいので空のリストがcarに与えられてこける。
Chibi shcemeのsyntax-ruleの基本的な感じとしては、(まじめに追ってないので本当に感じ「feeling」だけだが)、er-macro-transformerでer-macro-transformerを作るといった処理に見える。
あれ、ちょっとまてよ、もしそうだとした、こんな感じのマクロが
;; something-macroは別のとこで定義
(define-syntax a
  (something-macro ()
    ((_) (do-something))))
こんな感じに
(define-syntax a
  (er-macro-transformer
    (lambda (form rename compare)
      ;; パターンマッチングの処理とかがあって、最終的に
      ;; これ↓を呼ぶ
      (do-something))))
展開されるということか?
でも、自前の処理系だと、マクロの展開は、マクロのコンパイル → コンパイルされたコードの適用 → 展開されたコードのコンパイル、という実行順序なので、2段階コンパイルされるということになる。1段階目でコンパイルされた時は参照(というか変数?)だったシンボルが、2段階目では変数として扱われてるということかな。
なんかちょっと見えてきたかも。試してみよう。

No comments:

Post a Comment