sb-walkerのrpushの例がよく分からない (2) — #:g1

Posted 2011-12-03 23:44:00 GMT

前回のwith-rpushでは、macroexpand-allしないといけないのが謎でしたが、walk-formに展開関数が渡っていないのがそもそも不思議(新しい環境でマクロが展開されない)で、明示的に渡せば良いのではないか、ということで

(defmacro with-lexical-macros (macros &body body &environment old-env)
  (sb-walker::with-augmented-environment (new-env old-env :macros macros)
    (sb-walker:walk-form `(progn ,@body)
                         new-env
                         (lambda (form context env)
                           (declare (ignore context))
                           (macroexpand-1 form env)))))
としたところ、これでもOKでした。
それでもいまいち腑に落ちないので、sb-walkerにマクロ展開系の機能がないか確認してみたのですが、
sb-walker:*walk-form-expand-macros-p*
という変数があり、デフォルトでは、NILなのですが、これをTにすると、展開関数を渡さなくてもマクロを展開してくれるようです。
ということで、sb-walkerで書くなら
(defun expand-rpush (form env)
  (declare (ignore env))
  `(push ,(caddr form) ,(cadr form)))

(defmacro with-lexical-macros (macros &body body &environment old-env) (let ((sb-walker:*walk-form-expand-macros-p* T)) (sb-walker::with-augmented-environment (new-env old-env :macros macros) (sb-walker:walk-form `(progn ,@body) new-env))))

(defmacro with-rpush (&body body) `(with-lexical-macros ((rpush ,#'expand-rpush)) ,@body))

(let ((ans '())) (with-rpush (rpush ans 'foo) )) ;=> (FOO)

と書くのが、オリジナルPortable CommonLoops版に大体対応するのではないか、というところで落ち着きました。
しかし、いずれにせよ、sb-walkerで動かない例が添付されているのは謎です…。

comments powered by Disqus