0.pre8.28
[sbcl.git] / src / code / symbol.lisp
1 ;;;; code to manipulate symbols (but not packages, which are handled
2 ;;;; elsewhere)
3 ;;;;
4 ;;;; Many of these definitions are trivial interpreter entries to
5 ;;;; functions open-coded by the compiler.
6
7 ;;;; This software is part of the SBCL system. See the README file for
8 ;;;; more information.
9 ;;;;
10 ;;;; This software is derived from the CMU CL system, which was
11 ;;;; written at Carnegie Mellon University and released into the
12 ;;;; public domain. The software is in the public domain and is
13 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
14 ;;;; files for more information.
15
16 (in-package "SB!IMPL")
17
18 (declaim (maybe-inline get %put getf remprop %putf get-properties keywordp))
19
20 (defun symbol-value (symbol)
21   #!+sb-doc
22   "Return SYMBOL's current bound value."
23   (declare (optimize (safety 1)))
24   (symbol-value symbol))
25
26 (defun boundp (symbol)
27   #!+sb-doc
28   "Return non-NIL if SYMBOL is bound to a value."
29   (boundp symbol))
30
31 (defun set (symbol new-value)
32   #!+sb-doc
33   "Set SYMBOL's value cell to NEW-VALUE."
34   (declare (type symbol symbol))
35   (about-to-modify-symbol-value symbol)
36   (%set-symbol-value symbol new-value))
37
38 ;;; can't do this yet, the appropriate vop only gets defined in
39 ;;; compiler/target/cell, 400 lines hence
40 ;;;(defun %set-symbol-value (symbol new-value)
41 ;;;  (%set-symbol-value symbol new-value))
42
43 (defun makunbound (symbol)
44   #!+sb-doc
45   "Make SYMBOL unbound, removing any value it may currently have."
46   (set symbol
47        (%primitive sb!c:make-other-immediate-type
48                    0
49                    sb!vm:unbound-marker-widetag))
50   symbol)
51
52 ;;; Return the built-in hash value for SYMBOL.
53
54 ;;; only backends for which a SYMBOL-HASH vop exists.  In the past,
55 ;;; when the MIPS backend supported (or nearly did) a generational
56 ;;; (non-conservative) garbage collector, this read (OR X86 MIPS).
57 ;;; Having excised the vestigial support for GENGC, this now only
58 ;;; applies for the x86 port, but if someone were to rework the GENGC
59 ;;; support, this might change again.  -- CSR, 2002-08-26
60 #!+x86 
61 (defun symbol-hash (symbol)
62   (symbol-hash symbol))
63
64 ;;; Compute the hash value for SYMBOL.
65 #!-x86
66 (defun symbol-hash (symbol)
67   (%sxhash-simple-string (symbol-name symbol)))
68
69 (defun symbol-function (symbol)
70   #!+sb-doc
71   "Return SYMBOL's current function definition. Settable with SETF."
72   (%coerce-name-to-fun symbol))
73
74 (defun (setf symbol-function) (new-value symbol)
75   (declare (type symbol symbol) (type function new-value))
76   (setf (%coerce-name-to-fun symbol) new-value))
77
78 (defun symbol-plist (symbol)
79   #!+sb-doc
80   "Return SYMBOL's property list."
81   (symbol-plist symbol))
82
83 (defun %set-symbol-plist (symbol new-value)
84   (setf (symbol-plist symbol) new-value))
85
86 (defun symbol-name (symbol)
87   #!+sb-doc
88   "Return SYMBOL's name as a string."
89   (symbol-name symbol))
90
91 (defun symbol-package (symbol)
92   #!+sb-doc
93   "Return the package SYMBOL was interned in, or NIL if none."
94   (symbol-package symbol))
95
96 (defun %set-symbol-package (symbol package)
97   (declare (type symbol symbol))
98   (%set-symbol-package symbol package))
99
100 (defun make-symbol (string)
101   #!+sb-doc
102   "Make and return a new symbol with the STRING as its print name."
103   (make-symbol string))
104
105 (defun get (symbol indicator &optional (default nil))
106   #!+sb-doc
107   "Look on the property list of SYMBOL for the specified INDICATOR. If this
108   is found, return the associated value, else return DEFAULT."
109   (do ((pl (symbol-plist symbol) (cddr pl)))
110       ((atom pl) default)
111     (cond ((atom (cdr pl))
112            (error "~S has an odd number of items in its property list."
113                    symbol))
114           ((eq (car pl) indicator)
115            (return (cadr pl))))))
116
117 (defun %put (symbol indicator value)
118   #!+sb-doc
119   "The VALUE is added as a property of SYMBOL under the specified INDICATOR.
120   Returns VALUE."
121   (do ((pl (symbol-plist symbol) (cddr pl)))
122       ((endp pl)
123        (setf (symbol-plist symbol)
124              (list* indicator value (symbol-plist symbol)))
125        value)
126     (cond ((endp (cdr pl))
127            (error "~S has an odd number of items in its property list."
128                   symbol))
129           ((eq (car pl) indicator)
130            (rplaca (cdr pl) value)
131            (return value)))))
132
133 (defun remprop (symbol indicator)
134   #!+sb-doc
135   "Look on property list of SYMBOL for property with specified
136   INDICATOR. If found, splice this indicator and its value out of
137   the plist, and return the tail of the original list starting with
138   INDICATOR. If not found, return () with no side effects.
139
140   NOTE: The ANSI specification requires REMPROP to return true (not false)
141   or false (the symbol NIL). Portable code should not rely on any other value."
142   (do ((pl (symbol-plist symbol) (cddr pl))
143        (prev nil pl))
144       ((atom pl) nil)
145     (cond ((atom (cdr pl))
146            (error "~S has an odd number of items in its property list."
147                   symbol))
148           ((eq (car pl) indicator)
149            (cond (prev (rplacd (cdr prev) (cddr pl)))
150                  (t
151                   (setf (symbol-plist symbol) (cddr pl))))
152            (return pl)))))
153
154 (defun getf (place indicator &optional (default ()))
155   #!+sb-doc
156   "Search the property list stored in Place for an indicator EQ to INDICATOR.
157   If one is found, return the corresponding value, else return DEFAULT."
158   (do ((plist place (cddr plist)))
159       ((null plist) default)
160     (cond ((atom (cdr plist))
161            (error 'simple-type-error
162                   :format-control "malformed property list: ~S."
163                   :format-arguments (list place)
164                   :datum (cdr plist)
165                   :expected-type 'cons))
166           ((eq (car plist) indicator)
167            (return (cadr plist))))))
168
169 (defun %putf (place property new-value)
170   (declare (type list place))
171   (do ((plist place (cddr plist)))
172       ((endp plist) (list* property new-value place))
173     (declare (type list plist))
174     (when (eq (car plist) property)
175       (setf (cadr plist) new-value)
176       (return place))))
177
178 (defun get-properties (place indicator-list)
179   #!+sb-doc
180   "Like GETF, except that INDICATOR-LIST is a list of indicators which will
181   be looked for in the property list stored in PLACE. Three values are
182   returned, see manual for details."
183   (do ((plist place (cddr plist)))
184       ((null plist) (values nil nil nil))
185     (cond ((atom (cdr plist))
186            (error 'simple-type-error
187                   :format-control "malformed property list: ~S."
188                   :format-arguments (list place)
189                   :datum (cdr plist)
190                   :expected-type 'cons))
191           ((memq (car plist) indicator-list)
192            (return (values (car plist) (cadr plist) plist))))))
193
194 (defun copy-symbol (symbol &optional (copy-props nil) &aux new-symbol)
195   #!+sb-doc
196   "Make and return a new uninterned symbol with the same print name
197   as SYMBOL. If COPY-PROPS is false, the new symbol is neither bound
198   nor fbound and has no properties, else it has a copy of SYMBOL's
199   function, value and property list."
200   (declare (type symbol symbol))
201   (setq new-symbol (make-symbol (symbol-name symbol)))
202   (when copy-props
203     (%set-symbol-value new-symbol
204                        (%primitive sb!c:fast-symbol-value symbol))
205     (setf (symbol-plist new-symbol)
206           (copy-list (symbol-plist symbol)))
207     (when (fboundp symbol)
208       (setf (symbol-function new-symbol) (symbol-function symbol))))
209   new-symbol)
210
211 ;;; FIXME: This declaration should be redundant.
212 (declaim (special *keyword-package*))
213
214 (defun keywordp (object)
215   #!+sb-doc
216   "Return true if Object is a symbol in the \"KEYWORD\" package."
217   (and (symbolp object)
218        (eq (symbol-package object) *keyword-package*)))
219 \f
220 ;;;; GENSYM and friends
221
222 (defvar *gensym-counter* 0
223   #!+sb-doc
224   "counter for generating unique GENSYM symbols")
225 (declaim (type unsigned-byte *gensym-counter*))
226
227 (defun gensym (&optional (thing "G"))
228   #!+sb-doc
229   "Creates a new uninterned symbol whose name is a prefix string (defaults
230    to \"G\"), followed by a decimal number. Thing, when supplied, will
231    alter the prefix if it is a string, or be used for the decimal number
232    if it is a number, of this symbol. The default value of the number is
233    the current value of *gensym-counter* which is incremented each time
234    it is used."
235   (let ((old *gensym-counter*))
236     (unless (numberp thing)
237       (let ((new (etypecase old
238                    (index (1+ old))
239                    (unsigned-byte (1+ old)))))
240         (declare (optimize (speed 3) (safety 0)(inhibit-warnings 3)))
241         (setq *gensym-counter* new)))
242     (multiple-value-bind (prefix int)
243         (etypecase thing
244           (simple-string (values thing old))
245           (fixnum (values "G" thing))
246           (string (values (coerce thing 'simple-string) old)))
247       (declare (simple-string prefix))
248       (make-symbol
249        (concatenate 'simple-string prefix
250                     (the simple-string
251                          (quick-integer-to-string int)))))))
252
253 (defvar *gentemp-counter* 0)
254 (declaim (type unsigned-byte *gentemp-counter*))
255
256 (defun gentemp (&optional (prefix "T") (package (sane-package)))
257   #!+sb-doc
258   "Creates a new symbol interned in package PACKAGE with the given PREFIX."
259   (declare (type string prefix))
260   (loop
261     (let ((*print-base* 10)
262           (*print-radix* nil)
263           (*print-pretty* nil)
264           (new-pname (format nil "~A~D" prefix (incf *gentemp-counter*))))
265       (multiple-value-bind (symbol existsp) (find-symbol new-pname package)
266         (declare (ignore symbol))
267         (unless existsp (return (values (intern new-pname package))))))))