1 ;;;; This software is part of the SBCL system. See the README file for
4 ;;;; This software is derived from the CMU CL system, which was
5 ;;;; written at Carnegie Mellon University and released into the
6 ;;;; public domain. The software is in the public domain and is
7 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
8 ;;;; files for more information.
10 (in-package "SB!IMPL")
12 (def!macro sb
!xc
:defconstant
(name value
&optional documentation
)
14 "Define a global constant, saying that the value is constant and may be
15 compiled into code. If the variable already has a value, and this is not
16 EQL to the new value, the code is not portable (undefined behavior). The
17 third argument is an optional documentation string for the variable."
18 `(eval-when (:compile-toplevel
:load-toplevel
:execute
)
19 (sb!c
::%defconstant
',name
,value
',documentation
)))
21 ;;; the guts of DEFCONSTANT
22 (defun sb!c
::%defconstant
(name value doc
)
23 (unless (symbolp name
)
24 (error "The constant name is not a symbol: ~S" name
))
25 (about-to-modify-symbol-value name
)
26 (when (looks-like-name-of-special-var-p name
)
27 (style-warn "defining ~S as a constant, even though the name follows~@
28 the usual naming convention (names like *FOO*) for special variables"
30 (let ((kind (info :variable
:kind name
)))
33 ;; Note: This behavior (discouraging any non-EQL modification)
34 ;; is unpopular, but it is specified by ANSI (i.e. ANSI says a
35 ;; non-EQL change has undefined consequences). If people really
36 ;; want bindings which are constant in some sense other than
37 ;; EQL, I suggest either just using DEFVAR (which is usually
38 ;; appropriate, despite the un-mnemonic name), or defining
39 ;; something like the DEFCONSTANT-EQX macro used in SBCL (which
40 ;; is occasionally more appropriate). -- WHN 2001-12-21
42 (info :variable
:constant-value name
))
43 (multiple-value-bind (ignore aborted
)
44 (with-simple-restart (abort "Keep the old value.")
45 (cerror "Go ahead and change the value."
48 :old-value
(info :variable
:constant-value name
)
50 (declare (ignore ignore
))
52 (return-from sb
!c
::%defconstant name
)))))
54 ;; (This is OK -- undefined variables are of this kind. So we
55 ;; don't warn or error or anything, just fall through.)
57 (t (warn "redefining ~(~A~) ~S to be a constant" kind name
))))
59 (setf (fdocumentation name
'variable
) doc
))
61 (setf (symbol-value name
) value
)
64 ;; Redefining our cross-compilation host's CL symbols
65 ;; would be poor form.
67 ;; FIXME: Having to check this and then not treat it
68 ;; as a fatal error seems like a symptom of things
69 ;; being pretty broken. It's also a problem in and of
70 ;; itself, since it makes it too easy for cases of
71 ;; using the cross-compilation host Lisp's CL
72 ;; constant values in the target Lisp to slip by. I
73 ;; got backed into this because the cross-compiler
74 ;; translates DEFCONSTANT SB!XC:FOO into DEFCONSTANT
75 ;; CL:FOO. It would be good to unscrew the
76 ;; cross-compilation package hacks so that that
77 ;; translation doesn't happen. Perhaps:
78 ;; * Replace SB-XC with SB-CL. SB-CL exports all the
79 ;; symbols which ANSI requires to be exported from CL.
80 ;; * Make a nickname SB!CL which behaves like SB!XC.
81 ;; * Go through the loaded-on-the-host code making
82 ;; every target definition be in SB-CL. E.g.
83 ;; DEFMACRO-MUNDANELY DEFCONSTANT becomes
84 ;; DEFMACRO-MUNDANELY SB!CL:DEFCONSTANT.
85 ;; * Make IN-TARGET-COMPILATION-MODE do
86 ;; UNUSE-PACKAGE CL and USE-PACKAGE SB-CL in each
87 ;; of the target packages (then undo it on exit).
88 ;; * Make the cross-compiler's implementation of
89 ;; EVAL-WHEN (:COMPILE-TOPLEVEL) do UNCROSS.
90 ;; (This may not require any change.)
91 ;; * Hack GENESIS as necessary so that it outputs
92 ;; SB-CL stuff as COMMON-LISP stuff.
93 ;; * Now the code here can assert that the symbol
94 ;; being defined isn't in the cross-compilation
96 (unless (eql (find-symbol (symbol-name name
) :cl
) name
)
97 ;; KLUDGE: In the cross-compiler, we use the
98 ;; cross-compilation host's DEFCONSTANT macro
99 ;; instead of just (SETF SYMBOL-VALUE), in order to
100 ;; get whatever blessing the cross-compilation host
101 ;; may expect for a global (SETF SYMBOL-VALUE).
102 ;; (CMU CL, at least around 2.4.19, generated full
103 ;; WARNINGs for code -- e.g. DEFTYPE expanders --
104 ;; which referred to symbols which had been set by
105 ;; (SETF SYMBOL-VALUE). I doubt such warnings are
106 ;; ANSI-compliant, but I'm not sure, so I've
107 ;; written this in a way that CMU CL will tolerate
108 ;; and which ought to work elsewhere too.) -- WHN
110 (eval `(defconstant ,name
',value
))))
112 (setf (info :variable
:kind name
) :constant
113 (info :variable
:constant-value name
) value
)