;; from: http://marcomaggi.github.io/weblog/2015-February-16.html#fn-2 #!r6rs (import (rnrs)) (define (fun) (mac)) (fun) (define-syntax mac (syntax-rules () ((_) (begin (display 123) (newline) (flush-output-port (current-output-port))))))原因は分かっている。Sagittariusではスクリプトとして読まれたファイルは全て読まれた順に評価されるが、R6RSは「全て読み込んでマクロを展開してから実行しろ」という風に定めている。ちなみに0.6.2(か0.6.1からだっか)からは
begin
で囲むと動く。ついでに、library
フォームの中でも動く。このケースであればオプションを追加してそのオプションが指定された場合は一度ファイルを全部読み取って何かしらで包んでやればよいということになる。begin
ではまずいのでそれように何か足してやる必要はある。考えているのはAndre van Tonderの展開器で使われているprogram
とか。じゃあ、それを入れればいいじゃん?という話になるのだが、話はそんなに簡単でもない。現状ではトップレベルで定義された
define-syntax
のコンパイル及びトップレベルのマクロの展開しかしない。つまり、let(rec)-syntax
を用いてトップレベルに定義されるマクロは展開されないのである。つまり、これはbegin
で包んでやっても動かない。
#!r6rs (import (rnrs)) (define (fun) (mac)) (fun) (let-syntax () (define-syntax mac (syntax-rules () ((_) (begin (display 123) (newline) (flush-output-port (current-output-port)))))))これも
let(rec)-syntax
で定義されているマクロを評価してやればいいじゃん?と思うかもしれないが、話はそんなに簡単でもない。この例であれば動くのだが、例えば内側にdefine
があって、その中で局所マクロが使われていた場合に困る。と、ここまで書いて案が浮かんできた。問題になるのは、局所マクロの評価をした後に
define
がコンパイルされない(すると問題になる)という部分だったのだが、ライブラリ及びトップレベルのbegin
展開時に対応するコンパイル時環境を式に保持させればちょっとした手間でいけるような気がしてきた(現状よりさらにメモリを喰うようになるのが気になるが・・・)。ちょっと頑張ってみようかな。
No comments:
Post a Comment