symbol-macrolet で shadowing しなきゃならん special-form

書いてて気づいたんだけど、単純に除外するんじゃなくて、たとえば (let (foo ...) ...) なら foo は symbol-macro じゃないけど他の bar とかは symbol-macro になるから、bar とかはちゃんと置換しなきゃいけないんだ。うん。

で。

  1. 関数で lexical scope を作ることはできないんで、関数は放置
  2. macro は macroexpand すれば消えてなくなるので無視
  3. つまり special-form さえ気にすればおk
(do-all-symbols (sym) (if (special-form-p sym) (format t "~S~%" sym)))

から関係ありそうなのを列挙。

lexical environment

  • macrolet ???
  • let*
  • labels
  • let
  • multiple-value-bind
  • flet
  • function (lambda)

macroexpand した後で macrolet が残ってるってありえないよーな。

forms using symbol as 'tag'

  • throw
  • return-from
  • go
  • catch
  • tagbody
  • block

other: eval-when

:compile-toplevel とか symbol-macro で変換されても困るだろ。

追記 (2009-07-11 12:02)

そもそも constant は symbol macro にできないみたい @sbcl。keyword symbol が constantp だなんて知らなかった。

other: quote

これはどーなんかなぁ。

(macroexpand '(defmacro foo () foo))
=> (progn nil (system:*fset 'foo '(macro nil (block foo foo))))

とか見ると quote されてるのはそのままにしとくのが楽そうなんだけど。

sbcl で試してみたら

(let ((bar 'I-AM-BAR))
  (symbol-macrolet ((foo bar))
    (list foo 'foo)))
=> (I-AM-BAR FOO)

で quoted symbol はそのままみたい。

Each reference to symbol as a variable within the lexical scope of symbol-macrolet is expanded by the normal macro expansion process;

CLHS: Special Operator SYMBOL-MACROLET

だから quote されてたら放置でいーのか。


あと、すっげー気になるっていうか、どーにもできない気がするのが si:*byte-code。