0.7.6.20:
[sbcl.git] / src / code / macros.lisp
index fe01efd..32cc184 100644 (file)
@@ -31,8 +31,8 @@
    some locations known to SETF, starting over with test-form. Returns NIL."
   `(do () (,test-form)
      (assert-error ',test-form ',places ,datum ,@arguments)
-     ,@(mapcar #'(lambda (place)
-                  `(setf ,place (assert-prompt ',place ,place)))
+     ,@(mapcar (lambda (place)
+                `(setf ,place (assert-prompt ',place ,place)))
               places)))
 
 (defun assert-prompt (name value)
        (setf ,place
             (check-type-error ',place ,place-value ',type ,type-string)))))
 \f
-;;;; DEFCONSTANT
+;;;; DEFINE-SYMBOL-MACRO
 
-(defmacro-mundanely defconstant (name value &optional documentation)
-  #!+sb-doc
-  "Define a global constant, saying that the value is constant and may be
-  compiled into code. If the variable already has a value, and this is not
-  EQL to the new value, the code is not portable (undefined behavior). The
-  third argument is an optional documentation string for the variable."
+(defmacro-mundanely define-symbol-macro (name expansion)
   `(eval-when (:compile-toplevel :load-toplevel :execute)
-     (sb!c::%defconstant ',name ,value ',documentation)))
+    (sb!c::%define-symbol-macro ',name ',expansion)))
 
-;;; the guts of DEFCONSTANT
-(defun sb!c::%defconstant (name value doc)
+(defun sb!c::%define-symbol-macro (name expansion)
   (unless (symbolp name)
-    (error "The constant name is not a symbol: ~S" name))
-  (about-to-modify name)
-  (when (looks-like-name-of-special-var-p name)
-    (style-warn "defining ~S as a constant, even though the name follows~@
-the usual naming convention (names like *FOO*) for special variables"
-               name))
-  (let ((kind (info :variable :kind name)))
-    (case kind
-      (:constant
-       ;; Note: This behavior (discouraging any non-EQL modification)
-       ;; is unpopular, but it is specified by ANSI (i.e. ANSI says a
-       ;; non-EQL change has undefined consequences). If people really
-       ;; want bindings which are constant in some sense other than
-       ;; EQL, I suggest either just using DEFVAR (which is usually
-       ;; appropriate, despite the un-mnemonic name), or defining
-       ;; something like SB-INT:DEFCONSTANT-EQX (which is occasionally
-       ;; more appropriate). -- WHN 2000-11-03
-       (unless (eql value
-                   (info :variable :constant-value name))
-        (cerror "Go ahead and change the value."
-                "The constant ~S is being redefined."
-                name)))
-      (:global
-       ;; (This is OK -- undefined variables are of this kind. So we
-       ;; don't warn or error or anything, just fall through.)
-       )
-      (t (warn "redefining ~(~A~) ~S to be a constant" kind name))))
-  (when doc
-    (setf (fdocumentation name 'variable) doc))
-
-  ;; We want to set the cross-compilation host's symbol value, not just
-  ;; the cross-compiler's (INFO :VARIABLE :CONSTANT-VALUE NAME), so
-  ;; that code like
-  ;;   (defconstant max-entries 61)
-  ;;   (deftype entry-index () `(mod ,max-entries))
-  ;; will be cross-compiled correctly.
-  #-sb-xc-host (setf (symbol-value name) value)
-  #+sb-xc-host (progn
-                (/show (symbol-package name))
-                ;; Redefining our cross-compilation host's CL symbols
-                ;; would be poor form.
-                ;;
-                ;; FIXME: Having to check this and then not treat it
-                ;; as a fatal error seems like a symptom of things
-                ;; being pretty broken. It's also a problem in and of
-                ;; itself, since it makes it too easy for cases of
-                ;; using the cross-compilation host Lisp's CL
-                ;; constant values in the target Lisp to slip by. I
-                ;; got backed into this because the cross-compiler
-                ;; translates DEFCONSTANT SB!XC:FOO into DEFCONSTANT
-                ;; CL:FOO. It would be good to unscrew the
-                ;; cross-compilation package hacks so that that
-                ;; translation doesn't happen. Perhaps:
-                ;;   * Replace SB-XC with SB-CL. SB-CL exports all the 
-                ;;     symbols which ANSI requires to be exported from CL.
-                ;;   * Make a nickname SB!CL which behaves like SB!XC.
-                ;;   * Go through the loaded-on-the-host code making
-                ;;     every target definition be in SB-CL. E.g.
-                ;;     DEFMACRO-MUNDANELY DEFCONSTANT becomes
-                ;;     DEFMACRO-MUNDANELY SB!CL:DEFCONSTANT.
-                ;;   * Make IN-TARGET-COMPILATION-MODE do 
-                ;;     UNUSE-PACKAGE CL and USE-PACKAGE SB-CL in each
-                ;;     of the target packages (then undo it on exit).
-                ;;   * Make the cross-compiler's implementation of
-                ;;     EVAL-WHEN (:COMPILE-TOPLEVEL) do UNCROSS.
-                ;;     (This may not require any change.)
-                ;;   * Hack GENESIS as necessary so that it outputs
-                ;;     SB-CL stuff as COMMON-LISP stuff.
-                ;;   * Now the code here can assert that the symbol
-                ;;     being defined isn't in the cross-compilation
-                ;;     host's CL package.
-                (unless (eql (find-symbol (symbol-name name) :cl) name)
-                  ;; KLUDGE: In the cross-compiler, we use the
-                  ;; cross-compilation host's DEFCONSTANT macro
-                  ;; instead of just (SETF SYMBOL-VALUE), in order to
-                  ;; get whatever blessing the cross-compilation host
-                  ;; may expect for a global (SETF SYMBOL-VALUE).
-                  ;; (CMU CL, at least around 2.4.19, generated full
-                  ;; WARNINGs for code -- e.g. DEFTYPE expanders --
-                  ;; which referred to symbols which had been set by
-                  ;; (SETF SYMBOL-VALUE). I doubt such warnings are
-                  ;; ANSI-compliant, but I'm not sure, so I've
-                  ;; written this in a way that CMU CL will tolerate
-                  ;; and which ought to work elsewhere too.) -- WHN
-                  ;; 2001-03-24
-                  (eval `(defconstant ,name ',value))))
-
-  (setf (info :variable :kind name) :constant)
-  (setf (info :variable :constant-value name) value)
+    (error 'simple-type-error :datum name :expected-type 'symbol
+          :format-control "Symbol macro name is not a symbol: ~S."
+          :format-arguments (list name)))
+  (ecase (info :variable :kind name)
+    ((:macro :global nil)
+     (setf (info :variable :kind name) :macro)
+     (setf (info :variable :macro-expansion name) expansion))
+    (:special
+     (error 'simple-program-error
+           :format-control "Symbol macro name already declared special: ~S."
+           :format-arguments (list name)))
+    (:constant
+     (error 'simple-program-error
+           :format-control "Symbol macro name already declared constant: ~S."
+           :format-arguments (list name))))
   name)
+
 \f
 ;;;; DEFINE-COMPILER-MACRO
 
-;;; FIXME: The logic here for handling compiler macros named (SETF
-;;; FOO) was added after the fork from SBCL, is not well tested, and
-;;; may conflict with subtleties of the ANSI standard. E.g. section
-;;; "3.2.2.1 Compiler Macros" says that creating a lexical binding for
-;;; a function name shadows a compiler macro, and it's not clear that
-;;; that works with this version. It should be tested.
 (defmacro-mundanely define-compiler-macro (name lambda-list &body body)
   #!+sb-doc
   "Define a compiler-macro for NAME."
+  (legal-fun-name-or-type-error name)
+  (when (consp name)
+    ;; It's fairly clear that the user intends the compiler macro to
+    ;; expand when he does (SETF (FOO ...) X). And that's even a
+    ;; useful and reasonable thing to want. Unfortunately,
+    ;; (SETF (FOO ...) X) macroexpands into (FUNCALL (SETF FOO) X ...),
+    ;; and it's not at all clear that it's valid to expand a FUNCALL form,
+    ;; and the ANSI standard doesn't seem to say anything else which
+    ;; would justify us expanding the compiler macro the way the user
+    ;; wants. So instead we rely on 3.2.2.1.3 "When Compiler Macros Are
+    ;; Used" which says they never have to be used, so by ignoring such
+    ;; macros we're erring on the safe side. But any user who does
+    ;; (DEFINE-COMPILER-MACRO (SETF FOO) ...) could easily be surprised
+    ;; by this way of complying with a rather screwy aspect of the ANSI
+    ;; spec, so at least we can warn him...
+    (compiler-style-warn
+     "defining compiler macro of (SETF ...), which will not be expanded"))
   (let ((whole (gensym "WHOLE-"))
        (environment (gensym "ENV-")))
     (multiple-value-bind (body local-decs doc)
@@ -199,7 +131,7 @@ the usual naming convention (names like *FOO*) for special variables"
                        :environment environment)
       (let ((def `(lambda (,whole ,environment)
                    ,@local-decs
-                   (block ,(function-name-block-name name)
+                   (block ,(fun-name-block-name name)
                      ,body))))
        `(sb!c::%define-compiler-macro ',name #',def ',lambda-list ,doc)))))
 (defun sb!c::%define-compiler-macro (name definition lambda-list doc)
@@ -449,7 +381,7 @@ the usual naming convention (names like *FOO*) for special variables"
   code in BODY to provide possible further output."
   `(%print-unreadable-object ,object ,stream ,type ,identity
                             ,(if body
-                                 `#'(lambda () ,@body)
+                                 `(lambda () ,@body)
                                  nil)))
 
 (defmacro-mundanely ignore-errors (&rest forms)