Move poorly-named NWORDS function near its call site
[sbcl.git] / src / code / defsetfs.lisp
blob45dfdfe481005e24705e3274e76027b4c8d16be4
1 ;;;; various DEFSETFs, pulled into one file for convenience in doing
2 ;;;; them as early in the build process as possible so as to avoid
3 ;;;; hassles with invoking SETF FOO before DEFSETF FOO and thus
4 ;;;; compiling a call to some nonexistent function #'(SETF FOO)
6 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; more information.
8 ;;;;
9 ;;;; This software is derived from the CMU CL system, which was
10 ;;;; written at Carnegie Mellon University and released into the
11 ;;;; public domain. The software is in the public domain and is
12 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
13 ;;;; files for more information.
15 ;;; from alieneval.lisp
16 (in-package "SB!ALIEN")
17 (defsetf slot %set-slot)
18 (defsetf deref (alien &rest indices) (value)
19 `(%set-deref ,alien ,value ,@indices))
20 (defsetf %heap-alien %set-heap-alien)
22 ;;; from arch-vm.lisp
23 (in-package "SB!VM")
24 (defsetf context-register %set-context-register)
25 (defsetf context-float-register %set-context-float-register)
26 ;;; from bit-bash.lisp
27 (defsetf word-sap-ref %set-word-sap-ref)
29 ;;; from debug-int.lisp
30 (in-package "SB!DI")
31 (defsetf stack-ref %set-stack-ref)
32 (defsetf debug-var-value %set-debug-var-value)
33 (defsetf debug-var-value %set-debug-var-value)
34 (defsetf breakpoint-info %set-breakpoint-info)
36 ;;; from bignum.lisp
37 (in-package "SB!IMPL")
38 (defsetf %bignum-ref %bignum-set)
40 ;;; from defstruct.lisp
41 (defsetf %instance-ref %instance-set)
43 (defsetf %raw-instance-ref/word %raw-instance-set/word)
44 #!+raw-signed-word
45 (defsetf %raw-instance-ref/signed-word %raw-instance-set/signed-word)
46 (defsetf %raw-instance-ref/single %raw-instance-set/single)
47 (defsetf %raw-instance-ref/double %raw-instance-set/double)
48 (defsetf %raw-instance-ref/complex-single %raw-instance-set/complex-single)
49 (defsetf %raw-instance-ref/complex-double %raw-instance-set/complex-double)
51 (defsetf %instance-layout %set-instance-layout)
52 (defsetf %funcallable-instance-info %set-funcallable-instance-info)
53 (defsetf %funcallable-instance-layout %set-funcallable-instance-layout)
55 ;;; from early-setf.lisp
57 ;;; (setf aref/bit/sbit) are implemented using setf-functions,
58 ;;; because they have to work with (setf (apply #'aref array subscripts))
59 ;;; All other setfs can be done using setf-functions too, but I
60 ;;; haven't found technical advantages or disadvantages for either
61 ;;; scheme.
62 (defsetf car %rplaca)
63 (defsetf first %rplaca)
64 (defsetf cdr %rplacd)
65 (defsetf rest %rplacd)
67 (eval-when (:compile-toplevel :load-toplevel :execute)
68 (defun %cxr-setf-expander (sub-accessor setter)
69 (flet ((expand (place-reader original-form)
70 (let ((temp (make-symbol "LIST"))
71 (newval (make-symbol "NEW")))
72 (values (list temp)
73 `((,@place-reader ,@(cdr original-form)))
74 (list newval)
75 `(,setter ,temp ,newval)
76 `(,(if (eq setter '%rplacd) 'cdr 'car) ,temp)))))
77 (if (eq sub-accessor 'nthcdr) ; random N
78 (lambda (access-form env)
79 (declare (ignore env))
80 (declare (sb!c::lambda-list (n list)))
81 (destructuring-bind (n list) (cdr access-form) ; for effect
82 (declare (ignore n list)))
83 (expand '(nthcdr) access-form))
84 ;; NTHCDR of fixed N, or CxxxxR composition
85 (lambda (access-form env)
86 (declare (ignore env))
87 (declare (sb!c::lambda-list (list)))
88 (destructuring-bind (list) (cdr access-form) ; for effect
89 (declare (ignore list)))
90 (expand sub-accessor access-form))))))
92 (macrolet ((def (name &optional alias &aux (string (string name)))
93 `(eval-when (:compile-toplevel :load-toplevel :execute)
94 (let ((closure
95 (%cxr-setf-expander
96 '(,(symbolicate "C" (subseq string 2)))
97 ',(symbolicate "%RPLAC" (subseq string 1 2)))))
98 (%defsetf ',name closure)
99 ,@(when alias `((%defsetf ',alias closure)))))))
100 ;; Rather than expand into a DEFINE-SETF-EXPANDER, install a single closure
101 ;; as the expander and capture just enough to distinguish the variations.
102 (def caar)
103 (def cadr second)
104 (def cdar)
105 (def cddr)
106 (def caaar)
107 (def cadar)
108 (def cdaar)
109 (def cddar)
110 (def caadr)
111 (def caddr third)
112 (def cdadr)
113 (def cdddr)
114 (def caaaar)
115 (def cadaar)
116 (def cdaaar)
117 (def cddaar)
118 (def caadar)
119 (def caddar)
120 (def cdadar)
121 (def cdddar)
122 (def caaadr)
123 (def cadadr)
124 (def cdaadr)
125 (def cddadr)
126 (def caaddr)
127 (def cadddr fourth)
128 (def cdaddr)
129 (def cddddr))
131 ;; FIFTH through TENTH
132 (macrolet ((def (name subform)
133 `(eval-when (:compile-toplevel :load-toplevel :execute)
134 (%defsetf ',name (%cxr-setf-expander ',subform '%rplaca)))))
135 (def fifth (nthcdr 4)) ; or CDDDDR
136 (def sixth (nthcdr 5))
137 (def seventh (nthcdr 6))
138 (def eighth (nthcdr 7))
139 (def ninth (nthcdr 8))
140 (def tenth (nthcdr 9)))
142 ;; CLHS says under the entry for NTH:
143 ;; "nth may be used to specify a place to setf. Specifically,
144 ;; (setf (nth n list) new-object) == (setf (car (nthcdr n list)) new-object)"
145 ;; which means that it's wrong to use %SETNTH because in the second form,
146 ;; (NTHCDR ...) is a subform of the CAR expression, and so must be
147 ;; bound to a temporary variable.
148 (eval-when (:compile-toplevel :load-toplevel :execute)
149 (%defsetf 'nth (%cxr-setf-expander 'nthcdr '%rplaca)))
151 (defsetf elt %setelt)
152 (defsetf row-major-aref %set-row-major-aref)
153 (defsetf svref %svset)
154 (defsetf char %charset)
155 (defsetf schar %scharset)
156 (defsetf %array-dimension %set-array-dimension)
157 (defsetf %vector-raw-bits %set-vector-raw-bits)
158 (defsetf symbol-value set)
159 (defsetf symbol-global-value set-symbol-global-value)
160 (defsetf symbol-plist %set-symbol-plist)
161 (defsetf fill-pointer %set-fill-pointer)
162 (defsetf sap-ref-8 %set-sap-ref-8)
163 (defsetf signed-sap-ref-8 %set-signed-sap-ref-8)
164 (defsetf sap-ref-16 %set-sap-ref-16)
165 (defsetf signed-sap-ref-16 %set-signed-sap-ref-16)
166 (defsetf sap-ref-32 %set-sap-ref-32)
167 (defsetf signed-sap-ref-32 %set-signed-sap-ref-32)
168 (defsetf sap-ref-64 %set-sap-ref-64)
169 (defsetf signed-sap-ref-64 %set-signed-sap-ref-64)
170 (defsetf sap-ref-word %set-sap-ref-word)
171 (defsetf signed-sap-ref-word %set-signed-sap-ref-word)
172 (defsetf sap-ref-sap %set-sap-ref-sap)
173 (defsetf sap-ref-lispobj %set-sap-ref-lispobj)
174 (defsetf sap-ref-single %set-sap-ref-single)
175 (defsetf sap-ref-double %set-sap-ref-double)
176 #!+long-float (defsetf sap-ref-long %set-sap-ref-long)
177 (defsetf subseq (sequence start &optional end) (v)
178 `(progn (replace ,sequence ,v :start1 ,start :end1 ,end) ,v))
180 ;;; from fdefinition.lisp
181 (defsetf fdefinition %set-fdefinition)
183 ;;; from kernel.lisp
184 (defsetf code-header-ref code-header-set)
186 ;;; from pcl
187 (defsetf slot-value sb!pcl::set-slot-value)
189 ;;; from sxhash.lisp
190 (define-modify-macro mixf (y) mix)
192 ;;;; Long form DEFSETF macros:
194 ;; CLHS Notes on DEFSETF say that: "A setf of a call on access-fn also evaluates
195 ;; all of access-fn's arguments; it cannot treat any of them specially."
196 ;; An implication is that even though the DEFAULT argument to GET,GETHASH serves
197 ;; no purpose except when used in a R/M/W context such as PUSH, you can't elide
198 ;; it. In particular, this must fail: (SETF (GET 'SYM 'IND (ERROR "Foo")) 3).
200 (defsetf get (symbol indicator &optional default &environment e) (newval)
201 (let ((constp (sb!xc:constantp default e)))
202 ;; always reference default's temp var to "use" it
203 `(%put ,symbol ,indicator ,(if constp newval `(progn ,default ,newval)))))
205 ;; A possible optimization for read/modify/write of GETHASH
206 ;; would be to predetermine the vector element where the key/value pair goes.
207 (defsetf gethash (key hashtable &optional default &environment e) (newval)
208 (let ((constp (sb!xc:constantp default e)))
209 ;; always reference default's temp var to "use" it
210 `(%puthash ,key ,hashtable ,(if constp newval `(progn ,default ,newval)))))
212 ;;;; DEFINE-SETF-MACROs
214 (define-setf-expander the (&whole form type place &environment env)
215 (binding* ((op (car form))
216 ((temps subforms store-vars setter getter)
217 (sb!xc:get-setf-expansion place env)))
218 (values temps subforms store-vars
219 `(multiple-value-bind ,store-vars (,op ,type (values ,@store-vars))
220 ,setter)
221 `(,op ,type ,getter))))
223 (define-setf-expander getf (place prop &optional default &environment env)
224 (binding* (((place-tempvars place-tempvals stores set get)
225 (sb!xc:get-setf-expansion place env))
226 ((call-tempvars call-tempvals call-args bitmask)
227 (collect-setf-temps (list prop default) env '(indicator default)))
228 (newval (gensym "NEW")))
229 (values `(,@place-tempvars ,@call-tempvars)
230 `(,@place-tempvals ,@call-tempvals)
231 `(,newval)
232 `(let ((,(car stores) (%putf ,get ,(first call-args) ,newval))
233 ,@(cdr stores))
234 ;; prevent "unused variable" style-warning
235 ,@(when (logbitp 1 bitmask) (last call-tempvars))
236 ,set
237 ,newval)
238 `(getf ,get ,@call-args))))
240 (define-setf-expander values (&rest places &environment env)
241 ;; KLUDGE: don't use COLLECT - it gets defined later.
242 ;; It could be potentially be defined earlier if it were important,
243 ;; but sidestepping it this one time wasn't so difficult.
244 (let (all-dummies all-vals newvals setters getters)
245 (dolist (place places)
246 (multiple-value-bind (dummies vals newval setter getter)
247 (sb!xc:get-setf-expansion place env)
248 ;; ANSI 5.1.2.3 explains this logic quite precisely. --
249 ;; CSR, 2004-06-29
250 (setq all-dummies (append all-dummies dummies (cdr newval))
251 all-vals (append all-vals vals
252 (mapcar (constantly nil) (cdr newval)))
253 newvals (append newvals (list (car newval))))
254 (push setter setters)
255 (push getter getters)))
256 (values all-dummies all-vals newvals
257 `(values ,@(nreverse setters)) `(values ,@(nreverse getters)))))
259 ;;; CMU CL had a comment here that:
260 ;;; Evil hack invented by the gnomes of Vassar Street (though not as evil as
261 ;;; it used to be.) The function arg must be constant, and is converted to
262 ;;; an APPLY of the SETF function, which ought to exist.
264 ;;; Historical note: The hack was considered evil becase prior to the
265 ;;; standardization of #'(SETF F) as a namespace for functions, all that existed
266 ;;; were SETF expanders. To "invert" (APPLY #'F A B .. LAST), you assumed that
267 ;;; the SETF expander was ok to use on (F A B .. LAST), yielding something
268 ;;; like (set-F A B .. LAST). If the LAST arg didn't move (based on comparing
269 ;;; gensyms between the "getter" and "setter" forms), you'd stick APPLY
270 ;;; in front and hope for the best. Plus AREF still had to be special-cased.
272 ;;; It may not be clear (wasn't to me..) that this is a standard thing, but See
273 ;;; "5.1.2.5 APPLY Forms as Places" in the ANSI spec. I haven't actually
274 ;;; verified that this code has any correspondence to that code, but at least
275 ;;; ANSI has some place for SETF APPLY. -- WHN 19990604
276 (define-setf-expander apply (functionoid &rest args &environment env)
277 ;; Technically (per CLHS) this only must allow AREF,BIT,SBIT
278 ;; but there's not much danger in allowing other stuff.
279 (unless (typep functionoid '(cons (eql function) (cons symbol null)))
280 (error "SETF of APPLY is only defined for function args like #'SYMBOL."))
281 (multiple-value-bind (vars vals args) (collect-setf-temps args env nil)
282 (let ((new-var (copy-symbol 'new)))
283 (values vars vals (list new-var)
284 `(apply #'(setf ,(cadr functionoid)) ,new-var ,@args)
285 `(apply ,functionoid ,@args)))))
287 ;;; Perform expansion of SETF on LDB, MASK-FIELD, or LOGBITP.
288 ;;; It is preferable to destructure the BYTE form and bind temp vars to its
289 ;;; parts rather than bind a temp for its result. (See the source transforms
290 ;;; for LDB/DPB). But for constant arguments to BYTE, we don't need any temp.
291 (define-setf-expander ldb (&whole form spec place &environment env)
292 "The first argument is a byte specifier. The second is any place form
293 acceptable to SETF. Replace the specified byte of the number in this
294 place with bits from the low-order end of the new value."
295 (binding* (((bytespec-form store-fun load-fun)
296 (ecase (car form)
297 (ldb (values spec 'dpb 'ldb))
298 (mask-field (values spec 'deposit-field 'mask-field))
299 (logbitp (values `(byte 1 ,spec) 'dpb 'logbitp))))
300 (spec (%macroexpand bytespec-form env))
301 ((byte-tempvars byte-tempvals byte-args)
302 (if (typep spec '(cons (eql byte)
303 (and (not (cons integer (cons integer)))
304 (cons t (cons t null)))))
305 (collect-setf-temps (cdr spec) env '(size pos))
306 (collect-setf-temps (list spec) env '(bytespec))))
307 (byte (if (cdr byte-args) (cons 'byte byte-args) (car byte-args)))
308 ((place-tempvars place-tempvals stores setter getter)
309 (sb!xc:get-setf-expansion place env))
310 (newval (sb!xc:gensym "NEW"))
311 (new-int `(,store-fun
312 ,(if (eq load-fun 'logbitp) `(if ,newval 1 0) newval)
313 ,byte ,getter)))
314 (values `(,@byte-tempvars ,@place-tempvars)
315 `(,@byte-tempvals ,@place-tempvals)
316 (list newval)
317 ;; FIXME: expand-rmw-macro has code for determining whether
318 ;; a binding of a "newval" can be elided.
319 (if (and (typep setter '(cons (eql setq)
320 (cons symbol (cons t null))))
321 (not (cdr stores))
322 (eq (third setter) (first stores)))
323 `(progn (setq ,(second setter) ,new-int) ,newval)
324 `(let ((,(car stores) ,new-int) ,@(cdr stores))
325 ,setter
326 ,newval))
327 (if (eq load-fun 'logbitp)
328 ;; If there was a temp for the POS, then use it.
329 ;; Otherwise use the constant POS from the original spec.
330 `(logbitp ,(or (car byte-tempvars) (third spec)) ,getter)
331 `(,load-fun ,byte ,getter)))))
333 (locally (declare (notinline info)) ; can't inline
334 (eval-when (:compile-toplevel :load-toplevel :execute)
335 (%defsetf 'truly-the (info :setf :expander 'the))
337 (%defsetf 'mask-field (info :setf :expander 'ldb)
338 "The first argument is a byte specifier. The second is any place form
339 acceptable to SETF. Replaces the specified byte of the number in this place
340 with bits from the corresponding position in the new value.")
342 ;;; SETF of LOGBITP is not mandated by CLHS but is nice to have.
343 ;;; FIXME: the code is suboptimal. Better code would "pre-shift" the 1 bit,
344 ;;; so that result = (in & ~mask) | (flag ? mask : 0)
345 ;;; Additionally (setf (logbitp N x) t) is extremely stupid- it first clears
346 ;;; and then sets the bit, though it does manage to pre-shift the constants.
347 (%defsetf 'logbitp (info :setf :expander 'ldb))))