Sagittariusはマクロ展開フェーズなんてまどろっこしいものを持たないのだが、なんとかしてそれっぽくエミュレートできないかということちょっと知恵を搾り出し中(正直、搾取しすぎて搾りかすしか出ないが・・・)。とりあえず、library内のtoplevelなdefine-syntaxについては強引に先にやってしまうおう的に解決。
問題になってくるのは局所マクロである。
R6RSでは以下のようなコードが動かないといけない。
(import (rnrs))
(let ()
(define-syntax define-inline
(syntax-rules ()
((_ (name . args) body ...)
(define-syntax name
(syntax-rules ()
((_ . args)
(begin body ...)))))))
(define (puts args) (display args) (newline))
(define-inline (print args) (puts args))
(print "abc"))
;; abcを表示
(let ()
(define-syntax define-inline
(syntax-rules ()
((_ (name . args) body ...)
(define-syntax name
(syntax-rules ()
((_ . args)
(begin body ...)))))))
(define-inline (print args) (puts args))
(define (puts args) (display args) (newline))
(print "abcde"))
;; abcdeを表示
最初のパターンは何とか(そこそこスマートに)解決できたんだけど、次のパターンのうまい方法が思いつかない。起きていることそしては、define-inlineで展開されたprintはputsが内部defineとして保持される前にコンパイルされる。そうするとprintのマクロ展開器はputsが内部defineだと知らないので展開器は特に環境情報を付加することなくシンボルputsを識別子に変換する。っで、コンパイラは何も持ってない識別子を大域変数と解釈しコンパイルする。
コンパイラが上記のputs識別子から内部defineのputsを参照できればいいのだが、本当に何の情報も持っていない識別子の参照を許すとマクロのhygieneを壊してしまうのでうかつなことはできない。さて、どうしたものか・・・
No comments:
Post a Comment