(import (rnrs))
(define-syntax foo
(lambda (x)
(syntax-case x ()
((_)
(let ()
;; こいつが問題。syntax-rulesでも起きるけど
;; syntax-caseの方が通常はデバッグが楽なので
(define-syntax prob
(lambda (x)
(syntax-case x ()
((_) #'ok))))
#t)))))
要するにsyntax-caseのテンプレート部分で局所的マクロを定義すると&compileが投げられるという不具合。エラーのメッセージは局所変数.varが参照されているけど、その定義がIForm上で見つからないというもの。 .varはマクロ展開器がパターン変数等を参照するために自動でつけられるものなのだが、この場合だと
fooとprobの両方が持っている。何がこの不具合をデバッグしづらくしているかというと、(デバッガがないというのは置いておいて)
probがコンパイル時にコンパイルされるのでどんな感じの中間コードになっているかというのが出力できないこと。コンパイラはいくつかのステップを踏んでVMコードを出力するのだが、このパターンはどのステップで不具合が入るのかとか、なんで入るのかというのを全て推測するしかないのが辛い。なんとなく推測としてある不具合の原因としては、
prob側で参照されている.varがfoo側で定義されたものになってるんだろうなぁ、くらいのものである。(恐らく正しいはず)さて、なんでこんなことが起きるんだ?
わかった、フェーズの問題だ。
probはフェーズが違うのに同じ環境を参照しようとしてるからおかしなことになってるんだ。問題はSagittariusはフェーズなんて概念がないので、フェーズ相当の何かしらをどうにかして検出してやる必要がある。どうでもいいのだが、上記のコードはYpsilonでなぜかout of contextって言われる。まぁ、恐らく僕が面しているものと同じ不具合みたいなものだろう。ついでに、explicit phasingな処理系だと怒られる。
runとexpandをつけてやる必要がある。追記の追記:
恐らく、マクロの中で定義された局所マクロのコンパイルをコンパイラが検出できればなんとかなる気がする。ただ、現状ではそんな情報がどこにもない。解決案は2つあって、
- コンパイル時にフェーズを暗に持つ
- マクロの束縛を検出したらなんらかフラグを立てる
No comments:
Post a Comment