Fix grammar in lossage message
[sbcl.git] / src / code / defstruct.lisp
blob72c9a492f7284a0d141d3947458748ba21da4c74
1 ;;;; that part of DEFSTRUCT implementation which is needed not just
2 ;;;; in the target Lisp but also in the cross-compilation host
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
13 (in-package "SB!KERNEL")
15 (/show0 "code/defstruct.lisp 15")
17 ;;;; getting LAYOUTs
19 ;;; Return the compiler layout for NAME. (The class referred to by
20 ;;; NAME must be a structure-like class.)
21 (defun compiler-layout-or-lose (name)
22 (let ((res (info :type :compiler-layout name)))
23 (cond ((not res)
24 (error "Class is not yet defined or was undefined: ~S" name))
25 ((not (typep (layout-info res) 'defstruct-description))
26 (error "Class is not a structure class: ~S" name))
28 (sb!int:check-deprecated-type name)
29 res))))
31 (defun compiler-layout-ready-p (name)
32 (let ((layout (info :type :compiler-layout name)))
33 (and layout (typep (layout-info layout) 'defstruct-description))))
35 (sb!xc:defmacro %make-structure-instance-macro (dd slot-specs &rest slot-vars)
36 (if (compiler-layout-ready-p (dd-name dd))
37 `(truly-the ,(dd-name dd)
38 (%make-structure-instance ,dd ,slot-specs ,@slot-vars))
39 ;; Non-toplevel defstructs don't have a layout at compile time,
40 ;; so we need to construct the actual function at runtime -- but
41 ;; we cache it at the call site, so that we don't perform quite
42 ;; so horribly.
43 `(let* ((cell (load-time-value (list nil)))
44 (fun (car cell)))
45 (if (functionp fun)
46 (funcall fun ,@slot-vars)
47 (funcall (setf (car cell)
48 (%make-structure-instance-allocator ,dd ,slot-specs))
49 ,@slot-vars)))))
51 (declaim (ftype (sfunction (defstruct-description list) function)
52 %make-structure-instance-allocator))
53 (defun %make-structure-instance-allocator (dd slot-specs)
54 (let ((vars (make-gensym-list (length slot-specs))))
55 (values (compile nil
56 `(lambda (,@vars)
57 (%make-structure-instance-macro ,dd ',slot-specs ,@vars))))))
59 (defun %make-funcallable-structure-instance-allocator (dd slot-specs)
60 (when slot-specs
61 (bug "funcallable-structure-instance allocation with slots unimplemented"))
62 (let ((name (dd-name dd))
63 (length (dd-length dd))
64 (nobject (gensym "OBJECT")))
65 (values
66 (compile nil `(lambda ()
67 (let ((,nobject (%make-funcallable-instance ,length)))
68 (setf (%funcallable-instance-layout ,nobject)
69 (%delayed-get-compiler-layout ,name))
70 ,nobject))))))
72 ;;; Delay looking for compiler-layout until the constructor is being
73 ;;; compiled, since it doesn't exist until after the EVAL-WHEN
74 ;;; (COMPILE) stuff is compiled. (Or, in the oddball case when
75 ;;; DEFSTRUCT is executing in a non-toplevel context, the
76 ;;; compiler-layout still doesn't exist at compilation time, and we
77 ;;; delay still further.)
78 (sb!xc:defmacro %delayed-get-compiler-layout (name)
79 (let ((layout (info :type :compiler-layout name)))
80 (cond (layout
81 ;; ordinary case: When the DEFSTRUCT is at top level,
82 ;; then EVAL-WHEN (COMPILE) stuff will have set up the
83 ;; layout for us to use.
84 (unless (typep (layout-info layout) 'defstruct-description)
85 (error "Class is not a structure class: ~S" name))
86 `,layout)
88 ;; KLUDGE: In the case that DEFSTRUCT is not at top-level
89 ;; the layout doesn't exist at compile time. In that case
90 ;; we laboriously look it up at run time. This code will
91 ;; run on every constructor call and will likely be quite
92 ;; slow, so if anyone cares about performance of
93 ;; non-toplevel DEFSTRUCTs, it should be rewritten to be
94 ;; cleverer. -- WHN 2002-10-23
95 (sb!c:compiler-notify
96 "implementation limitation: ~
97 Non-toplevel DEFSTRUCT constructors are slow.")
98 (with-unique-names (layout)
99 `(let ((,layout (info :type :compiler-layout ',name)))
100 (unless (typep (layout-info ,layout) 'defstruct-description)
101 (error "Class is not a structure class: ~S" ',name))
102 ,layout))))))
104 ;;; re. %DELAYED-GET-COMPILER-LAYOUT and COMPILE-TIME-FIND-LAYOUT, above..
106 ;;; FIXME: Perhaps both should be defined with SB!XC:DEFMACRO?
107 ;;; FIXME: Do we really need both? If so, their names and implementations
108 ;;; should probably be tweaked to be more parallel.
110 ;;;; DEFSTRUCT-DESCRIPTION
112 ;;; The DEFSTRUCT-DESCRIPTION structure holds compile-time information
113 ;;; about a structure type.
114 ;;; Its definition occurs in 'early-classoid.lisp'
115 (defmethod print-object ((x defstruct-description) stream)
116 (print-unreadable-object (x stream :type t :identity t)
117 (prin1 (dd-name x) stream)))
119 ;;; Does DD describe a structure with a class?
120 (defun dd-class-p (dd)
121 (if (member (dd-type dd) '(structure funcallable-structure)) t nil))
123 (defun dd-layout-or-lose (dd)
124 (compiler-layout-or-lose (dd-name dd)))
126 ;;;; DEFSTRUCT-SLOT-DESCRIPTION
128 ;;; A DEFSTRUCT-SLOT-DESCRIPTION holds compile-time information about
129 ;;; a structure slot.
130 (def!struct (defstruct-slot-description
131 (:conc-name dsd-)
132 (:copier nil)
133 #-sb-xc-host (:pure t))
134 ;; name of slot
135 name
136 ;; its position in the implementation sequence
137 (index (missing-arg) :type fixnum)
138 ;; the name of the accessor function
140 ;; (CMU CL had extra complexity here ("..or NIL if this accessor has
141 ;; the same name as an inherited accessor (which we don't want to
142 ;; shadow)") but that behavior doesn't seem to be specified by (or
143 ;; even particularly consistent with) ANSI, so it's gone in SBCL.)
144 (accessor-name nil :type symbol)
145 default ; default value expression
146 (type t) ; declared type specifier
147 (safe-p t :type boolean) ; whether the slot is known to be
148 ; always of the specified type
149 ;; Index into *RAW-SLOT-DATA* vector of the RAW-SLOT-DATA for this slot.
150 ;; The index is -1 if this slot is not raw.
151 (%raw-type -1 :type (integer -1 (#.(length *raw-slot-data*))))
152 (read-only nil :type (member t nil)))
153 #!-sb-fluid (declaim (freeze-type defstruct-slot-description))
154 (!set-load-form-method defstruct-slot-description (:host :xc :target))
155 (defmethod print-object ((x defstruct-slot-description) stream)
156 (print-unreadable-object (x stream :type t)
157 (prin1 (dsd-name x) stream)))
158 (defun dsd-raw-slot-data (dsd)
159 (let ((type-index (dsd-%raw-type dsd)))
160 (and (>= type-index 0)
161 (svref *raw-slot-data* type-index))))
162 (defun dsd-raw-type (dsd)
163 (acond ((dsd-raw-slot-data dsd) (raw-slot-data-raw-type it))
164 (t)))
166 ;;;; typed (non-class) structures
168 ;;; Return a type specifier we can use for testing :TYPE'd structures.
169 (defun dd-lisp-type (defstruct)
170 (ecase (dd-type defstruct)
171 (list 'list)
172 (vector `(simple-array ,(dd-element-type defstruct) (*)))))
174 ;;;; shared machinery for inline and out-of-line slot accessor functions
176 ;;; Classic comment preserved for entertainment value:
178 ;;; "A lie can travel halfway round the world while the truth is
179 ;;; putting on its shoes." -- Mark Twain
181 ;;;; the legendary DEFSTRUCT macro itself (both CL:DEFSTRUCT and its
182 ;;;; close personal friend SB!XC:DEFSTRUCT)
184 (sb!xc:defmacro delay-defstruct-functions (name &rest forms)
185 ;; KLUDGE: If DEFSTRUCT is not at the top-level,
186 ;; (typep x 'name) and similar forms can't get optimized
187 ;; and produce style-warnings for unknown types.
188 (let ((forms (cons 'progn forms)))
189 (if (compiler-layout-ready-p name)
190 forms
191 `(eval ',forms))))
193 (defun %defstruct-package-locks (dd)
194 (let ((name (dd-name dd)))
195 #+sb-xc-host (declare (ignore name))
196 (with-single-package-locked-error
197 (:symbol name "defining ~S as a structure"))
198 (awhen (dd-predicate-name dd)
199 (with-single-package-locked-error
200 (:symbol it "defining ~s as a predicate for ~s structure" name)))
201 (awhen (dd-copier-name dd)
202 (with-single-package-locked-error
203 (:symbol it "defining ~s as a copier for ~s structure" name)))
204 #-sb-xc-host ; does nothing anyway except warn about non-use of CTOR
205 (dolist (ctor (dd-constructors dd))
206 (with-single-package-locked-error
207 (:symbol (car ctor) "defining ~s as a constructor for ~s structure" name)))
208 (dolist (dsd (dd-slots dd))
209 (awhen (dsd-accessor-name dsd)
210 (with-single-package-locked-error
211 (:symbol it "defining ~s as an accessor for ~s structure" name))))))
213 ;;; Special var used by autogenerated print functions.
214 (sb!xc:proclaim '(special *current-level-in-print*))
216 ;;; shared logic for host macroexpansion for SB!XC:DEFSTRUCT and
217 ;;; cross-compiler macroexpansion for CL:DEFSTRUCT
218 ;;; This monster has exactly one inline use in the final image,
219 ;;; and we can drop the definition.
220 (declaim (inline !expander-for-defstruct))
221 (defun !expander-for-defstruct (null-env-p name-and-options slot-descriptions
222 expanding-into-code-for)
223 (binding*
224 (((dd classoid inherits)
225 (parse-defstruct null-env-p name-and-options slot-descriptions))
226 (boa-constructors (member-if #'listp (dd-constructors dd) :key #'cdr))
227 (keyword-constructors (ldiff (dd-constructors dd) boa-constructors))
228 (constructor-definitions
229 (nconc
230 (when keyword-constructors
231 (let ((primary (caar keyword-constructors)))
232 (cons
233 `(defun ,primary ,@(structure-ctor-lambda-parts dd :default))
234 ;; Quasi-bogus: not all the right effects on globaldb
235 ;; happen by defining functions this cheating way.
236 (mapcar (lambda (other)
237 `(setf (fdefinition ',(car other))
238 (fdefinition ',primary)))
239 (rest keyword-constructors)))))
240 (mapcar (lambda (ctor)
241 `(defun ,(car ctor)
242 ,@(structure-ctor-lambda-parts dd (cdr ctor))))
243 boa-constructors)))
244 (name (dd-name dd))
245 (print-method
246 (when (dd-print-option dd)
247 (let* ((x (make-symbol "OBJECT"))
248 (s (make-symbol "STREAM"))
249 (fname (dd-printer-fname dd))
250 (depthp (eq (dd-print-option dd) :print-function)))
251 ;; Giving empty :PRINT-OBJECT or :PRINT-FUNCTION options
252 ;; leaves FNAME eq to NIL. The user-level effect is
253 ;; to generate a PRINT-OBJECT method specialized for the type,
254 ;; implementing the default #S structure-printing behavior.
255 (cond ((not fname)
256 (setf fname 'default-structure-print depthp t))
257 ((not (symbolp fname))
258 ;; Don't dump the source form into the DD constant;
259 ;; just indicate that there was an expression there.
260 (setf (dd-printer-fname dd) t)))
261 `((defmethod print-object ((,x ,name) ,s)
262 (funcall #',fname ,x ,s
263 ,@(if depthp `(*current-level-in-print*)))))))))
264 ;; Return a list of forms and the DD-NAME.
265 (values
266 (if (dd-class-p dd)
267 `(,@(when (eq expanding-into-code-for :target)
268 ;; Note we intentionally enforce package locks, calling
269 ;; %DEFSTRUCT first. %DEFSTRUCT has the tests (and resulting
270 ;; CERROR) for collisions with LAYOUTs which already exist in
271 ;; the runtime. If there are collisions, we want the user's
272 ;; response to CERROR to control what happens. If the ABORT
273 ;; restart is chosen, %COMPILER-DEFSTRUCT should not modify
274 ;; the definition the class.
275 `((eval-when (:compile-toplevel :load-toplevel :execute)
276 (%defstruct-package-locks ',dd))))
277 (%defstruct ',dd ',inherits (sb!c:source-location))
278 (eval-when (:compile-toplevel :load-toplevel :execute)
279 (%compiler-defstruct ',dd ',inherits))
280 ,@(when (eq expanding-into-code-for :target)
281 `((delay-defstruct-functions
282 ,name
283 ,@(awhen (dd-copier-name dd)
284 `((defun ,(dd-copier-name dd) (instance)
285 (copy-structure (the ,(dd-name dd) instance)))))
286 ,@(awhen (dd-predicate-name dd)
287 `((defun ,(dd-predicate-name dd) (object)
288 (typep object ',(dd-name dd)))))
289 ,@(accessor-definitions dd classoid))
290 ;; This must be in the same lexical environment
291 ,@constructor-definitions
292 ,@print-method
293 ;; Various other operations only make sense on the target SBCL.
294 (%target-defstruct ',dd))))
295 ;; Not DD-CLASS-P
296 ;; FIXME: missing package lock checks
297 `((eval-when (:compile-toplevel :load-toplevel :execute)
298 (%proclaim-defstruct-ctors ',dd)
299 (setf (info :typed-structure :info ',name) ',dd))
300 (setf (info :source-location :typed-structure ',name)
301 (sb!c:source-location))
302 ,@(when (eq expanding-into-code-for :target)
303 `(,@(typed-accessor-definitions dd)
304 ,@(typed-predicate-definitions dd)
305 ,@(typed-copier-definitions dd)
306 ,@constructor-definitions
307 ,@(when (dd-doc dd)
308 `((setf (fdocumentation ',(dd-name dd) 'structure)
309 ',(dd-doc dd))))))))
310 name)))
312 #+sb-xc-host
313 (sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions)
314 ;; All defstructs are toplevel in SBCL's own source code,
315 ;; so pass T for null-lexenv.
316 `(progn ,@(!expander-for-defstruct
317 t name-and-options slot-descriptions :target)))
319 #+sb-xc
320 (sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions
321 &environment env)
322 #!+sb-doc
323 "DEFSTRUCT {Name | (Name Option*)} [Documentation] {Slot | (Slot [Default] {Key Value}*)}
324 Define the structure type Name. Instances are created by MAKE-<name>,
325 which takes &KEY arguments allowing initial slot values to the specified.
326 A SETF'able function <name>-<slot> is defined for each slot to read and
327 write slot values. <name>-p is a type predicate.
329 Popular DEFSTRUCT options (see manual for others):
331 (:CONSTRUCTOR Name)
332 (:PREDICATE Name)
333 Specify the name for the constructor or predicate.
335 (:CONSTRUCTOR Name Lambda-List)
336 Specify the name and arguments for a BOA constructor
337 (which is more efficient when keyword syntax isn't necessary.)
339 (:INCLUDE Supertype Slot-Spec*)
340 Make this type a subtype of the structure type Supertype. The optional
341 Slot-Specs override inherited slot options.
343 Slot options:
345 :TYPE Type-Spec
346 Asserts that the value of this slot is always of the specified type.
348 :READ-ONLY {T | NIL}
349 If true, no setter function is defined for this slot."
350 (multiple-value-bind (forms name)
351 (!expander-for-defstruct
352 (etypecase env
353 (sb!kernel:lexenv (sb!c::null-lexenv-p env))
354 ;; a LOCALLY environment would be fine,
355 ;; but is not an important case to handle.
356 #!+sb-fasteval (sb!interpreter:basic-env nil)
357 (null t))
358 name-and-options slot-descriptions :target)
359 `(progn ,@forms ',name)))
361 #+sb-xc-host
362 (defmacro sb!xc:defstruct (name-and-options &rest slot-descriptions)
363 #!+sb-doc
364 "Cause information about a target structure to be built into the
365 cross-compiler."
366 `(progn ,@(!expander-for-defstruct
367 t name-and-options slot-descriptions :host)))
369 ;;;; functions to generate code for various parts of DEFSTRUCT definitions
371 ;;; First, a helper to determine whether a name names an inherited
372 ;;; accessor.
373 (defun accessor-inherited-data (name defstruct)
374 (assoc name (dd-inherited-accessor-alist defstruct) :test #'eq))
376 ;;; Return a list of forms which create a predicate function for a
377 ;;; typed DEFSTRUCT.
378 (defun typed-predicate-definitions (defstruct)
379 (let ((name (dd-name defstruct))
380 (predicate-name (dd-predicate-name defstruct))
381 (argname 'x)) ; KISS: no user code appears in the DEFUN
382 (when predicate-name
383 (aver (dd-named defstruct))
384 (let ((ltype (dd-lisp-type defstruct))
385 (name-index (cdr (car (last (find-name-indices defstruct))))))
386 `((defun ,predicate-name (,argname)
387 (and (typep ,argname ',ltype)
388 ,(cond
389 ((subtypep ltype 'list)
390 `(do ((head (the ,ltype ,argname) (cdr head))
391 (i 0 (1+ i)))
392 ((or (not (consp head)) (= i ,name-index))
393 (and (consp head) (eq ',name (car head))))))
394 ((subtypep ltype 'vector)
395 `(and (>= (length (the ,ltype ,argname))
396 ,(dd-length defstruct))
397 (eq ',name (aref (the ,ltype ,argname) ,name-index))))
398 (t (bug "Unhandled representation type in typed DEFSTRUCT: ~
399 ~/sb!impl:print-type-specifier/."
400 ltype))))))))))
402 ;;; Return a list of forms to create a copier function of a typed DEFSTRUCT.
403 (defun typed-copier-definitions (defstruct)
404 (when (dd-copier-name defstruct)
405 `((setf (fdefinition ',(dd-copier-name defstruct)) #'copy-seq)
406 (declaim (ftype function ,(dd-copier-name defstruct))))))
408 ;;; Return a list of function definitions for accessing and setting
409 ;;; the slots of a typed DEFSTRUCT. The functions are proclaimed to be
410 ;;; inline, and the types of their arguments and results are declared
411 ;;; as well. We count on the compiler to do clever things with ELT.
412 (defun typed-accessor-definitions (defstruct)
413 (collect ((stuff))
414 (let ((ltype (dd-lisp-type defstruct)))
415 (dolist (slot (dd-slots defstruct))
416 (let ((name (dsd-accessor-name slot))
417 (index (dsd-index slot))
418 (new-value '(value))
419 (slot-type `(and ,(dsd-type slot)
420 ,(dd-element-type defstruct))))
421 (let ((inherited (accessor-inherited-data name defstruct)))
422 (cond
423 ((not inherited)
424 (stuff `(declaim (inline ,name ,@(unless (dsd-read-only slot)
425 `((setf ,name))))))
426 (stuff `(defun ,name (structure)
427 (declare (type ,ltype structure))
428 (the ,slot-type (elt structure ,index))))
429 (unless (dsd-read-only slot)
430 (stuff
431 `(defun (setf ,name) (,(car new-value) structure)
432 (declare (type ,ltype structure) (type ,slot-type . ,new-value))
433 (setf (elt structure ,index) . ,new-value)))))
434 ((not (= (cdr inherited) index))
435 (style-warn "~@<Non-overwritten accessor ~S does not access ~
436 slot with name ~S (accessing an inherited slot ~
437 instead).~:@>" name (dsd-name slot))))))))
438 (stuff)))
440 ;;;; parsing
442 ;;; CLHS says that
443 ;;; A defstruct option can be either a keyword or a list of a keyword
444 ;;; and arguments for that keyword; specifying the keyword by itself is
445 ;;; equivalent to specifying a list consisting of the keyword
446 ;;; and no arguments.
447 ;;; It is unclear whether that is meant to imply that any of the keywords
448 ;;; may be present in their atom form, or only if the grammar at the top
449 ;;; shows the atom form does <atom> have the meaning of (<atom>).
450 ;;; At least one other implementation accepts :NAMED as a singleton list.
451 ;; We take a more rigid view that the depicted grammar is exhaustive.
453 (defconstant-eqx +dd-option-names+
454 ;; Each keyword, except :CONSTRUCTOR which may appear more than once,
455 ;; and :NAMED which is trivial, and unambiguous if present more than
456 ;; once, though possibly worth a style-warning.
457 #(:include ; at least 1 argument
458 :initial-offset ; exactly 1 argument
459 :pure ; exactly 1 argument [nonstandard]
460 :type ; exactly 1 argument
461 :conc-name ; 0 or 1 arg
462 :copier ; "
463 :predicate ; "
464 :print-function ; "
465 :print-object) ; "
466 #'equalp)
468 ;;; Parse a single DEFSTRUCT option and store the results in DD.
469 (defun parse-1-dd-option (option dd seen-options)
470 (let* ((keyword (first option))
471 (bit (position keyword +dd-option-names+))
472 (args (rest option))
473 (arg-p (consp args))
474 (arg (if arg-p (car args)))
475 (name (dd-name dd)))
476 (declare (type (unsigned-byte 9) seen-options)) ; mask over DD-OPTION-NAMES
477 (when bit
478 (if (logbitp bit seen-options)
479 (error "More than one ~S option is not allowed" keyword)
480 (setf seen-options (logior seen-options (ash 1 bit))))
481 (multiple-value-bind (syntax-group winp)
482 (cond ; Perform checking per comment at +DD-OPTION-NAMES+.
483 ((= bit 0) (values 0 (and arg-p (proper-list-p args)))) ; >1 arg
484 ((< bit 4) (values 1 (and arg-p (not (cdr args))))) ; exactly 1
485 (t (values 2 (or (not args) (singleton-p args))))) ; 0 or 1
486 (unless winp
487 (if (proper-list-p option)
488 (error "DEFSTRUCT option ~S ~[requires at least~;~
489 requires exactly~;accepts at most~] one argument" keyword syntax-group)
490 (error "Invalid syntax in DEFSTRUCT option ~S" option)))))
491 (case keyword
492 (:conc-name
493 ;; unlike (:predicate) and (:copier) which mean "yes" if supplied
494 ;; without their argument, (:conc-name) and :conc-name mean no conc-name.
495 ;; Also note a subtle difference in :conc-name "" vs :conc-name NIL.
496 ;; The former re-interns each slot name into *PACKAGE* which might
497 ;; not be the same as using the given name directly as an accessor.
498 (setf (dd-conc-name dd) (if arg (string arg))))
499 (:constructor ; takes 0 to 2 arguments.
500 (destructuring-bind (&optional (cname (symbolicate "MAKE-" name))
501 (lambda-list nil ll-supplied-p)) args
502 (setf lambda-list
503 (cond ((not cname)
504 ;; Implementations disagree on the meaning of
505 ;; (:CONSTRUCTOR NIL (A B C)).
506 ;; The choices seem to be: don't define a constructor,
507 ;; define a constructor named NIL, signal a user error,
508 ;; or crash the system itself. The spec implies
509 ;; the behavior that we have, but at least a
510 ;; style-warning seems appropriate.
511 (when ll-supplied-p
512 (style-warn "~S does not define a constructor" option)))
513 ((not ll-supplied-p) :default)
515 (multiple-value-call
516 (lambda (&rest x)
517 (declare (dynamic-extent x))
518 (subseq x 0 ; remove trailing NILs
519 (1+ (position-if #'identity x :from-end t))))
520 (parse-lambda-list
521 lambda-list
522 :accept (lambda-list-keyword-mask
523 '(&optional &rest &key &allow-other-keys &aux))
524 :silent t))))
525 (dd-constructors dd) ; preserve order, just because
526 (nconc (dd-constructors dd) (list (cons cname lambda-list))))))
527 (:copier
528 (setf (dd-copier-name dd) (if arg-p arg (symbolicate "COPY-" name))))
529 (:predicate
530 (setf (dd-predicate-name dd) (if arg-p arg (symbolicate name "-P"))))
531 (:include
532 (setf (dd-include dd) args))
533 ((:print-function :print-object)
534 (when (dd-print-option dd)
535 (error "~S and ~S may not both be specified"
536 (dd-print-option dd) keyword))
537 (setf (dd-print-option dd) keyword (dd-printer-fname dd) arg))
538 (:type
539 (cond ((member arg '(list vector))
540 (setf (dd-type dd) arg (dd-element-type dd) t))
541 ((and (listp arg) (eq (first arg) 'vector))
542 (destructuring-bind (elt-type) (cdr arg)
543 (setf (dd-type dd) 'vector (dd-element-type dd) elt-type)))
545 (error "~S is a bad :TYPE for DEFSTRUCT." arg))))
546 (:named
547 (error "The DEFSTRUCT option :NAMED takes no arguments."))
548 (:initial-offset
549 (setf (dd-offset dd) arg)) ; FIXME: disallow (:INITIAL-OFFSET NIL)
550 (:pure
551 (setf (dd-pure dd) arg))
553 (error "unknown DEFSTRUCT option:~% ~S" option)))
554 seen-options))
556 ;;; Parse OPTIONS into the given DD.
557 (defun parse-defstruct-options (options dd)
558 (let ((seen-options 0)
559 (named-p nil))
560 (dolist (option options)
561 (if (eq option :named)
562 (setf named-p t (dd-named dd) t)
563 (setq seen-options
564 (parse-1-dd-option
565 (cond ((consp option) option)
566 ((member option
567 '(:conc-name :constructor :copier :predicate))
568 (list option))
570 ;; FIXME: ugly message (defstruct (s :include) a)
571 ;; saying "unrecognized" when it means "bad syntax"
572 (error "unrecognized DEFSTRUCT option: ~S" option)))
573 dd seen-options))))
574 (case (dd-type dd)
575 (structure
576 (when (dd-offset dd)
577 (error ":OFFSET can't be specified unless :TYPE is specified."))
578 #!-compact-instance-header
579 (unless (dd-include dd)
580 ;; FIXME: It'd be cleaner to treat no-:INCLUDE as defaulting
581 ;; to :INCLUDE STRUCTURE-OBJECT, and then let the general-case
582 ;; (INCF (DD-LENGTH DD) (DD-LENGTH included-DD)) logic take
583 ;; care of this. (Except that the :TYPE VECTOR and :TYPE
584 ;; LIST cases, with their :NAMED and un-:NAMED flavors,
585 ;; make that messy, alas.)
586 (incf (dd-length dd))))
588 ;; In case we are here, :TYPE is specified.
589 (if named-p
590 ;; CLHS - "The structure can be :named only if the type SYMBOL
591 ;; is a subtype of the supplied element-type."
592 (multiple-value-bind (winp certainp)
593 (subtypep 'symbol (dd-element-type dd))
594 (when (and (not winp) certainp)
595 (error ":NAMED option is incompatible with element ~
596 type ~/sb!impl:print-type-specifier/"
597 (dd-element-type dd))))
598 (when (dd-predicate-name dd)
599 (error ":PREDICATE cannot be used with :TYPE ~
600 unless :NAMED is also specified.")))
601 (awhen (dd-print-option dd)
602 (error ":TYPE option precludes specification of ~S option" it))
603 (when named-p
604 (incf (dd-length dd)))
605 (let ((offset (dd-offset dd)))
606 (when offset (incf (dd-length dd) offset)))))
608 (let ((name (dd-name dd)))
609 (collect ((keyword-ctors) (boa-ctors))
610 (let (no-constructors)
611 (dolist (constructor (dd-constructors dd))
612 (destructuring-bind (ctor-name . ll) constructor
613 (cond ((not ctor-name) (setq no-constructors t))
614 ((eq ll :default) (keyword-ctors constructor))
615 (t (boa-ctors constructor)))))
616 ;; Remove (NIL) and sort so that BOA constructors are last.
617 (setf (dd-constructors dd)
618 (if no-constructors
619 (progn
620 (when (or (keyword-ctors) (boa-ctors))
621 (error "(:CONSTRUCTOR NIL) combined with other :CONSTRUCTORs"))
622 nil)
623 (append (or (keyword-ctors)
624 (unless (boa-ctors)
625 `((,(symbolicate "MAKE-" name) . :default))))
626 (boa-ctors))))))
628 (flet ((option-present-p (bit-name)
629 (logbitp (position bit-name +dd-option-names+) seen-options)))
630 (declare (inline option-present-p))
631 (when (and (not (option-present-p :predicate))
632 (or (dd-class-p dd) named-p))
633 (setf (dd-predicate-name dd) (symbolicate name "-P")))
634 (unless (option-present-p :conc-name)
635 (setf (dd-conc-name dd) (string (gensymify* name "-"))))
636 (unless (option-present-p :copier)
637 (setf (dd-copier-name dd) (symbolicate "COPY-" name))))))
640 ;;; BOA constructors is (&aux x), i.e. without the default value, the
641 ;;; value of the slot is unspecified, but it should signal a type
642 ;;; error only when it's accessed. safe-p slot in dsd determines
643 ;;; whether to check the type after accessing the slot.
645 ;;; This was performed during boa constructor creating, but the
646 ;;; constructors are created after this information is used to inform
647 ;;; the compiler how to treat such slots.
648 (defun determine-unsafe-slots (dd)
649 (dolist (ctor (dd-constructors dd))
650 (let ((ll-parts (cdr ctor))) ; = (llks req opt rest key aux)
651 (dolist (var (if (listp ll-parts) (sixth ll-parts)))
652 (let* ((name (if (listp var) (car var) var))
653 (dsd (find name (dd-slots dd)
654 :key #'dsd-name
655 ;; FIXME: Not sure why this is #'EQ.
656 ;; Everywhere else we use STRING=.
657 :test #'eq)))
658 (when dsd
659 (setf (dsd-safe-p dsd) nil)))))))
661 ;;; Given name and options and slot descriptions (and possibly doc
662 ;;; string at the head of slot descriptions) return a DD holding that
663 ;;; info.
664 (defun parse-defstruct (null-env-p name-and-options slot-descriptions)
665 (binding* (((name options)
666 (if (listp name-and-options)
667 (values (car name-and-options) (cdr name-and-options))
668 (values name-and-options nil)))
669 (dd (make-defstruct-description null-env-p name)))
670 (parse-defstruct-options options dd)
671 (when (dd-include dd)
672 (frob-dd-inclusion-stuff dd))
673 (when (stringp (car slot-descriptions))
674 (setf (dd-doc dd) (pop slot-descriptions)))
675 (let* ((inherits
676 (if (dd-class-p dd)
677 #+sb-xc-host (!inherits-for-structure dd)
678 #-sb-xc-host
679 (let ((super (compiler-layout-or-lose (or (first (dd-include dd))
680 'structure-object))))
681 (concatenate 'simple-vector
682 (layout-inherits super) (vector super)))))
683 (proto-classoid
684 (if (dd-class-p dd)
685 (let* ((classoid (make-structure-classoid :name (dd-name dd)))
686 (layout (make-layout :classoid classoid :inherits inherits)))
687 (setf (layout-invalid layout) nil
688 (classoid-layout classoid) layout)
689 classoid))))
690 ;; Bind *pending-defstruct-type* to this classoid, which fixes a problem
691 ;; when redefining a DEFTYPE which appeared to be a raw slot. e.g.
692 ;; (DEFTYPE X () 'SINGLE-FLOAT) and later (DEFSTRUCT X (A 0 :TYPE X)).
693 ;; This is probably undefined behavior, but at least we'll not crash.
694 ;; Also make self-referential definitions not signal PARSE-UNKNOWN-TYPE
695 ;; on slots whose :TYPE option allows an instance of itself
696 (flet ((parse-slots ()
697 (dolist (slot-description slot-descriptions)
698 (allocate-1-slot dd (parse-1-dsd dd slot-description)))))
699 (if (dd-class-p dd)
700 (progn
701 (when (info :type :kind name)
702 ;; It could be buried anywhere in a complicated type expression.
703 ;; There's no way to clear selectively, so just flush the cache.
704 (values-specifier-type-cache-clear))
705 (let ((*pending-defstruct-type* proto-classoid))
706 (parse-slots)))
707 (parse-slots)))
708 (determine-unsafe-slots dd)
709 (values dd proto-classoid inherits))))
711 ;;;; stuff to parse slot descriptions
713 ;;; Parse a slot description for DEFSTRUCT, add it to the description
714 ;;; and return it. If supplied, SLOT is a pre-initialized DSD
715 ;;; that we modify to get the new slot. This is supplied when handling
716 ;;; included slots.
717 (defun parse-1-dsd (defstruct spec &optional
718 (slot (make-defstruct-slot-description :name ""
719 :index 0
720 :type t)))
721 #-sb-xc-host (declare (muffle-conditions style-warning))
722 (multiple-value-bind (name default default-p type type-p read-only ro-p)
723 (typecase spec
724 (symbol
725 (typecase spec
726 ((or null (member :conc-name :constructor :copier :predicate :named))
727 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" spec))
728 (keyword
729 (style-warn "slot name of ~S indicates possible syntax error in DEFSTRUCT" spec)))
730 spec)
731 (cons
732 (destructuring-bind
733 (name &optional (default nil default-p)
734 &key (type nil type-p) (read-only nil ro-p))
735 spec
736 (when (dd-conc-name defstruct)
737 ;; the warning here is useful, but in principle we cannot
738 ;; distinguish between legitimate and erroneous use of
739 ;; these names when :CONC-NAME is NIL. In the common
740 ;; case (CONC-NAME non-NIL), there are alternative ways
741 ;; of writing code with the same effect, so a full
742 ;; warning is justified.
743 (typecase name
744 ((member :conc-name :constructor :copier :predicate :include
745 :print-function :print-object :type :initial-offset :pure)
746 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" name))))
747 (values name default default-p
748 (uncross type) type-p
749 read-only ro-p)))
750 (t (error 'simple-program-error
751 :format-control "in DEFSTRUCT, ~S is not a legal slot ~
752 description."
753 :format-arguments (list spec))))
755 (when (find name (dd-slots defstruct)
756 :test #'string=
757 :key (lambda (x) (symbol-name (dsd-name x))))
758 (error 'simple-program-error
759 ;; Todo: indicate whether name is a duplicate in the directly
760 ;; specified slots vs. exists in the ancestor and so should
761 ;; be in the (:include ...) clause instead of where it is.
762 :format-control "duplicate slot name ~S"
763 :format-arguments (list name)))
764 (setf (dsd-name slot) name)
765 (setf (dd-slots defstruct) (nconc (dd-slots defstruct) (list slot)))
767 (let ((accessor-name (if (dd-conc-name defstruct)
768 (symbolicate (dd-conc-name defstruct) name)
769 name))
770 (predicate-name (dd-predicate-name defstruct)))
771 (setf (dsd-accessor-name slot) accessor-name)
772 (when (eql accessor-name predicate-name)
773 ;; Some adventurous soul has named a slot so that its accessor
774 ;; collides with the structure type predicate. ANSI doesn't
775 ;; specify what to do in this case. As of 2001-09-04, Martin
776 ;; Atzmueller reports that CLISP and Lispworks both give
777 ;; priority to the slot accessor, so that the predicate is
778 ;; overwritten. We might as well do the same (as well as
779 ;; signalling a warning).
780 (style-warn
781 "~@<The structure accessor name ~S is the same as the name of the ~
782 structure type predicate. ANSI doesn't specify what to do in ~
783 this case. We'll overwrite the type predicate with the slot ~
784 accessor, but you can't rely on this behavior, so it'd be wise to ~
785 remove the ambiguity in your code.~@:>"
786 accessor-name)
787 (setf (dd-predicate-name defstruct) nil))
788 ;; FIXME: It would be good to check for name collisions here, but
789 ;; the easy check,
790 ;;x#-sb-xc-host
791 ;;x(when (and (fboundp accessor-name)
792 ;;x (not (accessor-inherited-data accessor-name defstruct)))
793 ;;x (style-warn "redefining ~/sb-impl::print-symbol-with-prefix/ ~
794 ;; in DEFSTRUCT" accessor-name)))
795 ;; which was done until sbcl-0.8.11.18 or so, is wrong: it causes
796 ;; a warning at MACROEXPAND time, when instead the warning should
797 ;; occur not just because the code was constructed, but because it
798 ;; is actually compiled or loaded.
801 (when default-p
802 (setf (dsd-default slot) default))
803 (when type-p
804 (setf (dsd-type slot)
805 (if (eq (dsd-type slot) t)
806 type
807 `(and ,(dsd-type slot) ,type))))
808 (when ro-p
809 (if read-only
810 (setf (dsd-read-only slot) t)
811 (when (dsd-read-only slot)
812 (error "~@<The slot ~S is :READ-ONLY in superclass, and so must ~
813 be :READ-ONLY in subclass.~:@>"
814 (dsd-name slot)))))
815 slot))
817 ;;; When a value of type TYPE is stored in a structure, should it be
818 ;;; stored in a raw slot? Return the index of the matching RAW-SLOT-DATA
819 ;;; if TYPE should be stored in a raw slot, or NIL if not.
820 (defun structure-raw-slot-data-index (type)
821 (multiple-value-bind (fixnum? fixnum-certain?)
822 (sb!xc:subtypep type 'fixnum)
823 ;; (The extra test for FIXNUM-CERTAIN? here is intended for
824 ;; bootstrapping the system. In particular, in sbcl-0.6.2, we set up
825 ;; LAYOUT before FIXNUM is defined, and so could bogusly end up
826 ;; putting INDEX-typed values into raw slots if we didn't test
827 ;; FIXNUM-CERTAIN?.)
828 (if (or fixnum? (not fixnum-certain?))
830 (dotimes (i (length *raw-slot-data*))
831 (let ((data (svref *raw-slot-data* i)))
832 (when (sb!xc:subtypep type (raw-slot-data-raw-type data))
833 (return i)))))))
835 ;;; Allocate storage for a DSD in DD. This is where we decide whether
836 ;;; a slot is raw or not. Raw objects are aligned on the unit of their size.
837 (defun allocate-1-slot (dd dsd)
838 (let ((rsd-index (if (eq (dd-type dd) 'structure)
839 (structure-raw-slot-data-index (dsd-type dsd))
840 nil)))
841 (cond ((null rsd-index)
842 (setf (dsd-index dsd) (dd-length dd))
843 (incf (dd-length dd)))
845 (setf (dsd-%raw-type dsd) rsd-index)
846 (let* ((rsd (svref *raw-slot-data* rsd-index))
847 (words (raw-slot-data-n-words rsd))
848 (alignment (raw-slot-data-alignment rsd)))
849 (let ((len (dd-length dd)))
850 (setf (dd-length dd)
851 ;; this formula works but can it be made less unclear?
852 (- len (nth-value 1 (ceiling (1- len) alignment))))
853 (setf (dsd-index dsd) (dd-length dd))
854 (incf (dd-length dd) words))))))
855 (values))
857 (defun typed-structure-info-or-lose (name)
858 (or (info :typed-structure :info name)
859 (error ":TYPE'd DEFSTRUCT ~S not found for inclusion." name)))
861 ;;; Process any included slots pretty much like they were specified.
862 ;;; Also inherit various other attributes.
863 (defun frob-dd-inclusion-stuff (dd)
864 (destructuring-bind (included-name &rest modified-slots) (dd-include dd)
865 (let* ((type (dd-type dd))
866 (included-structure
867 (if (dd-class-p dd)
868 (layout-info (compiler-layout-or-lose included-name))
869 (typed-structure-info-or-lose included-name))))
871 ;; checks on legality
872 (unless (and (eq type (dd-type included-structure))
873 (type= (specifier-type (dd-element-type included-structure))
874 (specifier-type (dd-element-type dd))))
875 (error ":TYPE option mismatch between structures ~S and ~S"
876 (dd-name dd) included-name))
877 (let ((included-classoid (find-classoid included-name nil)))
878 (when included-classoid
879 ;; It's not particularly well-defined to :INCLUDE any of the
880 ;; CMU CL INSTANCE weirdosities like CONDITION or
881 ;; GENERIC-FUNCTION, and it's certainly not ANSI-compliant.
882 (let* ((included-layout (classoid-layout included-classoid))
883 (included-dd (layout-info included-layout)))
884 (when (dd-alternate-metaclass included-dd)
885 (error "can't :INCLUDE class ~S (has alternate metaclass)"
886 included-name)))))
888 ;; A few more sanity checks: every allegedly modified slot exists
889 ;; and no name appears more than once.
890 (flet ((included-slot-name (slot-desc)
891 (if (atom slot-desc) slot-desc (car slot-desc))))
892 (mapl (lambda (slots &aux (name (included-slot-name (car slots))))
893 (unless (find name (dd-slots included-structure)
894 :test #'string= :key #'dsd-name)
895 (error 'simple-program-error
896 :format-control "slot name ~S not present in included structure"
897 :format-arguments (list name)))
898 (when (find name (cdr slots)
899 :test #'string= :key #'included-slot-name)
900 (error 'simple-program-error
901 :format-control "included slot name ~S specified more than once"
902 :format-arguments (list name))))
903 modified-slots))
905 (incf (dd-length dd) (dd-length included-structure))
906 (when (dd-class-p dd)
907 (when (eq (dd-pure dd) :unspecified)
908 (setf (dd-pure dd) (dd-pure included-structure))))
910 (setf (dd-inherited-accessor-alist dd)
911 (dd-inherited-accessor-alist included-structure))
912 (dolist (included-slot (dd-slots included-structure))
913 (let* ((included-name (dsd-name included-slot))
914 (modified (or (find included-name modified-slots
915 :key (lambda (x) (if (atom x) x (car x)))
916 :test #'string=)
917 `(,included-name))))
918 ;; We stash away an alist of accessors to parents' slots
919 ;; that have already been created to avoid conflicts later
920 ;; so that structures with :INCLUDE and :CONC-NAME (and
921 ;; other edge cases) can work as specified.
922 (when (dsd-accessor-name included-slot)
923 ;; the "oldest" (i.e. highest up the tree of inheritance)
924 ;; will prevail, so don't push new ones on if they
925 ;; conflict.
926 (pushnew (cons (dsd-accessor-name included-slot)
927 (dsd-index included-slot))
928 (dd-inherited-accessor-alist dd)
929 :test #'eq :key #'car))
930 (let ((new-slot (parse-1-dsd dd
931 modified
932 (copy-structure included-slot))))
933 (when (and (neq (dsd-type new-slot) (dsd-type included-slot))
934 (not (sb!xc:subtypep (dsd-type included-slot)
935 (dsd-type new-slot)))
936 (dsd-safe-p included-slot))
937 (setf (dsd-safe-p new-slot) nil)
938 ;; XXX: notify?
939 )))))))
941 ;;;; various helper functions for setting up DEFSTRUCTs
943 ;;; This function is called at macroexpand time to compute the INHERITS
944 ;;; vector for a structure type definition.
945 ;;; The cross-compiler is allowed to magically compute LAYOUT-INHERITS.
946 (defun !inherits-for-structure (info)
947 (declare (type defstruct-description info))
948 (let* ((include (dd-include info))
949 (superclass-opt (dd-alternate-metaclass info))
950 (super
951 (if include
952 (compiler-layout-or-lose (first include))
953 (classoid-layout (find-classoid
954 (or (first superclass-opt)
955 'structure-object))))))
956 (case (dd-name info)
957 ((ansi-stream)
958 ;; STREAM is an abstract class and you can't :include it,
959 ;; so the inheritance has to be hardcoded.
960 (concatenate 'simple-vector
961 (layout-inherits super)
962 (vector super (classoid-layout (find-classoid 'stream)))))
963 ((fd-stream) ; Similarly, FILE-STREAM is abstract
964 (concatenate 'simple-vector
965 (layout-inherits super)
966 (vector super
967 (classoid-layout (find-classoid 'file-stream)))))
968 ((sb!impl::string-input-stream ; etc
969 sb!impl::string-output-stream
970 sb!impl::fill-pointer-output-stream)
971 (concatenate 'simple-vector
972 (layout-inherits super)
973 (vector super
974 (classoid-layout (find-classoid 'string-stream)))))
975 (t (concatenate 'simple-vector
976 (layout-inherits super)
977 (vector super))))))
979 ;;; Do miscellaneous (LOAD EVAL) time actions for the structure
980 ;;; described by DD. Create the class and LAYOUT, checking for
981 ;;; incompatible redefinition.
982 (defun %defstruct (dd inherits source-location)
983 (declare (type defstruct-description dd))
985 ;; We set up LAYOUTs even in the cross-compilation host.
986 (multiple-value-bind (classoid layout old-layout)
987 (ensure-structure-class dd inherits "current" "new")
988 (cond ((not old-layout)
989 (unless (eq (classoid-layout classoid) layout)
990 (register-layout layout)))
992 (%redefine-defstruct classoid old-layout layout)
993 (let ((old-dd (layout-info old-layout)))
994 (when (defstruct-description-p old-dd)
995 (dolist (slot (dd-slots old-dd))
996 (fmakunbound (dsd-accessor-name slot))
997 (unless (dsd-read-only slot)
998 (fmakunbound `(setf ,(dsd-accessor-name slot)))))))
999 (setq layout (classoid-layout classoid))))
1000 (setf (find-classoid (dd-name dd)) classoid)
1002 (when source-location
1003 (setf (layout-source-location layout) source-location))))
1006 ;;; Return a form accessing the writable place used for the slot
1007 ;;; described by DD and DSD in the INSTANCE (a form).
1008 (defun %accessor-place-form (dd dsd instance)
1009 (let (;; Compute REF even if not using it, as a sanity-check of DD-TYPE.
1010 (ref (ecase (dd-type dd)
1011 (structure '%instance-ref)
1012 (list 'nth)
1013 (vector 'aref)))
1014 (index (dsd-index dsd))
1015 (rsd (dsd-raw-slot-data dsd)))
1016 (if (not rsd) ; if not raw slot
1017 (multiple-value-call 'list ref
1018 (if (eq ref 'nth) (values index instance) (values instance index)))
1019 `(,(raw-slot-data-accessor-name rsd) ,instance ,index))))
1021 ;;; Return the transform of conceptual FUNCTION one of {:READ,:WRITE,:SETF}
1022 ;;; as applied to ARGS, given SLOT-KEY which is a cons of a DD and a DSD.
1023 ;;; Return NIL on failure.
1024 (defun slot-access-transform (function args slot-key)
1025 (when (consp args) ; need at least one arg
1026 (let* ((dd (car slot-key))
1027 (dsd (cdr slot-key))
1028 ;; optimistically compute PLACE before checking length of ARGS
1029 ;; because we expect success, and this unifies the three cases.
1030 ;; :SETF is like an invocation of the SETF macro - newval is
1031 ;; the second arg, but :WRITER is #'(SETF fn) - newval is first.
1032 (place
1033 (%accessor-place-form
1034 dd dsd `(the ,(dd-name dd)
1035 ,(car (if (eq function :write) (cdr args) args)))))
1036 (type-spec (dsd-type dsd)))
1037 (if (eq function :read)
1038 (when (singleton-p args)
1039 (if (eq type-spec t)
1040 place
1041 `(,(if (dsd-safe-p dsd) 'truly-the 'the) ,type-spec ,place)))
1042 (when (singleton-p (cdr args))
1043 (let ((inverse (info :setf :expander (car place))))
1044 (flet ((check (newval)
1045 (if (eq type-spec t) newval `(the ,type-spec ,newval))))
1046 (ecase function
1047 (:setf
1048 ;; Instance setters take newval last, which matches
1049 ;; the order in which a use of SETF has them.
1050 `(,inverse ,@(cdr place) ,(check (second args))))
1051 (:write
1052 ;; The call to #'(SETF fn) had newval first.
1053 ;; We need to preserve L-to-R evaluation.
1054 (once-only ((new (first args)))
1055 `(,inverse ,@(cdr place) ,(check new))))))))))))
1057 ;;; Return a LAMBDA form which can be used to set a slot
1058 (defun slot-setter-lambda-form (dd dsd)
1059 `(lambda (newval instance)
1060 ,(slot-access-transform :setf '(instance newval) (cons dd dsd))))
1062 ;;; Blow away all the compiler info for the structure CLASS. Iterate
1063 ;;; over this type, clearing the compiler structure type info, and
1064 ;;; undefining all the associated functions. If SUBCLASSES-P, also do
1065 ;;; the same for subclasses. FIXME: maybe rename UNDEFINE-FUN-NAME to
1066 ;;; UNDECLARE-FUNCTION-NAME?
1067 (defun undeclare-structure (classoid subclasses-p)
1068 (let ((info (layout-info (classoid-layout classoid))))
1069 (when (defstruct-description-p info)
1070 (let ((type (dd-name info)))
1071 (clear-info :type :compiler-layout type)
1072 ;; FIXME: shouldn't this undeclare any constructors too?
1073 (undefine-fun-name (dd-copier-name info))
1074 (undefine-fun-name (dd-predicate-name info))
1075 (dolist (slot (dd-slots info))
1076 (let ((fun (dsd-accessor-name slot)))
1077 (unless (accessor-inherited-data fun info)
1078 (undefine-fun-name fun)
1079 (unless (dsd-read-only slot)
1080 (undefine-fun-name `(setf ,fun)))))))
1081 ;; Clear out the SPECIFIER-TYPE cache so that subsequent
1082 ;; references are unknown types.
1083 (values-specifier-type-cache-clear)))
1084 (when subclasses-p
1085 (let ((subclasses (classoid-subclasses classoid)))
1086 (when subclasses
1087 (collect ((subs))
1088 (dohash ((classoid layout)
1089 subclasses
1090 :locked t)
1091 (declare (ignore layout))
1092 (undeclare-structure classoid nil)
1093 (subs (classoid-proper-name classoid)))
1094 ;; Is it really necessary to warn about
1095 ;; undeclaring functions for subclasses?
1096 (when (subs)
1097 (warn "undeclaring functions for old subclasses ~
1098 of ~S:~% ~S"
1099 (classoid-name classoid)
1100 (subs))))))))
1102 ;;; core compile-time setup of any class with a LAYOUT, used even by
1103 ;;; !DEFSTRUCT-WITH-ALTERNATE-METACLASS weirdosities
1104 (defun %compiler-set-up-layout (dd
1105 &optional
1106 ;; Several special cases
1107 ;; (STRUCTURE-OBJECT itself, and
1108 ;; structures with alternate
1109 ;; metaclasses) call this function
1110 ;; directly, and they're all at the
1111 ;; base of the instance class
1112 ;; structure, so this is a handy
1113 ;; default. (But note
1114 ;; FUNCALLABLE-STRUCTUREs need
1115 ;; assistance here)
1116 (inherits (vector (find-layout t))))
1118 (multiple-value-bind (classoid layout old-layout)
1119 (multiple-value-bind (clayout clayout-p)
1120 (info :type :compiler-layout (dd-name dd))
1121 (ensure-structure-class dd
1122 inherits
1123 (if clayout-p
1124 "The most recently compiled"
1125 "The current")
1126 "the most recently loaded"
1127 :compiler-layout clayout))
1128 (cond (old-layout
1129 (undeclare-structure (layout-classoid old-layout)
1130 (and (classoid-subclasses classoid)
1131 (not (eq layout old-layout))))
1132 (setf (layout-invalid layout) nil)
1133 ;; FIXME: it might be polite to hold onto old-layout and
1134 ;; restore it at the end of the file. -- RMK 2008-09-19
1135 ;; (International Talk Like a Pirate Day).
1136 (warn "~@<Clobbering the compiler's idea of the layout of ~A.~:@>"
1137 classoid))
1139 (unless (eq (classoid-layout classoid) layout)
1140 (register-layout layout :invalidate nil))
1141 (setf (find-classoid (dd-name dd)) classoid)))
1143 ;; At this point the class should be set up in the INFO database.
1144 ;; But the logic that enforces this is a little tangled and
1145 ;; scattered, so it's not obvious, so let's check.
1146 (aver (find-classoid (dd-name dd) nil))
1148 (setf (info :type :compiler-layout (dd-name dd)) layout))
1149 (values))
1151 (defun %proclaim-defstruct-ctors (dd)
1152 (dolist (ctor (dd-constructors dd))
1153 (let ((ftype (%struct-ctor-ftype dd (cdr ctor) (dd-element-type dd))))
1154 (sb!c:proclaim-ftype (car ctor) dd ftype :declared))))
1156 ;;; Do (COMPILE LOAD EVAL)-time actions for the normal (not
1157 ;;; ALTERNATE-LAYOUT) DEFSTRUCT described by DD.
1158 ;;; This includes generation of a style-warning about previously compiled
1159 ;;; calls to the accessors and/or predicate that weren't inlined.
1160 (defun %compiler-defstruct (dd inherits)
1161 (declare (type defstruct-description dd))
1163 (aver (dd-class-p dd)) ; LIST and VECTOR representation are not allowed
1164 (let ((check-inlining
1165 ;; Why use the secondary result of INFO, not the primary?
1166 ;; Because when DEFSTRUCT is evaluated, not via the file-compiler,
1167 ;; the first thing to happen is %DEFSTRUCT, which sets up FIND-CLASS.
1168 ;; Due to :COMPILER-LAYOUT's defaulting expression in globaldb,
1169 ;; it has a value - the layout of the classoid - that we don't want.
1170 ;; Also, since structures are technically not redefineable,
1171 ;; I don't worry about failure to inline a function that was
1172 ;; formerly not known as an accessor but now is.
1173 (null (nth-value 1 (info :type :compiler-layout (dd-name dd)))))
1174 (fnames))
1175 (%compiler-set-up-layout dd inherits)
1176 (%proclaim-defstruct-ctors dd)
1178 (awhen (dd-copier-name dd)
1179 (let ((dtype (dd-name dd)))
1180 (sb!xc:proclaim `(ftype (sfunction (,dtype) ,dtype) ,it))))
1182 (let ((predicate-name (dd-predicate-name dd)))
1183 (when predicate-name
1184 (when check-inlining
1185 (push predicate-name fnames))
1186 (setf (info :function :source-transform predicate-name)
1187 (cons dd :predicate))))
1189 (dolist (dsd (dd-slots dd))
1190 (let ((accessor-name (dsd-accessor-name dsd)))
1191 ;; Why this WHEN guard here, if there is neither a standards-specified
1192 ;; nor implementation-specific way to skip defining an accessor? Dunno.
1193 ;; And furthermore, by ignoring a package lock, it's possible to name
1194 ;; an accessor NIL: (defstruct (x (:conc-name "N")) IL)
1195 ;; making this test kinda bogus in two different ways.
1196 (when accessor-name
1197 (let ((inherited (accessor-inherited-data accessor-name dd)))
1198 (cond
1199 ((not inherited)
1200 (let ((writer `(setf ,accessor-name))
1201 (slot-key (cons dd dsd)))
1202 (when check-inlining
1203 (push accessor-name fnames))
1204 (setf (info :function :source-transform accessor-name)
1205 slot-key)
1206 (unless (dsd-read-only dsd)
1207 (when check-inlining
1208 (push writer fnames))
1209 (setf (info :function :source-transform writer) slot-key))))
1210 ((not (= (cdr inherited) (dsd-index dsd)))
1211 (style-warn "~@<Non-overwritten accessor ~S does not access ~
1212 slot with name ~S (accessing an inherited slot ~
1213 instead).~:@>"
1214 accessor-name
1215 (dsd-name dsd))))))))
1217 (awhen (remove-if-not #'sb!c::emitted-full-call-count fnames)
1218 (sb!c:compiler-style-warn
1219 'sb!c:inlining-dependency-failure
1220 ;; This message omits the http://en.wikipedia.org/wiki/Serial_comma
1221 :format-control "~@<Previously compiled call~P to ~
1222 ~{~/sb!impl:print-symbol-with-prefix/~^~#[~; and~:;,~] ~} ~
1223 could not be inlined because the structure definition for ~
1224 ~/sb!impl:print-symbol-with-prefix/ was not yet seen. To avoid this warning, ~
1225 DEFSTRUCT should precede references to the affected functions, ~
1226 or they must be declared locally notinline at each call site.~@:>"
1227 :format-arguments (list (length it) (nreverse it) (dd-name dd))))))
1229 ;;;; redefinition stuff
1231 ;;; Compare the slots of OLD and NEW, returning 3 lists of slot names:
1232 ;;; 1. Slots which have moved,
1233 ;;; 2. Slots whose type has changed,
1234 ;;; 3. Deleted slots.
1235 (defun compare-slots (old new)
1236 (let* ((oslots (dd-slots old))
1237 (nslots (dd-slots new))
1238 (onames (mapcar #'dsd-name oslots))
1239 (nnames (mapcar #'dsd-name nslots)))
1240 (collect ((moved)
1241 (retyped))
1242 (dolist (name (intersection onames nnames))
1243 (let ((os (find name oslots :key #'dsd-name :test #'string=))
1244 (ns (find name nslots :key #'dsd-name :test #'string=)))
1245 (unless (sb!xc:subtypep (dsd-type ns) (dsd-type os))
1246 (retyped name))
1247 (unless (and (= (dsd-index os) (dsd-index ns))
1248 (eq (dsd-raw-type os) (dsd-raw-type ns)))
1249 (moved name))))
1250 (values (moved)
1251 (retyped)
1252 (set-difference onames nnames :test #'string=)))))
1254 ;;; If we are redefining a structure with different slots than in the
1255 ;;; currently loaded version, give a warning and return true.
1256 (defun redefine-structure-warning (classoid old new)
1257 (declare (type defstruct-description old new)
1258 (type classoid classoid)
1259 (ignore classoid))
1260 (let ((name (dd-name new)))
1261 (multiple-value-bind (moved retyped deleted) (compare-slots old new)
1262 (when (or moved retyped deleted)
1263 (warn
1264 "incompatibly redefining slots of structure class ~S~@
1265 Make sure any uses of affected accessors are recompiled:~@
1266 ~@[ These slots were moved to new positions:~% ~S~%~]~
1267 ~@[ These slots have new incompatible types:~% ~S~%~]~
1268 ~@[ These slots were deleted:~% ~S~%~]"
1269 name moved retyped deleted)
1270 t))))
1272 ;;; This function is called when we are incompatibly redefining a
1273 ;;; structure CLASS to have the specified NEW-LAYOUT. We signal an
1274 ;;; error with some proceed options and return the layout that should
1275 ;;; be used.
1276 (defun %redefine-defstruct (classoid old-layout new-layout)
1277 (declare (type classoid classoid)
1278 (type layout old-layout new-layout))
1279 (let ((name (classoid-proper-name classoid)))
1280 (restart-case
1281 (error "~@<attempt to redefine the ~S class ~S incompatibly with the current definition~:@>"
1282 'structure-object
1283 name)
1284 (continue ()
1285 :report (lambda (s)
1286 (format s
1287 "~@<Use the new definition of ~S, invalidating ~
1288 already-loaded code and instances.~@:>"
1289 name))
1290 (register-layout new-layout))
1291 (recklessly-continue ()
1292 :report (lambda (s)
1293 (format s
1294 "~@<Use the new definition of ~S as if it were ~
1295 compatible, allowing old accessors to use new ~
1296 instances and allowing new accessors to use old ~
1297 instances.~@:>"
1298 name))
1299 ;; classic CMU CL warning: "Any old ~S instances will be in a bad way.
1300 ;; I hope you know what you're doing..."
1301 (register-layout new-layout
1302 :invalidate nil
1303 :destruct-layout old-layout))
1304 (clobber-it ()
1305 ;; FIXME: deprecated 2002-10-16, and since it's only interactive
1306 ;; hackery instead of a supported feature, can probably be deleted
1307 ;; in early 2003
1308 :report "(deprecated synonym for RECKLESSLY-CONTINUE)"
1309 (register-layout new-layout
1310 :invalidate nil
1311 :destruct-layout old-layout))))
1312 (values))
1314 ;;; Compute DD's bitmap, storing 1 for each tagged word.
1315 ;;; The bitmap should be stored as a negative fixnum in two cases:
1316 ;;; (1) if the positive value is a bignum but the negative is a fixnum.
1317 ;;; (2) if there are no raw slots at all.
1318 ;;; Example: given (DEFSTRUCT S A B C), the computed bitmap is #b11111 -
1319 ;;; one bit for the layout; one each for A, B, C; and one for padding.
1320 ;;; Whether this is stored as 31 or -1 is mostly immaterial,
1321 ;;; but -1 is preferable because GC has a special case for it.
1322 ;;; Suppose instead we have 1 untagged word followed by N tagged words
1323 ;;; for N > n-fixnum-bits. The computed bitmap is #b111...11101
1324 ;;; but the sign-extended value is -3, which is a fixnum.
1325 ;;; If both the + and - values are fixnums, and raw slots are present,
1326 ;;; we'll choose the positive value.
1327 (defun dd-bitmap (dd)
1328 ;; Without compact instances, the 0th bit is always 1.
1329 ;; LAYOUT is tagged but not reflected in DD-SLOTS
1330 (let ((bitmap sb!vm:instance-data-start))
1331 (dolist (slot (dd-slots dd))
1332 (when (eql t (dsd-raw-type slot))
1333 (setf bitmap (logior bitmap (ash 1 (dsd-index slot))))))
1334 (let* ((length (dd-length dd))
1335 (n-bits (logior length 1)))
1336 (when (evenp length) ; Add padding word if necessary.
1337 (setq bitmap (logior bitmap (ash 1 length))))
1338 (when (logbitp (1- n-bits) bitmap)
1339 (let ((sign-ext (logior (ash -1 n-bits) bitmap)))
1340 (when (or (and (fixnump sign-ext) (sb!xc:typep bitmap 'bignum))
1341 (eql sign-ext -1))
1342 (return-from dd-bitmap sign-ext)))))
1343 bitmap))
1345 ;;; This is called when we are about to define a structure class. It
1346 ;;; returns a (possibly new) class object and the layout which should
1347 ;;; be used for the new definition (may be the current layout, and
1348 ;;; also might be an uninstalled forward referenced layout.) The third
1349 ;;; value is true if this is an incompatible redefinition, in which
1350 ;;; case it is the old layout.
1351 (defun ensure-structure-class (info inherits old-context new-context
1352 &key compiler-layout)
1353 (declare (type defstruct-description info))
1354 (multiple-value-bind (class old-layout)
1355 (multiple-value-bind (class constructor)
1356 (acond ((cdr (dd-alternate-metaclass info))
1357 (values (first it) (second it)))
1359 (values 'structure-classoid 'make-structure-classoid)))
1360 (insured-find-classoid (dd-name info)
1361 (if (eq class 'structure-classoid)
1362 (lambda (x)
1363 (sb!xc:typep x 'structure-classoid))
1364 (lambda (x)
1365 (sb!xc:typep x (classoid-name (find-classoid class)))))
1366 (fdefinition constructor)))
1367 (setf (classoid-direct-superclasses class)
1368 (case (dd-name info)
1369 ((ansi-stream
1370 fd-stream
1371 sb!impl::string-input-stream sb!impl::string-output-stream
1372 sb!impl::fill-pointer-output-stream)
1373 (list (layout-classoid (svref inherits (1- (length inherits))))
1374 (layout-classoid (svref inherits (- (length inherits) 2)))))
1376 (list (layout-classoid
1377 (svref inherits (1- (length inherits))))))))
1378 (let* ((old-layout (or compiler-layout old-layout))
1379 (new-layout
1380 (when (or (not old-layout) *type-system-initialized*)
1381 (make-layout :classoid class
1382 :inherits inherits
1383 :depthoid (length inherits)
1384 :length (dd-length info)
1385 :info info
1386 :bitmap (dd-bitmap info)))))
1387 (cond
1388 ((not old-layout)
1389 (values class new-layout nil))
1390 ((not new-layout)
1391 ;; The assignment of INFO here can almost be deleted,
1392 ;; except for a few magical types that don't d.t.r.t. in cold-init:
1393 ;; STRUCTURE-OBJECT, CONDITION, ALIEN-VALUE, INTERPRETED-FUNCTION
1394 (setf (layout-info old-layout) info)
1395 (values class old-layout nil))
1396 (;; This clause corresponds to an assertion in REDEFINE-LAYOUT-WARNING
1397 ;; of classic CMU CL. I moved it out to here because it was only
1398 ;; exercised in this code path anyway. -- WHN 19990510
1399 (not (eq (layout-classoid new-layout) (layout-classoid old-layout)))
1400 (error "shouldn't happen: weird state of OLD-LAYOUT?"))
1401 ((redefine-layout-warning old-context
1402 old-layout
1403 new-context
1404 (layout-length new-layout)
1405 (layout-inherits new-layout)
1406 (layout-depthoid new-layout)
1407 (layout-bitmap new-layout))
1408 (values class new-layout old-layout))
1410 (let ((old-info (layout-info old-layout)))
1411 (if old-info
1412 (cond ((redefine-structure-warning class old-info info)
1413 (values class new-layout old-layout))
1415 (setf (layout-info old-layout) info)
1416 (values class old-layout nil)))
1417 (progn
1418 (setf (layout-info old-layout) info)
1419 (values class old-layout nil)))))))))
1421 ;;; Return a list of pairs (name . index). Used for :TYPE'd
1422 ;;; constructors to find all the names that we have to splice in &
1423 ;;; where. Note that these types don't have a layout, so we can't look
1424 ;;; at LAYOUT-INHERITS.
1425 (defun find-name-indices (defstruct)
1426 (collect ((res))
1427 (let ((infos ()))
1428 (do ((info defstruct
1429 (typed-structure-info-or-lose (first (dd-include info)))))
1430 ((not (dd-include info))
1431 (push info infos))
1432 (push info infos))
1434 (let ((i 0))
1435 (dolist (info infos)
1436 (incf i (or (dd-offset info) 0))
1437 (when (dd-named info)
1438 (res (cons (dd-name info) i)))
1439 (setq i (dd-length info)))))
1441 (res)))
1443 ;;; These functions are called to actually make a constructor after we
1444 ;;; have processed the arglist. The correct variant (according to the
1445 ;;; DD-TYPE) should be called. The function is defined with the
1446 ;;; specified name and arglist. VARS and TYPES are used for argument
1447 ;;; type declarations. VALUES are the values for the slots (in order.)
1449 ;;; This is split into two functions:
1450 ;;; * INSTANCE-CONSTRUCTOR-FORM has to deal with raw slots
1451 ;;; (there are two variations on this)
1452 ;;; * TYPED-CONSTRUCTOR-FORM deal with LIST & VECTOR
1453 ;;; which might have "name" symbols stuck in at various weird places.
1454 (defun instance-constructor-form (dd values)
1455 ;; The difference between the two implementations here is that on all
1456 ;; platforms we don't have the appropriate RAW-INSTANCE-INIT VOPS, which
1457 ;; must be able to deal with immediate values as well -- unlike
1458 ;; RAW-INSTANCE-SET VOPs, which never end up seeing immediate values. With
1459 ;; some additional cleverness we might manage without them and just a single
1460 ;; implementation here, though -- figure out a way to ensure that on those
1461 ;; platforms we always still get a non-immediate TN in every case...
1463 ;; Until someone does that, this means that instances with raw slots can be
1464 ;; DX allocated only on platforms with those additional VOPs.
1465 (let ((dd-slots (dd-slots dd)))
1466 (aver (= (length dd-slots) (length values)))
1467 #!+raw-instance-init-vops
1468 (collect ((slot-specs) (slot-values))
1469 (mapc (lambda (dsd value)
1470 (unless (eq value '.do-not-initialize-slot.)
1471 (slot-specs (list* :slot (dsd-raw-type dsd) (dsd-index dsd)))
1472 (slot-values value)))
1473 dd-slots values)
1474 `(%make-structure-instance-macro ,dd ',(slot-specs) ,@(slot-values)))
1475 #!-raw-instance-init-vops
1476 (collect ((slot-specs) (slot-values) (raw-slots) (raw-values))
1477 ;; Partition into non-raw and raw
1478 (mapc (lambda (dsd value)
1479 (unless (eq value '.do-not-initialize-slot.)
1480 (let ((raw-type (dsd-raw-type dsd)))
1481 (cond ((eq t raw-type)
1482 (slot-specs (list* :slot raw-type (dsd-index dsd)))
1483 (slot-values value))
1485 (raw-slots dsd)
1486 (raw-values value))))))
1487 dd-slots values)
1488 (let ((instance-form
1489 `(%make-structure-instance-macro ,dd
1490 ',(slot-specs) ,@(slot-values))))
1491 (if (raw-slots)
1492 (let ((temp (make-symbol "INSTANCE")))
1493 `(let ((,temp ,instance-form))
1494 ;; Transform to %RAW-INSTANCE-SET/foo, not SETF,
1495 ;; in case any slots are readonly.
1496 ,@(mapcar (lambda (dsd value)
1497 (slot-access-transform
1498 :setf (list temp value) (cons dd dsd)))
1499 (raw-slots) (raw-values))
1500 ,temp))
1501 instance-form)))))
1503 ;;; A "typed" constructors prefers to use a single call to LIST or VECTOR
1504 ;;; if possible, but can't always do that for VECTOR because it might not
1505 ;;; be a (VECTOR T). If not, we fallback to MAKE-ARRAY and (SETF AREF).
1506 (defun typed-constructor-form (dd values)
1507 (multiple-value-bind (operator initial-element)
1508 (cond ((and (eq (dd-type dd) 'vector) (eq (dd-element-type dd) t))
1509 (values 'vector 0))
1510 ((eq (dd-type dd) 'list)
1511 (values 'list nil)))
1512 (let* ((length (dd-length dd))
1513 (slots (dd-slots dd))
1514 ;; Possibly the most useless feature ever: more than one name slot.
1515 (names (find-name-indices dd)))
1516 (aver (= (length slots) (length values)))
1517 (if operator
1518 ;; The initial-element provides values for slots that are skipped
1519 ;; due to :initial-offset, not slots that are skipped due to
1520 ;; &AUX variables with no initial value.
1521 (let ((vals (make-list length :initial-element initial-element)))
1522 (dolist (x names)
1523 (setf (elt vals (cdr x)) `',(car x)))
1524 (mapc (lambda (dsd val)
1525 ;; For both vectors and lists, .DO-NOT-INITIALIZE-SLOT.
1526 ;; becomes 0 even though lists otherwise use NIL for slots
1527 ;; that are skipped to due :initial-offset.
1528 (setf (elt vals (dsd-index dsd))
1529 ;; All VALs have been wrapped in THE if necessary.
1530 (if (eq val '.do-not-initialize-slot.) 0 val)))
1531 slots values)
1532 (cons operator vals))
1533 (let ((temp (make-symbol "OBJ")))
1534 `(let ((,temp (make-array ,length
1535 :element-type ',(dd-element-type dd))))
1536 ,@(mapcar (lambda (x) `(setf (aref ,temp ,(cdr x)) ',(car x)))
1537 names)
1538 ,@(mapcan (lambda (dsd val)
1539 (unless (eq val '.do-not-initialize-slot.)
1540 `((setf (aref ,temp ,(dsd-index dsd)) ,val))))
1541 slots values)
1542 ,temp))))))
1544 ;;; Return the FTYPE for a DD constructor.
1545 ;;; This is tricky in uses such as the following:
1546 ;;; (DEFSTRUCT (S (:CONSTRUCTOR MS (A &AUX (A (ABS A))))) (A 0 :TYPE (MOD 4)))
1547 ;;; The constructor accepts integers betweeen -3 and 3 because the &AUX binding
1548 ;;; hides the positional argument A, and we can't actually put any constraint
1549 ;;; on A unless we figure out what the action of ABS is.
1551 ;;; The FTYPE is actually not a strong enough constraint anyway, so when IR1
1552 ;;; tests for the call compatibility it will test for correctness *after*
1553 ;;; argument defaulting.
1554 (defun %struct-ctor-ftype (dd args elt-type)
1555 (flet ((elt-type-intersect (dsd &aux (slot-type (dsd-type dsd)))
1556 (cond ((eq slot-type t) elt-type)
1557 ((eq elt-type t) slot-type)
1558 (t `(and ,elt-type ,slot-type)))))
1559 `(function
1560 ,(if (eq args :default)
1561 `(&key ,@(mapcar (lambda (dsd)
1562 `(,(keywordicate (dsd-name dsd))
1563 ,(elt-type-intersect dsd)))
1564 (dd-slots dd)))
1565 (destructuring-bind (llks &optional req opt rest keys aux) args
1566 (let ((aux (mapcar (lambda (var) (if (listp var) (car var) var))
1567 aux)))
1568 (flet ((get-arg-type (name)
1569 (let ((slot (unless (member name aux :test #'string=)
1570 (find name (dd-slots dd) :key #'dsd-name
1571 :test #'string=))))
1572 ;; If no slot, the arg restriction is T,
1573 ;; because we don't know where it goes.
1574 (if slot (elt-type-intersect slot) t))))
1575 (make-lambda-list
1576 llks nil (mapcar #'get-arg-type req)
1577 (mapcar (lambda (arg)
1578 (get-arg-type (parse-optional-arg-spec arg)))
1579 opt)
1580 (if rest (list t))
1581 (mapcar (lambda (arg)
1582 (multiple-value-bind (key var) (parse-key-arg-spec arg)
1583 `(,key ,(get-arg-type var))))
1584 keys))))))
1585 (values ,(cond ((dd-class-p dd) (dd-name dd))
1586 ((eq (dd-type dd) 'list) 'list)
1587 (t `(vector ,(dd-element-type dd) ,(dd-length dd))))
1588 &optional))))
1590 (defun struct-ctor-ftype (dd name)
1591 (let ((ctor (assq name (dd-constructors dd))))
1592 (aver ctor)
1593 (%struct-ctor-ftype dd (cdr ctor) (dd-element-type dd))))
1595 (defun proclaimed-ftype (name)
1596 (multiple-value-bind (info foundp) (info :function :type name)
1597 (values (cond ((defstruct-description-p info)
1598 (specifier-type (struct-ctor-ftype info name)))
1599 #-sb-xc-host ; PCL doesn't exist
1600 ((eq info :generic-function) (sb!pcl::compute-gf-ftype name))
1601 (t info))
1602 foundp)))
1604 ;;; Given a DD and a constructor spec (a cons of name and pre-parsed
1605 ;;; BOA lambda list, or the symbol :DEFAULT), return the effective
1606 ;;; lambda list and the body of the lambda.
1607 (defun structure-ctor-lambda-parts
1608 (dd args &aux (creator (ecase (dd-type dd)
1609 (structure #'instance-constructor-form)
1610 ((list vector) #'typed-constructor-form))))
1611 (when (eq args :default)
1612 (let ((lambda-list (mapcar (lambda (dsd)
1613 (let* ((temp (copy-symbol (dsd-name dsd)))
1614 (keyword (keywordicate temp)))
1615 `((,keyword ,temp) ,(dsd-default dsd))))
1616 (dd-slots dd))))
1617 (return-from structure-ctor-lambda-parts
1618 `((&key ,@lambda-list)
1619 (declare (explicit-check))
1620 ,(funcall creator dd
1621 (mapcar (lambda (dsd arg)
1622 (let ((type (dsd-type dsd))
1623 (var (cadar arg)))
1624 (if (eq type t) var `(the ,type ,var))))
1625 (dd-slots dd) lambda-list))))))
1626 (destructuring-bind (llks &optional req opt rest keys aux) args
1627 (collect ((vars (copy-list req)) ; list of bound vars
1628 (aux-vars)
1629 (skipped-vars))
1630 (dolist (binding aux)
1631 (let ((name (if (listp binding) (car binding) binding)))
1632 (aux-vars name)
1633 (unless (typep binding '(cons t cons))
1634 (skipped-vars name))))
1635 (macrolet ((rewrite (input key parse)
1636 `(mapcar
1637 (lambda (arg)
1638 (multiple-value-bind (,@key var def sup-p) (,parse arg)
1639 (declare (ignore ,@key def))
1640 (rewrite-1 arg var sup-p)))
1641 ,input)))
1642 (flet ((rewrite-1 (arg var sup-p-var)
1643 (vars var)
1644 (when sup-p-var (vars (car sup-p-var)))
1645 (let* ((slot (unless (member var (aux-vars) :test #'string=)
1646 (find var (dd-slots dd)
1647 :key #'dsd-name :test #'string=)))
1648 (default (and slot (dsd-default slot))))
1649 ;; If VAR initializes a slot and did not have a default in
1650 ;; the lambda list, and DSD-DEFAULT is not NIL,
1651 ;; then change the lambda-list's default for the variable.
1652 ;; Always prefer to insert (CAR ARG) if ARG was a list
1653 ;; so that (:KEY var) syntax is preserved.
1654 (if (and slot (not (typep arg '(cons t cons))) default)
1655 `(,(if (consp arg) (car arg) var) ,default ,@sup-p-var)
1656 arg)))) ; keep it as it was
1657 ;; Can we substitute symbols that are not EQ to symbols
1658 ;; naming slots, so we don't have to compare by STRING= later?
1659 ;; Probably not because other symbols could reference them.
1660 (setq opt (rewrite opt () parse-optional-arg-spec))
1661 (when rest (vars (car rest)))
1662 (setq keys (rewrite keys (key) parse-key-arg-spec))
1663 (dolist (arg (aux-vars)) (vars arg))))
1664 `(,(sb!c::make-lambda-list
1665 llks nil req opt rest keys
1666 ;; &AUX vars which do not initialize a slot are not mentioned
1667 ;; in the lambda list, though it's not clear what to do if
1668 ;; subsequent bindings refer to the deleted ones.
1669 ;; And worse, what if it's SETQd - is that even legal?
1670 (remove-if (lambda (x) (not (typep x '(cons t cons)))) aux))
1671 (declare (explicit-check))
1672 ,(funcall
1673 creator dd
1674 (mapcar
1675 (lambda (slot &aux (name (dsd-name slot)))
1676 (if (find name (skipped-vars) :test #'string=)
1677 ;; CLHS 3.4.6 Boa Lambda Lists
1678 '.do-not-initialize-slot.
1679 (let* ((type (dsd-type slot))
1680 (found (member (dsd-name slot) (vars) :test #'string=))
1681 (initform (if found (car found) (dsd-default slot))))
1682 ;; We can ignore the DD-ELEMENT-TYPE
1683 ;; because the container itself will check.
1684 (if (eq type t) initform `(the ,type ,initform)))))
1685 (dd-slots dd)))))))
1687 (defun accessor-definitions (dd *pending-defstruct-type*)
1688 (loop for dsd in (dd-slots dd)
1689 for accessor-name = (dsd-accessor-name dsd)
1690 unless (accessor-inherited-data accessor-name dd)
1691 nconc (dx-let ((key (cons dd dsd)))
1692 `(,@(unless (dsd-read-only dsd)
1693 `((defun (setf ,accessor-name) (value instance)
1694 ,(slot-access-transform :setf '(instance value) key))))
1695 (defun ,accessor-name (instance)
1696 ,(slot-access-transform :read '(instance) key))))))
1698 ;;;; instances with ALTERNATE-METACLASS
1699 ;;;;
1700 ;;;; The CMU CL support for structures with ALTERNATE-METACLASS was a
1701 ;;;; fairly general extension embedded in the main DEFSTRUCT code, and
1702 ;;;; the result was an fairly impressive mess as ALTERNATE-METACLASS
1703 ;;;; extension mixed with ANSI CL generality (e.g. :TYPE and :INCLUDE)
1704 ;;;; and CMU CL implementation hairiness (esp. raw slots). This SBCL
1705 ;;;; version is much less ambitious, noticing that ALTERNATE-METACLASS
1706 ;;;; is only used to implement CONDITION, STANDARD-INSTANCE, and
1707 ;;;; GENERIC-FUNCTION, and defining a simple specialized
1708 ;;;; separate-from-DEFSTRUCT macro to provide only enough
1709 ;;;; functionality to support those.
1710 ;;;;
1711 ;;;; KLUDGE: The defining macro here is so specialized that it's ugly
1712 ;;;; in its own way. It also violates once-and-only-once by knowing
1713 ;;;; much about structures and layouts that is already known by the
1714 ;;;; main DEFSTRUCT macro. Hopefully it will go away presently
1715 ;;;; (perhaps when CL:CLASS and SB-PCL:CLASS meet) as per FIXME below.
1716 ;;;; -- WHN 2001-10-28
1717 ;;;;
1718 ;;;; FIXME: There seems to be no good reason to shoehorn CONDITION,
1719 ;;;; STANDARD-INSTANCE, and GENERIC-FUNCTION into mutated structures
1720 ;;;; instead of just implementing them as primitive objects. (This
1721 ;;;; reduced-functionality macro seems pretty close to the
1722 ;;;; functionality of !DEFINE-PRIMITIVE-OBJECT..)
1724 ;;; The complete list of alternate-metaclass DEFSTRUCTs:
1725 ;;; CONDITION SB-EVAL:INTERPRETED-FUNCTION
1726 ;;; SB-PCL::STANDARD-INSTANCE SB-PCL::STANDARD-FUNCALLABLE-INSTANCE
1727 ;;; SB-PCL::CTOR SB-PCL::%METHOD-FUNCTION
1729 (defun make-dd-with-alternate-metaclass (&key (class-name (missing-arg))
1730 (superclass-name (missing-arg))
1731 (metaclass-name (missing-arg))
1732 (dd-type (missing-arg))
1733 metaclass-constructor
1734 slot-names)
1735 (let* ((dd (make-defstruct-description t class-name))
1736 (conc-name (string (gensymify* class-name "-")))
1737 (dd-slots (let ((reversed-result nil)
1738 ;; The index starts at 1 for ordinary named
1739 ;; slots because slot 0 is magical, used for
1740 ;; the LAYOUT in CONDITIONs and
1741 ;; FUNCALLABLE-INSTANCEs. (This is the same
1742 ;; in ordinary structures too: see (INCF
1743 ;; DD-LENGTH) in
1744 ;; PARSE-DEFSTRUCT-NAME-AND-OPTIONS).
1745 (index 1))
1746 (dolist (slot-name slot-names)
1747 (push (make-defstruct-slot-description
1748 :name slot-name
1749 :index index
1750 :accessor-name (symbolicate conc-name slot-name))
1751 reversed-result)
1752 (incf index))
1753 (nreverse reversed-result))))
1754 ;; We do *not* fill in the COPIER-NAME and PREDICATE-NAME
1755 ;; because none of the magical alternate-metaclass structures
1756 ;; have copiers and predicates that "Just work"
1757 (case dd-type
1758 ;; We don't support inheritance of alternate metaclass stuff,
1759 ;; and it's not a general-purpose facility, so sanity check our
1760 ;; own code.
1761 (structure
1762 (aver (eq superclass-name 't)))
1763 (funcallable-structure
1764 (aver (eq superclass-name 'function)))
1765 (t (bug "Unknown DD-TYPE in ALTERNATE-METACLASS: ~S" dd-type)))
1766 (setf (dd-alternate-metaclass dd) (list superclass-name
1767 metaclass-name
1768 metaclass-constructor)
1769 (dd-slots dd) dd-slots
1770 (dd-length dd) (1+ (length slot-names))
1771 (dd-type dd) dd-type)
1772 dd))
1774 ;;; make !DEFSTRUCT-WITH-ALTERNATE-METACLASS compilable by the host
1775 ;;; lisp, installing the information we need to reason about the
1776 ;;; structures (layouts and classoids).
1778 ;;; FIXME: we should share the parsing and the DD construction between
1779 ;;; this and the cross-compiler version, but my brain was too small to
1780 ;;; get that right. -- CSR, 2006-09-14
1781 #+sb-xc-host
1782 (defmacro !defstruct-with-alternate-metaclass
1783 (class-name &key
1784 (slot-names (missing-arg))
1785 (boa-constructor (missing-arg))
1786 (superclass-name (missing-arg))
1787 (metaclass-name (missing-arg))
1788 (metaclass-constructor (missing-arg))
1789 (dd-type (missing-arg))
1790 predicate
1791 (runtime-type-checks-p t))
1793 (declare (type (and list (not null)) slot-names))
1794 (declare (type (and symbol (not null))
1795 boa-constructor
1796 superclass-name
1797 metaclass-name
1798 metaclass-constructor))
1799 (declare (type symbol predicate))
1800 (declare (type (member structure funcallable-structure) dd-type))
1801 (declare (ignore boa-constructor predicate runtime-type-checks-p))
1803 (let* ((dd (make-dd-with-alternate-metaclass
1804 :class-name class-name
1805 :slot-names slot-names
1806 :superclass-name superclass-name
1807 :metaclass-name metaclass-name
1808 :metaclass-constructor metaclass-constructor
1809 :dd-type dd-type)))
1810 `(progn
1812 (eval-when (:compile-toplevel :load-toplevel :execute)
1813 (%compiler-set-up-layout ',dd ',(!inherits-for-structure dd))))))
1815 (sb!xc:defmacro !defstruct-with-alternate-metaclass
1816 (class-name &key
1817 (slot-names (missing-arg))
1818 (boa-constructor (missing-arg))
1819 (superclass-name (missing-arg))
1820 (metaclass-name (missing-arg))
1821 (metaclass-constructor (missing-arg))
1822 (dd-type (missing-arg))
1823 predicate
1824 (runtime-type-checks-p t))
1826 (declare (type (and list (not null)) slot-names))
1827 (declare (type (and symbol (not null))
1828 boa-constructor
1829 superclass-name
1830 metaclass-name
1831 metaclass-constructor))
1832 (declare (type symbol predicate))
1833 (declare (type (member structure funcallable-structure) dd-type))
1835 (let* ((dd (make-dd-with-alternate-metaclass
1836 :class-name class-name
1837 :slot-names slot-names
1838 :superclass-name superclass-name
1839 :metaclass-name metaclass-name
1840 :metaclass-constructor metaclass-constructor
1841 :dd-type dd-type))
1842 (dd-slots (dd-slots dd))
1843 (dd-length (1+ (length slot-names)))
1844 (object-gensym (make-symbol "OBJECT"))
1845 (new-value-gensym (make-symbol "NEW-VALUE"))
1846 (delayed-layout-form `(%delayed-get-compiler-layout ,class-name)))
1847 (multiple-value-bind (raw-maker-form raw-reffer-operator)
1848 (ecase dd-type
1849 (structure
1850 (values `(%make-structure-instance-macro ,dd nil)
1851 '%instance-ref))
1852 (funcallable-structure
1853 (values `(let ((,object-gensym
1854 (%make-funcallable-instance ,dd-length)))
1855 (setf (%funcallable-instance-layout ,object-gensym)
1856 ,delayed-layout-form)
1857 ,object-gensym)
1858 '%funcallable-instance-info)))
1859 `(progn
1861 (eval-when (:compile-toplevel :load-toplevel :execute)
1862 (%compiler-set-up-layout ',dd ',(!inherits-for-structure dd)))
1864 ;; slot readers and writers
1865 (declaim (inline ,@(mapcar #'dsd-accessor-name dd-slots)))
1866 ,@(mapcar (lambda (dsd)
1867 `(defun ,(dsd-accessor-name dsd) (,object-gensym)
1868 ,@(when runtime-type-checks-p
1869 `((declare (type ,class-name ,object-gensym))))
1870 (,raw-reffer-operator ,object-gensym
1871 ,(dsd-index dsd))))
1872 dd-slots)
1873 (declaim (inline ,@(mapcar (lambda (dsd)
1874 `(setf ,(dsd-accessor-name dsd)))
1875 dd-slots)))
1876 ,@(mapcar (lambda (dsd)
1877 `(defun (setf ,(dsd-accessor-name dsd)) (,new-value-gensym
1878 ,object-gensym)
1879 ,@(when runtime-type-checks-p
1880 `((declare (type ,class-name ,object-gensym))))
1881 (setf (,raw-reffer-operator ,object-gensym
1882 ,(dsd-index dsd))
1883 ,new-value-gensym)))
1884 dd-slots)
1886 ;; constructor
1887 (defun ,boa-constructor ,slot-names
1888 (let ((,object-gensym ,raw-maker-form))
1889 ,@(mapcar (lambda (slot-name)
1890 (let ((dsd (or (find slot-name dd-slots
1891 :key #'dsd-name :test #'string=)
1892 (bug "Bogus alt-metaclass boa ctor"))))
1893 `(setf (,(dsd-accessor-name dsd) ,object-gensym)
1894 ,slot-name)))
1895 slot-names)
1896 ,object-gensym))
1898 ;; predicate
1899 ,@(when predicate
1900 ;; Just delegate to the compiler's type optimization
1901 ;; code, which knows how to generate inline type tests
1902 ;; for the whole CMU CL INSTANCE menagerie.
1903 `(defun ,predicate (,object-gensym)
1904 (typep ,object-gensym ',class-name)))
1906 ;; Usually we AVER instead of ASSERT, but AVER isn't defined yet.
1907 ;; A naive reading of 'build-order' suggests it is,
1908 ;; but due to def!struct delay voodoo, it isn't.
1909 (assert (null (symbol-value '*defstruct-hooks*)))))))
1911 ;;;; finalizing bootstrapping
1913 ;;; Set up DD and LAYOUT for STRUCTURE-OBJECT class itself.
1915 ;;; Ordinary structure classes effectively :INCLUDE STRUCTURE-OBJECT
1916 ;;; when they have no explicit :INCLUDEs, so (1) it needs to be set up
1917 ;;; before we can define ordinary structure classes, and (2) it's
1918 ;;; special enough (and simple enough) that we just build it by hand
1919 ;;; instead of trying to generalize the ordinary DEFSTRUCT code.
1920 (defun !set-up-structure-object-class ()
1921 (let ((dd (make-defstruct-description t 'structure-object)))
1922 (setf
1923 (dd-slots dd) nil
1924 (dd-length dd) 1
1925 (dd-type dd) 'structure)
1926 (%compiler-set-up-layout dd)))
1927 #+sb-xc-host(!set-up-structure-object-class)
1929 (defun find-defstruct-description (name &optional (errorp t))
1930 (let* ((classoid (find-classoid name errorp))
1931 (info (and classoid
1932 (layout-info (classoid-layout classoid)))))
1933 (cond ((defstruct-description-p info)
1934 info)
1935 (errorp
1936 (error "No DEFSTRUCT-DESCRIPTION for ~S." name)))))
1938 (defun structure-instance-accessor-p (name)
1939 (let ((info (info :function :source-transform name)))
1940 (and (listp info)
1941 (defstruct-slot-description-p (cdr info))
1942 info)))
1944 (defun dd-default-constructor (dd)
1945 (let ((ctor (first (dd-constructors dd))))
1946 (when (typep ctor '(cons t (eql :default)))
1947 (car ctor))))
1949 ;;; These functions are required to emulate SBCL kernel functions
1950 ;;; in a vanilla ANSI Common Lisp cross-compilation host.
1951 ;;; The emulation doesn't need to be efficient, since it's needed
1952 ;;; only for object dumping.
1953 #+sb-xc-host
1954 (progn
1955 (defun %instance-layout (instance)
1956 (classoid-layout (find-classoid (type-of instance))))
1957 (defun %instance-length (instance)
1958 ;; In the target, it is theoretically possible to have %INSTANCE-LENGTH
1959 ;; exceeed layout length, but in the cross-compiler they're the same.
1960 (layout-length (%instance-layout instance)))
1961 (defun %instance-ref (instance index)
1962 (let ((layout (%instance-layout instance)))
1963 ;; with compact headers, 0 is an ordinary slot index.
1964 ;; without, it's the layout.
1965 (if (eql index (1- sb!vm:instance-data-start))
1966 (error "XC Host should use %INSTANCE-LAYOUT, not %INSTANCE-REF 0")
1967 (let* ((dd (layout-info layout))
1968 ;; If data starts at 1, then subtract 1 from index.
1969 ;; otherwise use the index as-is.
1970 (dsd (elt (dd-slots dd)
1971 (- index sb!vm:instance-data-start)))
1972 (accessor-name (dsd-accessor-name dsd)))
1973 ;; Why AVER these: because it is slightly abstraction-breaking
1974 ;; to assume that the slot-index N is the NTH item in the DSDs.
1975 ;; The target Lisp never assumes that.
1976 (aver (and (eql (dsd-index dsd) index) (eq (dsd-raw-type dsd) t)))
1977 (funcall accessor-name instance)))))
1979 (defun %raw-instance-ref/word (instance index)
1980 (declare (ignore instance index))
1981 (error "No such thing as raw structure access on the host"))
1983 ;; Setting with (FUNCALL `(SETF ,accessor) ...) is unportable because
1984 ;; "The mechanism by which defstruct arranges for slot accessors to be
1985 ;; usable with setf is implementation-dependent; for example, it may
1986 ;; use setf functions, setf expanders, or some other
1987 ;; implementation-dependent mechanism ..."
1988 ;; But such capability seems not to be needed.
1989 (defun %instance-set (instance index new-value)
1990 (declare (ignore instance index new-value))
1991 (error "Can not use %INSTANCE-SET on cross-compilation host.")))
1993 ;;; If LAMBDA-LIST and BODY constitute an auto-generated structure function
1994 ;;; (accessor or predicate) for NAME, return the kind of thing it is.
1995 (defun defstruct-generated-defn-p (name lambda-list body)
1996 (unless (singleton-p body)
1997 (return-from defstruct-generated-defn-p nil))
1998 (let ((info (info :function :source-transform name))
1999 (form (car body)))
2000 (when (consp info)
2001 (when (and (eq (cdr info) :predicate)
2002 (equal lambda-list '(object))
2003 (typep form
2004 '(cons (eql typep)
2005 (cons (eql object)
2006 (cons (cons (eql quote) (cons t null))
2007 null))))
2008 ;; extract dd-name from `(TYPEP OBJECT ',THING)
2009 (eq (second (third form)) (dd-name (car info))))
2010 (return-from defstruct-generated-defn-p :predicate))
2011 (when (defstruct-slot-description-p (cdr info))
2012 (multiple-value-bind (mode expected-lambda-list xform-args)
2013 (if (consp name)
2014 (values :setf '(value instance) '(instance value))
2015 (values :read '(instance) '(instance)))
2016 (when (and (equal expected-lambda-list lambda-list)
2017 (equal (slot-access-transform mode xform-args info) form))
2018 (return-from defstruct-generated-defn-p :accessor)))))))
2020 ;;; It's easier for the compiler to recognize the output of M-L-F-S-S
2021 ;;; without extraneous QUOTE forms, so we define some trivial wrapper macros.
2022 (defmacro new-instance (type) `(allocate-instance (find-class ',type)))
2023 (defmacro sb!pcl::set-slots (instance name-list &rest values)
2024 `(sb!pcl::%set-slots ,instance ',name-list ,@values))
2026 ;;; We require that MAKE-LOAD-FORM-SAVING-SLOTS produce deterministic output
2027 ;;; and that its output take a particular recognizable form so that it can
2028 ;;; be optimized into a sequence of fasl ops. MAKE-LOAD-FORM no longer returns
2029 ;;; a magic keyword except for the special case of :IGNORE-IT.
2030 ;;; The cross-compiler depends critically on optimizing the resulting sexprs
2031 ;;; so that the host can load cold objects, which it could not do
2032 ;;; if constructed by machine code for the target.
2033 ;;; This ends up being a performance win for the target system as well.
2035 (labels ((dsd-primitive-accessor (dsd &aux (rsd (dsd-raw-slot-data dsd)))
2036 (if rsd (raw-slot-data-accessor-name rsd) '%instance-ref))
2037 (quote-p (val)
2038 (cond ((listp val) val)
2039 ((symbolp val) (not (or (eq val t) (keywordp val))))
2040 (t nil)))
2041 ;; Return T if (but not only-if) INITS came from M-L-F-S-S.
2042 (canonical-p (inits dsds object &aux reader)
2043 (dolist (dsd dsds (null inits))
2044 (declare (type defstruct-slot-description dsd))
2045 (if (and (listp inits)
2046 (let ((place (pop inits)))
2047 (and (listp place)
2048 (eq (setq reader (dsd-primitive-accessor dsd))
2049 (pop place))
2050 (listp place) (eq object (pop place))
2051 (singleton-p place)
2052 (eql (dsd-index dsd) (car place))))
2053 (let ((init (and (listp inits) (car inits)))
2054 (val (funcall reader object (dsd-index dsd))))
2055 (if (quote-p val)
2056 (and (typep init '(cons (eql quote)))
2057 (singleton-p (cdr init))
2058 (eq val (cadr init)))
2059 (and inits (eql val init)))))
2060 (pop inits)
2061 (return nil)))))
2063 ;; It is possible to produce instances of structure-object which violate
2064 ;; the assumption throughout the compiler that slot readers are safe
2065 ;; unless dictated otherwise by the SAFE-P flag in the DSD.
2066 ;; * (defstruct S a (b (error "Must supply me") :type symbol))
2067 ;; * (defmethod make-load-form ((x S) &optional e) (m-l-f-s-s x :slot-names '(a)))
2068 ;; After these definitions, a dumped S will have 0 in slot B.
2070 (defun sb!xc:make-load-form-saving-slots (object &key (slot-names nil slot-names-p)
2071 environment)
2072 (declare (ignore environment))
2073 ;; If TYPE-OF isn't a symbol, the creation form probably can't be compiled
2074 ;; unless there is a MAKE-LOAD-FORM on the class without a proper-name.
2075 ;; This is better than returning a creation form that produces
2076 ;; something completely different.
2077 (values (let ((type (type-of object)))
2078 `(,(if (symbolp type) 'new-instance 'allocate-instance) ,type))
2079 (if (typep object 'structure-object)
2080 `(setf ,@(mapcan
2081 (lambda (dsd)
2082 (declare (type defstruct-slot-description dsd))
2083 (when (or (not slot-names-p)
2084 (memq (dsd-name dsd) slot-names))
2085 (let* ((acc (dsd-primitive-accessor dsd))
2086 (ind (dsd-index dsd))
2087 (val (funcall acc object ind)))
2088 (list `(,acc ,object ,ind)
2089 (if (quote-p val) `',val val)))))
2090 (dd-slots (layout-info (%instance-layout object)))))
2091 #-sb-xc-host
2092 (loop for slot in (sb!mop:class-slots (class-of object))
2093 for name = (sb!mop:slot-definition-name slot)
2094 when (if slot-names-p
2095 (memq name slot-names)
2096 (eq (sb!mop:slot-definition-allocation slot) :instance))
2097 collect name into names
2099 collect (if (slot-boundp object name)
2100 (let ((val (slot-value object name)))
2101 (if (quote-p val) `',val val))
2102 'sb!pcl:+slot-unbound+) into vals
2103 finally (return `(sb!pcl::set-slots ,object ,names ,@vals))))))
2105 ;; Call MAKE-LOAD-FORM inside a condition handler in case the method fails.
2106 ; If the resulting CREATION-FORM and INIT-FORM are equivalent to those
2107 ;; returned from MAKE-LOAD-FORM-SAVING-SLOTS, return 'SB-FASL::FOP-STRUCT.
2108 ;; If the object can be ignored, return :IGNORE-IT and NIL.
2109 (defun sb!c::%make-load-form (constant)
2110 (multiple-value-bind (creation-form init-form)
2111 (handler-case (sb!xc:make-load-form constant (make-null-lexenv))
2112 (error (condition) (sb!c:compiler-error condition)))
2113 (cond ((eq creation-form :ignore-it) (values :ignore-it nil))
2114 ((and (listp creation-form)
2115 (typep constant 'structure-object)
2116 (typep creation-form
2117 '(cons (eql new-instance) (cons symbol null)))
2118 (eq (second creation-form) (type-of constant))
2119 (typep init-form '(cons (eql setf)))
2120 (canonical-p (cdr init-form)
2121 (dd-slots (layout-info (%instance-layout constant)))
2122 constant))
2123 (values 'sb!fasl::fop-struct nil))
2125 (values creation-form init-form))))))
2127 (/show0 "code/defstruct.lisp end of file")