Let's start Scheme

2011-05-26

マクロに潜んでいる罠

たいした物言いだがたいしたことではない。
Sagittariusで発見して、Gaucheでも再現するという不思議なバグの話。
以下のコード
(define-syntax hoge
  (syntax-rules ()
    ((_ args ...)
     (letrec-syntax 
  ((find (syntax-rules ()
    ((_ a b c)
     (next a b))))
   (next (syntax-rules ()
    ((_ a b c)
     (find a b c))
    ((_ a b)
     (print a b)))))
       (find args ...)))))
(hoge 1 2 3)
findとかnextはSSAXのマクロから取っているだけで別に名前はなんでもいい。
これを実行すると、unknown variable nextというのが出る。でも、letrec-syntaxの部分だけ取り出して実行すると動く。
原因は分かっていて、識別子の比較が弱いためにコンパイル時環境のlookupが失敗しているのだ。
不思議なこととしては、最初のhogeが展開されたときに作成される識別子は正しく作成されている(この場合は同じアドレスという意味)のに、lookup時はなぜか失敗する。
コンパイル時環境のlookupはGaucheとほぼ同じなのだが、syntax-rulesの実装はまるで違う(はず)。なのに両方でこれが発生するということは、まぁ、そこなんだろう。もしくは、syntax-rules内で予定外の識別子がrenameされたかのどちらかなんだけど。

原因を追究していたのだが、疲れたので息抜きに書いてみた。

No comments:

Post a Comment