locally 特殊形式の実装 #271

Closed
x022235 opened this Issue May 6, 2012 · 3 comments

Projects

None yet

2 participants

Owner
x022235 commented May 6, 2012

PCL のブート (#75) に必要なので locally を実装する。
#PCL を書き換えれば locally なしでも大丈夫だとは思うが、素直に locally を実装する

マクロによる参考実装

(defmacro locally (&body body)
  (multiple-value-bind (decls body)
      (lisp::find-declaration body)
    (let ((special-vars (mapcan #'(lambda (decl)
                                    (when (eq (car decl) 'special)
                                      (cdr decl)))
                                (cdar decls))))
      (if special-vars
          `(let (,@(mapcar #'(lambda (var)
                               `(,var (when (boundp ',var )
                                        (symbol-value ',var))))
                           special-vars))
             (declare (special ,@special-vars))
             ,@body)
        `(progn ,@body)))))

#CLHS には特殊形式って明確に書いてあるのでマクロじゃダメ?
#special-form-p が nil を返すと困る人がいる?
#lisp レベルで特殊形式は実装できないんだっけか?

仕様

Contributor
southly commented May 7, 2012

スペシャルフォームをマクロで実装するのはOKのはずです。
CLtL2 の 「5.1.3 特殊形式」の章でそういうことが書いてありました。

Owner
x022235 commented May 9, 2012

ありがとうございます。このあたりですね。

An implementation is free to implement as a macro any construct described herein as a special form. Conversely, an implementation is free to implement as a special form any construct described herein as a macro if an equivalent macro definition is also provided. The practical consequence is that the predicates macro-function and special-form-p may both be true of the same symbol.

他にも調べた限りでは以下のように理解しました。
間違っている点があれば指摘していただけるとありがたいです。

  • special form を macro として実装してもいい
  • macro を special form として実装してもいい
  • macro を special form として実装する場合は、macro-function でマクロを展開できないといけない
  • special-form-p が t を返すのは CLtL2 で定義された 25 個のシンボルに対してのみ
    • special form を macro で実装した場合は、special-form-p は t を返さないといけない
    • macro を special form で実装した場合は、special-form-p は nil を返さないといけない
    • xyzzy では以下が special form として実装されており (これは問題ない)、 special-form-p が t を返すがこれは ANSI CL に準拠していない。また、macro-function が nil を返すのも問題。
      • system:*byte-code
      • interactive
      • multiple-value-bind
      • multiple-value-setq
      • save-excursion
      • save-restriction
      • save-window-excursion

参考文献:

Owner
x022235 commented Jun 16, 2012

バイトコンパイルにはまだ対応していない。
難しい。。。

@x022235 x022235 added a commit that referenced this issue Jun 20, 2012
@x022235 x022235 locally のコンパイルに対応. #271
バイトコードを追加するのは難しいので、コンパイル時に let に展開して
コンパイルするようにした。

例えば以下の式は:

  (let ((a 1))
    (locally
      (declare (special a))
      a))

このように展開してからコンパイルする。

  (let ((a 1))
    (let ((a (si:*symbol-value 'a)))
      a))

si:*symbol-value はスペシャル変数が定義されていないときは #:unbound を
返す関数 (symbol-value は unbound-variable エラーを通知する)。
89614e5
@x022235 x022235 added a commit that referenced this issue Jun 20, 2012
@x022235 x022235 Merge branch 'feature/#271-locally-special-form' into develop
Conflicts:
	unittest/lisp-tests.l
508d132
@x022235 x022235 added a commit that referenced this issue Jun 20, 2012
@x022235 x022235 locally でバッファローカル変数があれば優先して参照するようにした. #271
コンパイル時の動作は si:*symbol-value が既にバッファローカル変数を
参照するようにしているので変更なし。
コンパイルの有無で微妙に動作が変わっていたのを修正した。
a8b96ef
@x022235 x022235 closed this Jun 28, 2012
@x022235 x022235 was assigned Jun 28, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment