Use short form of DEFSETF for GET and GETHASH
[sbcl.git] / src / code / setf.lisp
blob5fee23ee2a7279b58e386e54c4cab5c50bf9511b
1 ;;;; SETF and friends
2 ;;;;
3 ;;;; Note: The expansions for SETF and friends sometimes create
4 ;;;; needless LET-bindings of argument values. The compiler will
5 ;;;; remove most of these spurious bindings, so SETF doesn't worry too
6 ;;;; much about creating them.
8 ;;;; This software is part of the SBCL system. See the README file for
9 ;;;; more information.
10 ;;;;
11 ;;;; This software is derived from the CMU CL system, which was
12 ;;;; written at Carnegie Mellon University and released into the
13 ;;;; public domain. The software is in the public domain and is
14 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
15 ;;;; files for more information.
17 (in-package "SB!IMPL")
19 ;;; The inverse for a generalized-variable reference function is stored in
20 ;;; one of two ways:
21 ;;;
22 ;;; A SETF inverse property corresponds to the short form of DEFSETF. It is
23 ;;; the name of a function takes the same args as the reference form, plus a
24 ;;; new-value arg at the end.
25 ;;;
26 ;;; A SETF method expander is created by the long form of DEFSETF or
27 ;;; by DEFINE-SETF-EXPANDER. It is a function that is called on the reference
28 ;;; form and that produces five values: a list of temporary variables, a list
29 ;;; of value forms, a list of the single store-value form, a storing function,
30 ;;; and an accessing function.
31 (declaim (ftype (function (t &optional (or null sb!c::lexenv))) sb!xc:get-setf-expansion))
32 (defun sb!xc:get-setf-expansion (form &optional environment)
33 #!+sb-doc
34 "Return five values needed by the SETF machinery: a list of temporary
35 variables, a list of values with which to fill them, a list of temporaries
36 for the new values, the setting function, and the accessing function."
37 (acond ((symbolp form)
38 (multiple-value-bind (expansion expanded)
39 (sb!xc:macroexpand-1 form environment)
40 (if expanded
41 (sb!xc:get-setf-expansion expansion environment)
42 (let ((new-var (sb!xc:gensym "NEW")))
43 (values nil nil (list new-var)
44 `(setq ,form ,new-var) form)))))
45 ;; Local functions inhibit global SETF methods.
46 ((and environment
47 (let ((name (car form)))
48 (dolist (x (sb!c::lexenv-funs environment))
49 (when (and (eq (car x) name)
50 (not (sb!c::defined-fun-p (cdr x))))
51 (return t)))))
52 (expand-or-get-setf-inverse form environment))
53 ((info :setf :inverse (car form))
54 (make-simple-setf-quintuple form environment nil `(,it)))
55 ((info :setf :expander (car form))
56 (if (consp it)
57 (make-setf-quintuple form environment (car it) (cdr it))
58 ;; KLUDGE: It may seem as though this should go through
59 ;; *MACROEXPAND-HOOK*, but the ANSI spec seems fairly explicit
60 ;; that *MACROEXPAND-HOOK* is a hook for MACROEXPAND-1, not
61 ;; for macroexpansion in general. -- WHN 19991128
62 (funcall it form environment)))
64 (expand-or-get-setf-inverse form environment))))
66 ;;; If a macro, expand one level and try again. If not, go for the
67 ;;; SETF function.
68 (declaim (ftype (function (t (or null sb!c::lexenv)))
69 expand-or-get-setf-inverse))
70 (defun expand-or-get-setf-inverse (form environment)
71 (multiple-value-bind (expansion expanded)
72 (%macroexpand-1 form environment)
73 (if expanded
74 (sb!xc:get-setf-expansion expansion environment)
75 (make-simple-setf-quintuple form environment
76 t `(funcall #'(setf ,(car form)))))))
78 ;; Expand PLACE until it is a form that SETF might know something about.
79 ;; Macros are expanded only when no SETF expander (or inverse) exists.
80 ;; Symbol-macros are always expanded because there are no SETF expanders
81 ;; for them. This is useful mainly when a symbol-macro or ordinary macro
82 ;; expands to a "mundane" lexical or special variable.
83 (defun macroexpand-for-setf (place environment)
84 (loop
85 (when (and (listp place)
86 (let ((op (car place)))
87 (or (info :setf :expander op) (info :setf :inverse op))))
88 (return place))
89 (multiple-value-bind (expansion macro-p) (%macroexpand-1 place environment)
90 (if macro-p
91 (setq place expansion) ; iterate
92 (return place)))))
94 ;;;; SETF itself
96 ;; Code shared by SETF, PSETF, SHIFTF attempting to minimize the expansion.
97 ;; This has significant speed+space benefit to a non-preprocessing interpreter,
98 ;; and to some degree a preprocessing interpreter.
99 (labels ((gen-let* (bindings body-forms)
100 (cond ((not bindings) body-forms)
102 (when (and (singleton-p body-forms)
103 (listp (car body-forms))
104 (eq (caar body-forms) 'let*))
105 (let ((nested (cdar body-forms))) ; extract the nested LET*
106 (setq bindings (append bindings (car nested))
107 body-forms (cdr nested))))
108 `((let* ,bindings ,@body-forms)))))
109 (gen-mv-bind (stores values body-forms)
110 (if (singleton-p stores)
111 (gen-let* `((,(car stores) ,values)) body-forms)
112 `((multiple-value-bind ,stores ,values ,@body-forms))))
113 ;; Instead of emitting (PROGN (VALUES (SETQ ...) (SETQ ...)) NIL)
114 ;; the SETQs can be lifted into the PROGN. This is unimportant
115 ;; for compiled code, but it helps the interpreter not needlessly
116 ;; collect arguments to call VALUES; and it's more human-readable.
117 (de-values-ify (forms)
118 (mapcan (lambda (form)
119 (if (and (listp form) (eq (car form) 'values))
120 (copy-list (cdr form))
121 (list form)))
122 forms)))
124 ;;; Except for atoms, we always call GET-SETF-EXPANSION, since it has
125 ;;; some non-trivial semantics. But when there is a setf inverse, and
126 ;;; G-S-E uses it, then we return a call to the inverse, rather than
127 ;;; returning a hairy LET form. This is probably important mainly as a
128 ;;; convenience in allowing the use of SETF inverses without the full
129 ;;; interpreter.
130 (defmacro-mundanely setf (&whole form &rest args &environment env)
131 #!+sb-doc
132 "Takes pairs of arguments like SETQ. The first is a place and the second
133 is the value that is supposed to go into that place. Returns the last
134 value. The place argument may be any of the access forms for which SETF
135 knows a corresponding setting form."
136 (unless args
137 (return-from setf nil))
138 (destructuring-bind (place value-form . more) args
139 (when more
140 (return-from setf `(progn ,@(sb!c::explode-setq form 'error))))
141 (when (symbolp (setq place (macroexpand-for-setf place env)))
142 (return-from setf `(setq ,place ,value-form)))
143 (multiple-value-bind (temps vals newval setter)
144 (sb!xc:get-setf-expansion place env)
145 (let ((inverse (info :setf :inverse (car place))))
146 (if (and inverse (eq inverse (car setter)))
147 `(,inverse ,@(cdr place) ,value-form)
148 (car (gen-let* (mapcar #'list temps vals)
149 (gen-mv-bind newval value-form
150 (list setter)))))))))
152 ;; various SETF-related macros
154 (defmacro-mundanely shiftf (&whole form &rest args &environment env)
155 #!+sb-doc
156 "One or more SETF-style place expressions, followed by a single
157 value expression. Evaluates all of the expressions in turn, then
158 assigns the value of each expression to the place on its left,
159 returning the value of the leftmost."
160 (declare (type sb!c::lexenv env))
161 (when (< (length args) 2)
162 (error "~S called with too few arguments: ~S" 'shiftf form))
163 (collect ((let-bindings) (mv-bindings) (setters) (getters))
164 (dolist (arg (butlast args))
165 (multiple-value-bind (temps subforms store-vars setter getter)
166 (sb!xc:get-setf-expansion arg env)
167 (let-bindings (mapcar #'list temps subforms))
168 (mv-bindings store-vars)
169 (setters setter)
170 (getters getter)))
171 ;; Handle the last arg specially here. The getter is just the last
172 ;; arg itself.
173 (getters (car (last args)))
174 (labels ((thunk (mv-bindings getters setters)
175 (if mv-bindings
176 (gen-mv-bind (car mv-bindings) (car getters)
177 (thunk (cdr mv-bindings) (cdr getters) setters))
178 setters)))
179 (let ((outputs (loop for i below (length (car (mv-bindings)))
180 collect (sb!xc:gensym "OUT"))))
181 `(let ,(reduce #'append (let-bindings))
182 ,@(gen-mv-bind outputs (car (getters))
183 (thunk (mv-bindings) (cdr (getters))
184 `(,@(de-values-ify (setters))
185 (values ,@outputs)))))))))
187 (labels
188 ((expand (args env operator single-op)
189 (cond ((singleton-p (cdr args)) ; commonest case probably
190 (return-from expand `(progn (,single-op ,@args) nil)))
191 ((not args)
192 (return-from expand nil)))
193 (collect ((let*-bindings) (mv-bindings) (setters))
194 (do ((a args (cddr a)))
195 ((endp a))
196 (when (endp (cdr a))
197 (error "Odd number of args to ~S." operator))
198 (let ((place (car a))
199 (value-form (cadr a)))
200 (when (and (not (symbolp place)) (eq operator 'psetq))
201 (error 'simple-program-error
202 :format-control "Place ~S in PSETQ is not a SYMBOL"
203 :format-arguments (list place)))
204 (multiple-value-bind (temps vals stores setter)
205 (sb!xc:get-setf-expansion place env)
206 (let*-bindings (mapcar #'list temps vals))
207 (mv-bindings (cons stores value-form))
208 (setters setter))))
209 (car (build (let*-bindings) (mv-bindings)
210 (de-values-ify (setters))))))
211 (build (let*-bindings mv-bindings setters)
212 (if let*-bindings
213 (gen-let* (car let*-bindings)
214 (gen-mv-bind (caar mv-bindings) (cdar mv-bindings)
215 (build (cdr let*-bindings) (cdr mv-bindings)
216 setters)))
217 `(,@setters nil))))
219 (defmacro-mundanely psetf (&rest pairs &environment env)
220 #!+sb-doc
221 "This is to SETF as PSETQ is to SETQ. Args are alternating place
222 expressions and values to go into those places. All of the subforms and
223 values are determined, left to right, and only then are the locations
224 updated. Returns NIL."
225 (expand pairs env 'psetf 'setf))
227 (defmacro-mundanely psetq (&rest pairs &environment env)
228 #!+sb-doc
229 "PSETQ {var value}*
230 Set the variables to the values, like SETQ, except that assignments
231 happen in parallel, i.e. no assignments take place until all the
232 forms have been evaluated."
233 (expand pairs env 'psetq 'setq))))
235 ;;; FIXME: Compiling this definition of ROTATEF apparently blows away the
236 ;;; definition in the cross-compiler itself, so that after that, any
237 ;;; ROTATEF operations can no longer be compiled, because
238 ;;; GET-SETF-EXPANSION is called instead of SB!XC:GET-SETF-EXPANSION.
239 (defmacro-mundanely rotatef (&rest args &environment env)
240 #!+sb-doc
241 "Takes any number of SETF-style place expressions. Evaluates all of the
242 expressions in turn, then assigns to each place the value of the form to
243 its right. The rightmost form gets the value of the leftmost.
244 Returns NIL."
245 (declare (type sb!c::lexenv env))
246 (when args
247 (collect ((let*-bindings) (mv-bindings) (setters) (getters))
248 (dolist (arg args)
249 (multiple-value-bind (temps subforms store-vars setter getter)
250 (sb!xc:get-setf-expansion arg env)
251 (let*-bindings (mapcar #'list temps subforms))
252 (mv-bindings store-vars)
253 (setters setter)
254 (getters getter)))
255 (setters nil)
256 (getters (car (getters)))
257 (labels ((thunk (mv-bindings getters)
258 (if mv-bindings
259 `((multiple-value-bind ,(car mv-bindings) ,(car getters)
260 ,@(thunk (cdr mv-bindings) (cdr getters))))
261 (setters))))
262 `(let* ,(reduce #'append(let*-bindings))
263 ,@(thunk (mv-bindings) (cdr (getters))))))))
265 (defmacro-mundanely push (obj place &environment env)
266 #!+sb-doc
267 "Takes an object and a location holding a list. Conses the object onto
268 the list, returning the modified list. OBJ is evaluated before PLACE."
269 ;; If PLACE has multiple store locations, what should we do?
270 ;; In other Lisp implementations:
271 ;; - One errs, says "Multiple store variables not expected"
272 ;; - One pushes multiple values produced by OBJ form into multiple places.
273 ;; - At least two produce an incorrect expansion that doesn't even work.
274 (expand-rmw-macro 'cons (list obj) place '() env '(item)))
276 (defmacro-mundanely pushnew (obj place &rest keys
277 &key key test test-not &environment env)
278 #!+sb-doc
279 "Takes an object and a location holding a list. If the object is
280 already in the list, does nothing; otherwise, conses the object onto
281 the list. Returns the modified list. If there is a :TEST keyword, this
282 is used for the comparison."
283 (declare (ignore key test test-not))
284 (multiple-value-bind (dummies vals newval setter getter)
285 (sb!xc:get-setf-expansion place env)
286 (let ((g (gensym)))
287 `(let* ((,g ,obj)
288 ,@(mapcar #'list dummies vals)
289 (,(car newval) (adjoin ,g ,getter ,@keys))
290 ,@(cdr newval))
291 ,setter))))
293 (defmacro-mundanely pop (place &environment env)
294 #!+sb-doc
295 "The argument is a location holding a list. Pops one item off the front
296 of the list and returns it."
297 (if (symbolp (setq place (macroexpand-for-setf place env)))
298 `(prog1 (car ,place) (setq ,place (cdr ,place)))
299 (multiple-value-bind (temps vals stores setter getter)
300 (sb!xc:get-setf-expansion place env)
301 (let ((list (copy-symbol 'list))
302 (ret (copy-symbol 'car)))
303 `(let* (,@(mapcar #'list temps vals)
304 (,list ,getter)
305 (,ret (car ,list))
306 (,(car stores) (cdr ,list))
307 ,@(cdr stores))
308 ,setter
309 ,ret)))))
311 (defmacro-mundanely remf (place indicator &environment env)
312 #!+sb-doc
313 "Place may be any place expression acceptable to SETF, and is expected
314 to hold a property list or (). This list is destructively altered to
315 remove the property specified by the indicator. Returns T if such a
316 property was present, NIL if not."
317 (multiple-value-bind (temps vals newval setter getter)
318 (sb!xc:get-setf-expansion place env)
319 (let* ((flag (make-symbol "FLAG"))
320 (body `(multiple-value-bind (,(car newval) ,flag)
321 ;; See ANSI 5.1.3 for why we do out-of-order evaluation
322 (truly-the (values list boolean)
323 (%remf ,indicator ,getter))
324 ,(if (cdr newval) `(let ,(cdr newval) ,setter) setter)
325 ,flag)))
326 (if temps `(let* ,(mapcar #'list temps vals) ,body) body))))
328 ;; Perform the work of REMF.
329 (defun %remf (indicator plist)
330 (let ((tail plist) (predecessor))
331 (loop
332 (when (endp tail) (return (values plist nil)))
333 (let ((key (pop tail)))
334 (when (atom tail)
335 (error (if tail
336 "Improper list in REMF."
337 "Odd-length list in REMF.")))
338 (let ((next (cdr tail)))
339 (when (eq key indicator)
340 ;; This function is strict in its return type!
341 (the list next) ; for effect
342 (return (values (cond (predecessor
343 (setf (cdr predecessor) next)
344 plist)
346 next))
347 t)))
348 (setq predecessor tail tail next))))))
350 ;;; INCF and DECF have a straightforward expansion, avoiding temp vars,
351 ;;; when the PLACE is a non-macro symbol. Otherwise we do the generalized
352 ;;; SETF-like thing. The compiler doesn't care either way, but this
353 ;;; reduces the incentive to treat some macros as special-forms when
354 ;;; squeezing more performance from a Lisp interpreter.
355 ;;; DEFINE-MODIFY-MACRO could be used, but this expands more compactly.
356 (declaim (inline xsubtract))
357 (defun xsubtract (a b) (- b a)) ; exchanged subtract
358 (flet ((expand (place delta env operator)
359 (if (symbolp (setq place (macroexpand-for-setf place env)))
360 `(setq ,place (,operator ,delta ,place))
361 (multiple-value-bind (dummies vals newval setter getter)
362 (sb!xc:get-setf-expansion place env)
363 `(let* (,@(mapcar #'list dummies vals)
364 (,(car newval) (,operator ,delta ,getter))
365 ,@(cdr newval))
366 ,setter)))))
367 (defmacro-mundanely incf (place &optional (delta 1) &environment env)
368 #!+sb-doc
369 "The first argument is some location holding a number. This number is
370 incremented by the second argument, DELTA, which defaults to 1."
371 (expand place delta env '+))
373 (defmacro-mundanely decf (place &optional (delta 1) &environment env)
374 #!+sb-doc
375 "The first argument is some location holding a number. This number is
376 decremented by the second argument, DELTA, which defaults to 1."
377 (expand place delta env 'xsubtract)))
379 ;;;; DEFINE-MODIFY-MACRO stuff
381 (def!macro sb!xc:define-modify-macro (name lambda-list function &optional doc-string)
382 #!+sb-doc
383 "Creates a new read-modify-write macro like PUSH or INCF."
384 (let ((other-args nil)
385 (rest-arg nil)
386 (env (make-symbol "ENV")) ; To beautify resulting arglist.
387 (reference (make-symbol "PLACE"))) ; Note that these will be nonexistent
388 ; in the final expansion anyway.
389 ;; Parse out the variable names and &REST arg from the lambda list.
390 (do ((ll lambda-list (cdr ll))
391 (arg nil))
392 ((null ll))
393 (setq arg (car ll))
394 (cond ((eq arg '&optional))
395 ((eq arg '&rest)
396 (if (symbolp (cadr ll))
397 (setq rest-arg (cadr ll))
398 (error "Non-symbol &REST argument in definition of ~S." name))
399 (if (null (cddr ll))
400 (return nil)
401 (error "Illegal stuff after &REST argument.")))
402 ((memq arg '(&key &allow-other-keys &aux))
403 (error "~S not allowed in DEFINE-MODIFY-MACRO lambda list." arg))
404 ((symbolp arg)
405 (push arg other-args))
406 ((and (listp arg) (symbolp (car arg)))
407 (push (car arg) other-args))
408 (t (error "Illegal stuff in lambda list."))))
409 (setq other-args (nreverse other-args))
410 `(#-sb-xc-host sb!xc:defmacro
411 #+sb-xc-host defmacro-mundanely
412 ,name (,reference ,@lambda-list &environment ,env)
413 ,@(when doc-string (list (the string doc-string)))
414 (expand-rmw-macro ',function
415 '() ,reference (list* ,@other-args ,rest-arg)
416 ,env ',other-args))))
418 ;;;; DEFSETF
420 (eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
421 ;;; Assign SETF macro information for NAME, making all appropriate checks.
422 (macrolet ((assign-it ()
423 `(progn
424 (when inverse
425 (clear-info :setf :expander name)
426 (setf (info :setf :inverse name) inverse))
427 (when expander
428 #-sb-xc-host
429 (setf (%fun-lambda-list
430 (if (listp expander) (cdr expander) expander))
431 expander-lambda-list)
432 (clear-info :setf :inverse name)
433 (setf (info :setf :expander name) expander))
434 (when doc
435 (setf (fdocumentation name 'setf) doc))
436 name)))
437 (defun %defsetf (name expander expander-lambda-list inverse doc)
438 #+sb-xc-host (declare (ignore expander-lambda-list))
439 (with-single-package-locked-error
440 (:symbol name "defining a setf-expander for ~A"))
441 (let ((setf-fn-name `(setf ,name)))
442 (multiple-value-bind (where-from present-p)
443 (info :function :where-from setf-fn-name)
444 ;; One might think that :DECLARED merits a style warning, but SBCL
445 ;; provides ~58 standard accessors as both (SETF F) and a macro.
446 ;; So allow the user to declaim an FTYPE and we'll hush up.
447 ;; What's good for the the goose is good for the gander.
448 (case where-from
449 (:assumed
450 ;; This indicates probable user error. Compilation assumed something
451 ;; to be functional; a macro says otherwise. Because :where-from's
452 ;; default can be :assumed, PRESENT-P disambiguates "defaulted" from
453 ;; "known" to have made an existence assumption.
454 (when present-p
455 (warn "defining setf macro for ~S when ~S was previously ~
456 treated as a function" name setf-fn-name)))
457 (:defined
458 ;; Somebody defined (SETF F) but then also said F has a macro.
459 ;; A soft warning seems appropriate because in this case it's
460 ;; at least in theory not wrong to call the function.
461 ;; The user can declare an FTYPE if both things are intentional.
462 (style-warn "defining setf macro for ~S when ~S is also defined"
463 name setf-fn-name)))))
464 (assign-it))
465 (defun !quietly-defsetf (name expander expander-lambda-list inverse doc)
466 (assign-it))))
468 (def!macro sb!xc:defsetf (access-fn &rest rest)
469 #!+sb-doc
470 "Associates a SETF update function or macro with the specified access
471 function or macro. The format is complex. See the manual for details."
472 (unless (symbolp access-fn)
473 (error "~S access-function name ~S is not a symbol."
474 'sb!xc:defsetf access-fn))
475 (typecase rest
476 ((cons (and symbol (not null)) (or null (cons string null)))
477 `(eval-when (:load-toplevel :compile-toplevel :execute)
478 (%defsetf ',access-fn nil nil ',(car rest) ',(cadr rest))))
479 ((cons list (cons list))
480 (destructuring-bind (lambda-list (&rest store-variables) &body body) rest
481 (multiple-value-bind (forms decls doc) (parse-body body)
482 (multiple-value-bind (store-var-decl other-decls)
483 (extract-var-decls decls store-variables)
484 (let ((form (copy-symbol 'form))
485 (environment (copy-symbol 'env)))
486 ;; FIXME: a defsetf lambda-list is *NOT* a macro lambda list!
487 ;; Suppose that (MY-ACC ((X))) is a macro, not a function,
488 ;; and you attempt to destructure the X. It parses ok by accident,
489 ;; but when you attempt to bind to subforms of MY-ACC,
490 ;; you find that ((X)) is not a well-formed sexpr.
491 (multiple-value-bind (body env-decl)
492 (parse-defmacro lambda-list form `(,@other-decls ,@forms)
493 access-fn 'defsetf
494 :environment environment
495 :anonymousp t)
496 `(eval-when (:compile-toplevel :load-toplevel :execute)
497 (%defsetf ',access-fn
498 (cons ,(length store-variables)
499 (lambda (,form ,environment ,@store-variables)
500 ,@env-decl ; possibly (IGNORE ENVIRONMENT)
501 ,@(if store-var-decl (list store-var-decl))
502 ,body))
503 ',lambda-list nil ',doc))))))))
505 (error "Ill-formed DEFSETF for ~S" access-fn))))
507 ;; Much of the SETF framework shares logic to assemble the first two values
508 ;; for GET-SETF-EXPANSION while eschewing bindings for constant arguments.
509 (flet ((collect-call-temps (place-subforms environment name-hints)
510 (collect ((temp-vars) (temp-vals) (call-arguments))
511 (dolist (form place-subforms
512 (values (temp-vars) (temp-vals) (call-arguments)))
513 ;; Generated code is more understandable when it uses temp vars
514 ;; whose names resemble the lambda vars for the DEFSETF of PLACE.
515 (labels ((nice-tempname ()
516 (if name-hints
517 (let ((sym (pop name-hints)))
518 (if (member sym sb!xc:lambda-list-keywords)
519 (nice-tempname)
520 (copy-symbol (if (consp sym) (car sym) sym))))
521 (gensymify form))))
522 (call-arguments (if (sb!xc:constantp form environment)
523 form
524 (let ((temp (nice-tempname)))
525 (temp-vars temp)
526 (temp-vals form)
527 temp))))))))
529 ;; Return the 5-part expansion of a SETF form that calls #'(SETF Fn)
530 ;; when SETF-FUN-P is non-nil, or the short form of a DEFSETF, when NIL.
531 ;; INVERSE should be (FUNCALL #'(SETF x)) or (SETTER-FN) respectively.
532 (defun make-simple-setf-quintuple (access-form environment setf-fun-p inverse)
533 (multiple-value-bind (temp-vars temp-vals args)
534 (collect-call-temps (cdr access-form) environment nil)
535 (let ((store (sb!xc:gensym "NEW")))
536 (values temp-vars temp-vals (list store)
537 `(,@inverse ,@(if setf-fun-p `(,store ,@args) `(,@args ,store)))
538 `(,(car access-form) ,@args)))))
540 ;; Return the 5-part expansion of a SETF form defined by the long form
541 ;; of DEFSETF.
542 ;; FIXME: totally broken if there are keyword arguments. lp#1452947
543 (defun make-setf-quintuple (access-form environment num-store-vars expander)
544 (declare (type function expander))
545 (multiple-value-bind (temp-vars temp-vals call-arguments)
546 ;; FORMALS affect aesthetics only, not behavior.
547 (let ((formals #-sb-xc-host (%simple-fun-arglist expander)))
548 (collect-call-temps (cdr access-form) environment formals))
549 (let ((stores (let ((sb!xc:*gensym-counter* 1))
550 (make-gensym-list num-store-vars "NEW"))))
551 (values temp-vars temp-vals stores
552 (apply expander call-arguments environment stores)
553 `(,(car access-form) ,@call-arguments)))))
555 ;; Expand a macro defined by DEFINE-MODIFY-MACRO.
556 ;; The generated call resembles (FUNCTION PLACE . ARG-FORMS) but the
557 ;; read and write of PLACE - not including its subforms - are done
558 ;; only after all ARG-FORMS are evaluated.
559 (defun expand-rmw-macro (function before-arg-forms place after-arg-forms
560 environment name-hints)
561 ;; Note that NAME-HINTS do the wrong thing if you have both "before" and
562 ;; "after" args. In that case it is probably best to specify them as ().
563 (binding* (((before-temps before-vals before-args)
564 (collect-call-temps before-arg-forms environment name-hints))
565 ((place-temps place-subforms stores setter getter)
566 (sb!xc:get-setf-expansion place environment))
567 ((after-temps after-vals after-args)
568 (collect-call-temps after-arg-forms environment name-hints))
569 (compute `(,function ,@before-args ,getter ,@after-args))
570 (set-fn (and (listp setter) (car setter)))
571 (newval-temp (car stores))
572 (newval-binding `((,newval-temp ,compute))))
573 ;; Elide the binding of NEWVAL-TEMP if it is ref'd exactly once
574 ;; and all the call arguments are temporaries and/or constants.
575 (when (and (= (count newval-temp setter) 1)
576 (or (eq set-fn 'setq)
577 (and (eq (info :function :kind set-fn) :function)
578 (every (lambda (x)
579 (or (member x place-temps)
580 (eq x newval-temp)
581 (sb!xc:constantp x environment)))
582 (cdr setter)))))
583 (setq newval-binding nil
584 setter (substitute compute newval-temp setter)))
585 (let ((bindings
586 (flet ((zip (list1 list2) (mapcar #'list list1 list2)))
587 (append (zip before-temps before-vals)
588 (zip place-temps place-subforms)
589 (zip after-temps after-vals)
590 newval-binding
591 (cdr stores)))))
592 (if bindings `(let* ,bindings ,setter) setter)))))
594 ;;;; DEFMACRO DEFINE-SETF-EXPANDER and various DEFINE-SETF-EXPANDERs
596 ;;; DEFINE-SETF-EXPANDER is a lot like DEFMACRO.
597 (def!macro sb!xc:define-setf-expander (access-fn lambda-list &body body)
598 #!+sb-doc
599 "Syntax like DEFMACRO, but creates a setf expander function. The body
600 of the definition must be a form that returns five appropriate values."
601 (unless (symbolp access-fn)
602 (error "~S access-function name ~S is not a symbol."
603 'sb!xc:define-setf-expander access-fn))
604 (with-unique-names (whole environment)
605 (multiple-value-bind (body local-decs doc)
606 (parse-defmacro lambda-list whole body access-fn
607 'sb!xc:define-setf-expander
608 :environment environment)
609 `(eval-when (:compile-toplevel :load-toplevel :execute)
610 (%defsetf ',access-fn
611 (lambda (,whole ,environment) ,@local-decs ,body)
612 ',lambda-list nil ',doc)))))
614 (sb!xc:define-setf-expander values (&rest places &environment env)
615 (declare (type sb!c::lexenv env))
616 (collect ((setters) (getters))
617 (let ((all-dummies '())
618 (all-vals '())
619 (newvals '()))
620 (dolist (place places)
621 (multiple-value-bind (dummies vals newval setter getter)
622 (sb!xc:get-setf-expansion place env)
623 ;; ANSI 5.1.2.3 explains this logic quite precisely. --
624 ;; CSR, 2004-06-29
625 (setq all-dummies (append all-dummies dummies (cdr newval))
626 all-vals (append all-vals vals
627 (mapcar (constantly nil) (cdr newval)))
628 newvals (append newvals (list (car newval))))
629 (setters setter)
630 (getters getter)))
631 (values all-dummies all-vals newvals
632 `(values ,@(setters)) `(values ,@(getters))))))
634 (sb!xc:define-setf-expander getf (place prop
635 &optional default
636 &environment env)
637 (declare (type sb!c::lexenv env))
638 (multiple-value-bind (temps values stores set get)
639 (sb!xc:get-setf-expansion place env)
640 (let ((newval (gensym))
641 (ptemp (gensym))
642 (def-temp (if default (gensym))))
643 (values `(,@temps ,ptemp ,@(if default `(,def-temp)))
644 `(,@values ,prop ,@(if default `(,default)))
645 `(,newval)
646 `(let ((,(car stores) (%putf ,get ,ptemp ,newval))
647 ,@(cdr stores))
648 ,def-temp ;; prevent unused style-warning
649 ,set
650 ,newval)
651 `(getf ,get ,ptemp ,@(if default `(,def-temp)))))))
653 ;; CLHS Notes on DEFSETF say that: "A setf of a call on access-fn also evaluates
654 ;; all of access-fn's arguments; it cannot treat any of them specially."
655 ;; An implication is that even though the DEFAULT argument to GET,GETHASH serves
656 ;; no purpose except when used in a R/M/W context such as PUSH, you can't elide
657 ;; it. In particular, this must fail: (SETF (GET 'SYM 'IND (ERROR "Foo")) 3).
659 (sb!xc:defsetf get (symbol indicator &optional default &environment e) (newval)
660 (let ((form `(%put ,symbol ,indicator ,newval)))
661 (if (and default (not (sb!xc:constantp default e)))
662 `(progn ,default ,form) ; reference default to "use" it
663 form)))
665 ;; A possible optimization for read/modify/write of GETHASH
666 ;; would be to predetermine the vector element where the key/value pair goes.
667 (sb!xc:defsetf gethash (key hashtable &optional default &environment e) (newval)
668 (let ((form `(%puthash ,key ,hashtable ,newval)))
669 (if (and default (not (sb!xc:constantp default e)))
670 `(progn ,default ,form) ; reference default to "use" it
671 form)))
673 (sb!xc:define-setf-expander logbitp (index int &environment env)
674 (declare (type sb!c::lexenv env))
675 (multiple-value-bind (temps vals stores store-form access-form)
676 (sb!xc:get-setf-expansion int env)
677 (let ((ind (gensym))
678 (store (gensym))
679 (stemp (first stores)))
680 (values `(,ind ,@temps)
681 `(,index
682 ,@vals)
683 (list store)
684 `(let ((,stemp
685 (dpb (if ,store 1 0) (byte 1 ,ind) ,access-form))
686 ,@(cdr stores))
687 ,store-form
688 ,store)
689 `(logbitp ,ind ,access-form)))))
691 ;;; CMU CL had a comment here that:
692 ;;; Evil hack invented by the gnomes of Vassar Street (though not as evil as
693 ;;; it used to be.) The function arg must be constant, and is converted to
694 ;;; an APPLY of the SETF function, which ought to exist.
696 ;;; Historical note: The hack was considered evil becase prior to the
697 ;;; standardization of #'(SETF F) as a namespace for functions, all that existed
698 ;;; were SETF expanders. To "invert" (APPLY #'F A B .. LAST), you assumed that
699 ;;; the SETF expander was ok to use on (F A B .. LAST), yielding something
700 ;;; like (set-F A B .. LAST). If the LAST arg didn't move (based on comparing
701 ;;; gensyms between the "getter" and "setter" forms), you'd stick APPLY
702 ;;; in front and hope for the best. Plus AREF still had to be special-cased.
704 ;;; It may not be clear (wasn't to me..) that this is a standard thing, but See
705 ;;; "5.1.2.5 APPLY Forms as Places" in the ANSI spec. I haven't actually
706 ;;; verified that this code has any correspondence to that code, but at least
707 ;;; ANSI has some place for SETF APPLY. -- WHN 19990604
708 (sb!xc:define-setf-expander apply (functionoid &rest args)
709 ;; Technically (per CLHS) this only must allow AREF,BIT,SBIT
710 ;; but there's not much danger in allowing other stuff.
711 (unless (typep functionoid '(cons (eql function) (cons symbol null)))
712 (error "SETF of APPLY is only defined for function args like #'SYMBOL."))
713 (let ((function (second functionoid))
714 (new-var (gensym))
715 (vars (make-gensym-list (length args))))
716 (values vars args (list new-var)
717 `(apply #'(setf ,function) ,new-var ,@vars)
718 `(apply #',function ,@vars))))
720 ;;; Special-case a BYTE bytespec so that the compiler can recognize it.
721 ;;; FIXME: it is suboptimal that (INCF (LDB (BYTE 9 0) (ELT X 0)))
722 ;;; performs two reads of (ELT X 0), once to get the value from which
723 ;;; to extract a 9-bit subfield, and again to combine the incremented
724 ;;; value with the other bits. I don't think it's wrong per se,
725 ;;; but is worthy of some thought as to whether it can be improved.
726 (sb!xc:define-setf-expander ldb (bytespec place &environment env)
727 #!+sb-doc
728 "The first argument is a byte specifier. The second is any place form
729 acceptable to SETF. Replace the specified byte of the number in this
730 place with bits from the low-order end of the new value."
731 (declare (type sb!c::lexenv env))
732 (multiple-value-bind (dummies vals newval setter getter)
733 (sb!xc:get-setf-expansion place env)
734 (if (and (consp bytespec) (eq (car bytespec) 'byte))
735 (let ((n-size (gensym))
736 (n-pos (gensym))
737 (n-new (gensym)))
738 (values (list* n-size n-pos dummies)
739 (list* (second bytespec) (third bytespec) vals)
740 (list n-new)
741 `(let ((,(car newval) (dpb ,n-new (byte ,n-size ,n-pos)
742 ,getter))
743 ,@(cdr newval))
744 ,setter
745 ,n-new)
746 `(ldb (byte ,n-size ,n-pos) ,getter)))
747 (let ((btemp (gensym))
748 (gnuval (gensym)))
749 (values (cons btemp dummies)
750 (cons bytespec vals)
751 (list gnuval)
752 `(let ((,(car newval) (dpb ,gnuval ,btemp ,getter)))
753 ,setter
754 ,gnuval)
755 `(ldb ,btemp ,getter))))))
757 (sb!xc:define-setf-expander mask-field (bytespec place &environment env)
758 #!+sb-doc
759 "The first argument is a byte specifier. The second is any place form
760 acceptable to SETF. Replaces the specified byte of the number in this place
761 with bits from the corresponding position in the new value."
762 (declare (type sb!c::lexenv env))
763 (multiple-value-bind (dummies vals newval setter getter)
764 (sb!xc:get-setf-expansion place env)
765 (let ((btemp (gensym))
766 (gnuval (gensym)))
767 (values (cons btemp dummies)
768 (cons bytespec vals)
769 (list gnuval)
770 `(let ((,(car newval) (deposit-field ,gnuval ,btemp ,getter))
771 ,@(cdr newval))
772 ,setter
773 ,gnuval)
774 `(mask-field ,btemp ,getter)))))
776 (defun setf-expand-the (the type place env)
777 (declare (type sb!c::lexenv env))
778 (multiple-value-bind (temps subforms store-vars setter getter)
779 (sb!xc:get-setf-expansion place env)
780 (values temps subforms store-vars
781 `(multiple-value-bind ,store-vars
782 (,the ,type (values ,@store-vars))
783 ,setter)
784 `(,the ,type ,getter))))
786 (sb!xc:define-setf-expander the (type place &environment env)
787 (setf-expand-the 'the type place env))
789 (sb!xc:define-setf-expander truly-the (type place &environment env)
790 (setf-expand-the 'truly-the type place env))