Make 'primordial-extensions' very primordial.
[sbcl.git] / src / code / defstruct.lisp
blob01b212ddceae123b7b94ecf52d7f061cc7f35eb0
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 DEFMACRO-MUNDANELY?
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 (def!method 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 (:make-load-form-fun just-dump-it-normally)
132 (:conc-name dsd-)
133 (:copier nil)
134 #-sb-xc-host (:pure t))
135 ;; name of slot
136 name
137 ;; its position in the implementation sequence
138 (index (missing-arg) :type fixnum)
139 ;; the name of the accessor function
141 ;; (CMU CL had extra complexity here ("..or NIL if this accessor has
142 ;; the same name as an inherited accessor (which we don't want to
143 ;; shadow)") but that behavior doesn't seem to be specified by (or
144 ;; even particularly consistent with) ANSI, so it's gone in SBCL.)
145 (accessor-name nil :type symbol)
146 default ; default value expression
147 (type t) ; declared type specifier
148 (safe-p t :type boolean) ; whether the slot is known to be
149 ; always of the specified type
150 ;; Index into *RAW-SLOT-DATA* vector of the RAW-SLOT-DATA for this slot.
151 ;; The index is -1 if this slot is not raw.
152 (%raw-type -1 :type (integer -1 (#.(length *raw-slot-data*))))
153 (read-only nil :type (member t nil)))
154 #!-sb-fluid (declaim (freeze-type defstruct-slot-description))
155 (def!method 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 ;;; shared logic for host macroexpansion for SB!XC:DEFSTRUCT and
214 ;;; cross-compiler macroexpansion for CL:DEFSTRUCT
215 ;;; This monster has exactly one inline use in the final image,
216 ;;; and we can drop the definition.
217 (declaim (inline !expander-for-defstruct))
218 (defun !expander-for-defstruct (null-env-p name-and-options slot-descriptions
219 expanding-into-code-for)
220 (let* ((dd (parse-defstruct null-env-p name-and-options slot-descriptions))
221 (name (dd-name dd))
222 (inherits
223 (if (dd-class-p dd)
224 #+sb-xc-host (!inherits-for-structure dd)
225 #-sb-xc-host
226 (let ((super (compiler-layout-or-lose (or (first (dd-include dd))
227 'structure-object))))
228 (concatenate 'simple-vector
229 (layout-inherits super) (vector super)))))
230 (boa-constructors (member-if #'listp (dd-constructors dd) :key #'cdr))
231 (keyword-constructors (ldiff (dd-constructors dd) boa-constructors))
232 (constructor-definitions
233 (nconc
234 (when keyword-constructors
235 (let ((primary (caar keyword-constructors)))
236 (cons
237 `(defun ,primary ,@(structure-ctor-lambda-parts dd :default))
238 ;; Quasi-bogus: not all the right effects on globaldb
239 ;; happen by defining functions this cheating way.
240 (mapcar (lambda (other)
241 `(setf (fdefinition ',(car other))
242 (fdefinition ',primary)))
243 (rest keyword-constructors)))))
244 (mapcar (lambda (ctor)
245 `(defun ,(car ctor)
246 ,@(structure-ctor-lambda-parts dd (cdr ctor))))
247 boa-constructors)))
248 (print-method
249 (when (dd-print-option dd)
250 (let* ((x (sb!xc:gensym "OBJECT"))
251 (s (sb!xc:gensym "STREAM"))
252 (fname (dd-printer-fname dd))
253 (depthp (eq (dd-print-option dd) :print-function)))
254 ;; Giving empty :PRINT-OBJECT or :PRINT-FUNCTION options
255 ;; leaves FNAME eq to NIL. The user-level effect is
256 ;; to generate a PRINT-OBJECT method specialized for the type,
257 ;; implementing the default #S structure-printing behavior.
258 (cond ((not fname)
259 (setf fname 'default-structure-print depthp t))
260 ((not (symbolp fname))
261 ;; Don't dump the source form into the DD constant;
262 ;; just indicate that there was an expression there.
263 (setf (dd-printer-fname dd) t)))
264 `((sb!xc:defmethod print-object ((,x ,name) ,s)
265 (funcall #',fname ,x ,s
266 ,@(if depthp `(*current-level-in-print*)))))))))
267 ;; Return a list of forms and the DD-NAME.
268 (values
269 (if (dd-class-p dd)
270 `(,@(when (eq expanding-into-code-for :target)
271 ;; Note we intentionally enforce package locks, calling
272 ;; %DEFSTRUCT first. %DEFSTRUCT has the tests (and resulting
273 ;; CERROR) for collisions with LAYOUTs which already exist in
274 ;; the runtime. If there are collisions, we want the user's
275 ;; response to CERROR to control what happens. If the ABORT
276 ;; restart is chosen, %COMPILER-DEFSTRUCT should not modify
277 ;; the definition the class.
278 `((eval-when (:compile-toplevel :load-toplevel :execute)
279 (%defstruct-package-locks ',dd))))
280 (%defstruct ',dd ',inherits (sb!c:source-location))
281 (eval-when (:compile-toplevel :load-toplevel :execute)
282 (%compiler-defstruct ',dd ',inherits))
283 ,@(when (eq expanding-into-code-for :target)
284 `((delay-defstruct-functions
285 ,name
286 ,@(awhen (dd-copier-name dd)
287 `((defun ,(dd-copier-name dd) (instance)
288 (copy-structure (the ,(dd-name dd) instance)))))
289 ,@(awhen (dd-predicate-name dd)
290 `((defun ,(dd-predicate-name dd) (object)
291 (typep object ',(dd-name dd)))))
292 ,@(accessor-definitions dd))
293 ;; This must be in the same lexical environment
294 ,@constructor-definitions
295 ,@print-method
296 ;; Various other operations only make sense on the target SBCL.
297 (%target-defstruct ',dd))))
298 ;; Not DD-CLASS-P
299 ;; FIXME: missing package lock checks
300 `((eval-when (:compile-toplevel :load-toplevel :execute)
301 (%proclaim-defstruct-ctors ',dd)
302 (setf (info :typed-structure :info ',name) ',dd))
303 (setf (info :source-location :typed-structure ',name)
304 (sb!c:source-location))
305 ,@(when (eq expanding-into-code-for :target)
306 `(,@(typed-accessor-definitions dd)
307 ,@(typed-predicate-definitions dd)
308 ,@(typed-copier-definitions dd)
309 ,@constructor-definitions
310 ,@(when (dd-doc dd)
311 `((setf (fdocumentation ',(dd-name dd) 'structure)
312 ',(dd-doc dd))))))))
313 name)))
315 #+sb-xc-host
316 (sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions)
317 ;; All defstructs are toplevel in SBCL's own source code,
318 ;; so pass T for null-lexenv.
319 `(progn ,@(!expander-for-defstruct
320 t name-and-options slot-descriptions :target)))
322 #+sb-xc
323 (sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions
324 &environment env)
325 #!+sb-doc
326 "DEFSTRUCT {Name | (Name Option*)} [Documentation] {Slot | (Slot [Default] {Key Value}*)}
327 Define the structure type Name. Instances are created by MAKE-<name>,
328 which takes &KEY arguments allowing initial slot values to the specified.
329 A SETF'able function <name>-<slot> is defined for each slot to read and
330 write slot values. <name>-p is a type predicate.
332 Popular DEFSTRUCT options (see manual for others):
334 (:CONSTRUCTOR Name)
335 (:PREDICATE Name)
336 Specify the name for the constructor or predicate.
338 (:CONSTRUCTOR Name Lambda-List)
339 Specify the name and arguments for a BOA constructor
340 (which is more efficient when keyword syntax isn't necessary.)
342 (:INCLUDE Supertype Slot-Spec*)
343 Make this type a subtype of the structure type Supertype. The optional
344 Slot-Specs override inherited slot options.
346 Slot options:
348 :TYPE Type-Spec
349 Asserts that the value of this slot is always of the specified type.
351 :READ-ONLY {T | NIL}
352 If true, no setter function is defined for this slot."
353 (multiple-value-bind (forms name)
354 (!expander-for-defstruct
355 (etypecase env
356 (sb!kernel:lexenv (sb!c::null-lexenv-p env))
357 ;; a LOCALLY environment would be fine,
358 ;; but is not an important case to handle.
359 #!+sb-fasteval (sb!interpreter:basic-env nil)
360 (null t))
361 name-and-options slot-descriptions :target)
362 `(progn ,@forms ',name)))
364 #+sb-xc-host
365 (defmacro sb!xc:defstruct (name-and-options &rest slot-descriptions)
366 #!+sb-doc
367 "Cause information about a target structure to be built into the
368 cross-compiler."
369 `(progn ,@(!expander-for-defstruct
370 t name-and-options slot-descriptions :host)))
372 ;;;; functions to generate code for various parts of DEFSTRUCT definitions
374 ;;; First, a helper to determine whether a name names an inherited
375 ;;; accessor.
376 (defun accessor-inherited-data (name defstruct)
377 (assoc name (dd-inherited-accessor-alist defstruct) :test #'eq))
379 ;;; Return a list of forms which create a predicate function for a
380 ;;; typed DEFSTRUCT.
381 (defun typed-predicate-definitions (defstruct)
382 (let ((name (dd-name defstruct))
383 (predicate-name (dd-predicate-name defstruct))
384 (argname 'x)) ; KISS: no user code appears in the DEFUN
385 (when predicate-name
386 (aver (dd-named defstruct))
387 (let ((ltype (dd-lisp-type defstruct))
388 (name-index (cdr (car (last (find-name-indices defstruct))))))
389 `((defun ,predicate-name (,argname)
390 (and (typep ,argname ',ltype)
391 ,(cond
392 ((subtypep ltype 'list)
393 `(do ((head (the ,ltype ,argname) (cdr head))
394 (i 0 (1+ i)))
395 ((or (not (consp head)) (= i ,name-index))
396 (and (consp head) (eq ',name (car head))))))
397 ((subtypep ltype 'vector)
398 `(and (>= (length (the ,ltype ,argname))
399 ,(dd-length defstruct))
400 (eq ',name (aref (the ,ltype ,argname) ,name-index))))
401 (t (bug "Uncatered-for lisp type in typed DEFSTRUCT: ~S."
402 ltype))))))))))
404 ;;; Return a list of forms to create a copier function of a typed DEFSTRUCT.
405 (defun typed-copier-definitions (defstruct)
406 (when (dd-copier-name defstruct)
407 `((setf (fdefinition ',(dd-copier-name defstruct)) #'copy-seq)
408 (declaim (ftype function ,(dd-copier-name defstruct))))))
410 ;;; Return a list of function definitions for accessing and setting
411 ;;; the slots of a typed DEFSTRUCT. The functions are proclaimed to be
412 ;;; inline, and the types of their arguments and results are declared
413 ;;; as well. We count on the compiler to do clever things with ELT.
414 (defun typed-accessor-definitions (defstruct)
415 (collect ((stuff))
416 (let ((ltype (dd-lisp-type defstruct)))
417 (dolist (slot (dd-slots defstruct))
418 (let ((name (dsd-accessor-name slot))
419 (index (dsd-index slot))
420 (new-value '(value))
421 (slot-type `(and ,(dsd-type slot)
422 ,(dd-element-type defstruct))))
423 (let ((inherited (accessor-inherited-data name defstruct)))
424 (cond
425 ((not inherited)
426 (stuff `(declaim (inline ,name ,@(unless (dsd-read-only slot)
427 `((setf ,name))))))
428 (stuff `(defun ,name (structure)
429 (declare (type ,ltype structure))
430 (the ,slot-type (elt structure ,index))))
431 (unless (dsd-read-only slot)
432 (stuff
433 `(defun (setf ,name) (,(car new-value) structure)
434 (declare (type ,ltype structure) (type ,slot-type . ,new-value))
435 (setf (elt structure ,index) . ,new-value)))))
436 ((not (= (cdr inherited) index))
437 (style-warn "~@<Non-overwritten accessor ~S does not access ~
438 slot with name ~S (accessing an inherited slot ~
439 instead).~:@>" name (dsd-name slot))))))))
440 (stuff)))
442 ;;;; parsing
444 ;;; CLHS says that
445 ;;; A defstruct option can be either a keyword or a list of a keyword
446 ;;; and arguments for that keyword; specifying the keyword by itself is
447 ;;; equivalent to specifying a list consisting of the keyword
448 ;;; and no arguments.
449 ;;; It is unclear whether that is meant to imply that any of the keywords
450 ;;; may be present in their atom form, or only if the grammar at the top
451 ;;; shows the atom form does <atom> have the meaning of (<atom>).
452 ;;; At least one other implementation accepts :NAMED as a singleton list.
453 ;; We take a more rigid view that the depicted grammar is exhaustive.
455 (defconstant-eqx +dd-option-names+
456 ;; Each keyword, except :CONSTRUCTOR which may appear more than once,
457 ;; and :NAMED which is trivial, and unambiguous if present more than
458 ;; once, though possibly worth a style-warning.
459 #(:include ; at least 1 argument
460 :initial-offset ; exactly 1 argument
461 :pure ; exactly 1 argument [nonstandard]
462 :type ; exactly 1 argument
463 :conc-name ; 0 or 1 arg
464 :copier ; "
465 :predicate ; "
466 :print-function ; "
467 :print-object) ; "
468 #'equalp)
470 ;;; Parse a single DEFSTRUCT option and store the results in DD.
471 (defun parse-1-dd-option (option dd seen-options)
472 (let* ((keyword (first option))
473 (bit (position keyword +dd-option-names+))
474 (args (rest option))
475 (arg-p (consp args))
476 (arg (if arg-p (car args)))
477 (name (dd-name dd)))
478 (declare (type (unsigned-byte 9) seen-options)) ; mask over DD-OPTION-NAMES
479 (when bit
480 (if (logbitp bit seen-options)
481 (error "More than one ~S option is not allowed" keyword)
482 (setf seen-options (logior seen-options (ash 1 bit))))
483 (multiple-value-bind (syntax-group winp)
484 (cond ; Perform checking per comment at +DD-OPTION-NAMES+.
485 ((= bit 0) (values 0 (and arg-p (proper-list-p args)))) ; >1 arg
486 ((< bit 4) (values 1 (and arg-p (not (cdr args))))) ; exactly 1
487 (t (values 2 (or (not args) (singleton-p args))))) ; 0 or 1
488 (unless winp
489 (if (proper-list-p option)
490 (error "DEFSTRUCT option ~S ~[requires at least~;~
491 requires exactly~;accepts at most~] one argument" keyword syntax-group)
492 (error "Invalid syntax in DEFSTRUCT option ~S" option)))))
493 (case keyword
494 (:conc-name
495 ;; unlike (:predicate) and (:copier) which mean "yes" if supplied
496 ;; without their argument, (:conc-name) and :conc-name mean no conc-name.
497 ;; Also note a subtle difference in :conc-name "" vs :conc-name NIL.
498 ;; The former re-interns each slot name into *PACKAGE* which might
499 ;; not be the same as using the given name directly as an accessor.
500 (setf (dd-conc-name dd) (if arg (string arg))))
501 (:constructor ; takes 0 to 2 arguments.
502 (destructuring-bind (&optional (cname (symbolicate "MAKE-" name))
503 (lambda-list nil ll-supplied-p)) args
504 (setf lambda-list
505 (cond ((not cname)
506 ;; Implementations disagree on the meaning of
507 ;; (:CONSTRUCTOR NIL (A B C)).
508 ;; The choices seem to be: don't define a constructor,
509 ;; define a constructor named NIL, signal a user error,
510 ;; or crash the system itself. The spec implies
511 ;; the behavior that we have, but at least a
512 ;; style-warning seems appropriate.
513 (when ll-supplied-p
514 (style-warn "~S does not define a constructor" option)))
515 ((not ll-supplied-p) :default)
517 (multiple-value-call
518 (lambda (&rest x)
519 (declare (dynamic-extent x))
520 (subseq x 0 ; remove trailing NILs
521 (1+ (position-if #'identity x :from-end t))))
522 (parse-lambda-list
523 lambda-list
524 :accept (lambda-list-keyword-mask
525 '(&optional &rest &key &allow-other-keys &aux))
526 :silent t))))
527 (dd-constructors dd) ; preserve order, just because
528 (nconc (dd-constructors dd) (list (cons cname lambda-list))))))
529 (:copier
530 (setf (dd-copier-name dd) (if arg-p arg (symbolicate "COPY-" name))))
531 (:predicate
532 (setf (dd-predicate-name dd) (if arg-p arg (symbolicate name "-P"))))
533 (:include
534 (setf (dd-include dd) args))
535 ((:print-function :print-object)
536 (when (dd-print-option dd)
537 (error "~S and ~S may not both be specified"
538 (dd-print-option dd) keyword))
539 (setf (dd-print-option dd) keyword (dd-printer-fname dd) arg))
540 (:type
541 (cond ((member arg '(list vector))
542 (setf (dd-type dd) arg (dd-element-type dd) t))
543 ((and (listp arg) (eq (first arg) 'vector))
544 (destructuring-bind (elt-type) (cdr arg)
545 (setf (dd-type dd) 'vector (dd-element-type dd) elt-type)))
547 (error "~S is a bad :TYPE for DEFSTRUCT." arg))))
548 (:named
549 (error "The DEFSTRUCT option :NAMED takes no arguments."))
550 (:initial-offset
551 (setf (dd-offset dd) arg)) ; FIXME: disallow (:INITIAL-OFFSET NIL)
552 (:pure
553 (setf (dd-pure dd) arg))
555 (error "unknown DEFSTRUCT option:~% ~S" option)))
556 seen-options))
558 ;;; Parse OPTIONS into the given DD.
559 (defun parse-defstruct-options (options dd)
560 (let ((seen-options 0)
561 (named-p nil))
562 (dolist (option options)
563 (if (eq option :named)
564 (setf named-p t (dd-named dd) t)
565 (setq seen-options
566 (parse-1-dd-option
567 (cond ((consp option) option)
568 ((member option
569 '(:conc-name :constructor :copier :predicate))
570 (list option))
572 ;; FIXME: ugly message (defstruct (s :include) a)
573 ;; saying "unrecognized" when it means "bad syntax"
574 (error "unrecognized DEFSTRUCT option: ~S" option)))
575 dd seen-options))))
576 (case (dd-type dd)
577 (structure
578 (when (dd-offset dd)
579 (error ":OFFSET can't be specified unless :TYPE is specified."))
580 (unless (dd-include dd)
581 ;; FIXME: It'd be cleaner to treat no-:INCLUDE as defaulting
582 ;; to :INCLUDE STRUCTURE-OBJECT, and then let the general-case
583 ;; (INCF (DD-LENGTH DD) (DD-LENGTH included-DD)) logic take
584 ;; care of this. (Except that the :TYPE VECTOR and :TYPE
585 ;; LIST cases, with their :NAMED and un-:NAMED flavors,
586 ;; make that messy, alas.)
587 (incf (dd-length dd))))
589 ;; In case we are here, :TYPE is specified.
590 (if named-p
591 ;; CLHS - "The structure can be :named only if the type SYMBOL
592 ;; is a subtype of the supplied element-type."
593 (multiple-value-bind (winp certainp)
594 (subtypep 'symbol (dd-element-type dd))
595 (when (and (not winp) certainp)
596 (error ":NAMED option is incompatible with element type ~S"
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) (concatenate 'string (string 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 (result (make-defstruct-description null-env-p name)))
670 (parse-defstruct-options options result)
671 (when (dd-include result)
672 (frob-dd-inclusion-stuff result))
673 (when (stringp (car slot-descriptions))
674 (setf (dd-doc result) (pop slot-descriptions)))
675 (dolist (slot-description slot-descriptions)
676 (allocate-1-slot result (parse-1-dsd result slot-description)))
677 (determine-unsafe-slots result)
678 result))
680 ;;;; stuff to parse slot descriptions
682 ;;; Parse a slot description for DEFSTRUCT, add it to the description
683 ;;; and return it. If supplied, SLOT is a pre-initialized DSD
684 ;;; that we modify to get the new slot. This is supplied when handling
685 ;;; included slots.
686 (defun parse-1-dsd (defstruct spec &optional
687 (slot (make-defstruct-slot-description :name ""
688 :index 0
689 :type t)))
690 #-sb-xc-host (declare (muffle-conditions style-warning))
691 (multiple-value-bind (name default default-p type type-p read-only ro-p)
692 (typecase spec
693 (symbol
694 (typecase spec
695 ((or null (member :conc-name :constructor :copier :predicate :named))
696 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" spec))
697 (keyword
698 (style-warn "slot name of ~S indicates possible syntax error in DEFSTRUCT" spec)))
699 spec)
700 (cons
701 (destructuring-bind
702 (name &optional (default nil default-p)
703 &key (type nil type-p) (read-only nil ro-p))
704 spec
705 (when (dd-conc-name defstruct)
706 ;; the warning here is useful, but in principle we cannot
707 ;; distinguish between legitimate and erroneous use of
708 ;; these names when :CONC-NAME is NIL. In the common
709 ;; case (CONC-NAME non-NIL), there are alternative ways
710 ;; of writing code with the same effect, so a full
711 ;; warning is justified.
712 (typecase name
713 ((member :conc-name :constructor :copier :predicate :include
714 :print-function :print-object :type :initial-offset :pure)
715 (warn "slot name of ~S indicates probable syntax error in DEFSTRUCT" name))))
716 (values name default default-p
717 (uncross type) type-p
718 read-only ro-p)))
719 (t (error 'simple-program-error
720 :format-control "in DEFSTRUCT, ~S is not a legal slot ~
721 description."
722 :format-arguments (list spec))))
724 (when (find name (dd-slots defstruct)
725 :test #'string=
726 :key (lambda (x) (symbol-name (dsd-name x))))
727 (error 'simple-program-error
728 ;; Todo: indicate whether name is a duplicate in the directly
729 ;; specified slots vs. exists in the ancestor and so should
730 ;; be in the (:include ...) clause instead of where it is.
731 :format-control "duplicate slot name ~S"
732 :format-arguments (list name)))
733 (setf (dsd-name slot) name)
734 (setf (dd-slots defstruct) (nconc (dd-slots defstruct) (list slot)))
736 (let ((accessor-name (if (dd-conc-name defstruct)
737 (symbolicate (dd-conc-name defstruct) name)
738 name))
739 (predicate-name (dd-predicate-name defstruct)))
740 (setf (dsd-accessor-name slot) accessor-name)
741 (when (eql accessor-name predicate-name)
742 ;; Some adventurous soul has named a slot so that its accessor
743 ;; collides with the structure type predicate. ANSI doesn't
744 ;; specify what to do in this case. As of 2001-09-04, Martin
745 ;; Atzmueller reports that CLISP and Lispworks both give
746 ;; priority to the slot accessor, so that the predicate is
747 ;; overwritten. We might as well do the same (as well as
748 ;; signalling a warning).
749 (style-warn
750 "~@<The structure accessor name ~S is the same as the name of the ~
751 structure type predicate. ANSI doesn't specify what to do in ~
752 this case. We'll overwrite the type predicate with the slot ~
753 accessor, but you can't rely on this behavior, so it'd be wise to ~
754 remove the ambiguity in your code.~@:>"
755 accessor-name)
756 (setf (dd-predicate-name defstruct) nil))
757 ;; FIXME: It would be good to check for name collisions here, but
758 ;; the easy check,
759 ;;x#-sb-xc-host
760 ;;x(when (and (fboundp accessor-name)
761 ;;x (not (accessor-inherited-data accessor-name defstruct)))
762 ;;x (style-warn "redefining ~/sb-impl::print-symbol-with-prefix/ ~
763 ;; in DEFSTRUCT" accessor-name)))
764 ;; which was done until sbcl-0.8.11.18 or so, is wrong: it causes
765 ;; a warning at MACROEXPAND time, when instead the warning should
766 ;; occur not just because the code was constructed, but because it
767 ;; is actually compiled or loaded.
770 (when default-p
771 (setf (dsd-default slot) default))
772 (when type-p
773 (setf (dsd-type slot)
774 (if (eq (dsd-type slot) t)
775 type
776 `(and ,(dsd-type slot) ,type))))
777 (when ro-p
778 (if read-only
779 (setf (dsd-read-only slot) t)
780 (when (dsd-read-only slot)
781 (error "~@<The slot ~S is :READ-ONLY in superclass, and so must ~
782 be :READ-ONLY in subclass.~:@>"
783 (dsd-name slot)))))
784 slot))
786 ;;; When a value of type TYPE is stored in a structure, should it be
787 ;;; stored in a raw slot? Return the index of the matching RAW-SLOT-DATA
788 ;;; if TYPE should be stored in a raw slot, or NIL if not.
789 (defun structure-raw-slot-data-index (type)
790 (multiple-value-bind (fixnum? fixnum-certain?)
791 (sb!xc:subtypep type 'fixnum)
792 ;; (The extra test for FIXNUM-CERTAIN? here is intended for
793 ;; bootstrapping the system. In particular, in sbcl-0.6.2, we set up
794 ;; LAYOUT before FIXNUM is defined, and so could bogusly end up
795 ;; putting INDEX-typed values into raw slots if we didn't test
796 ;; FIXNUM-CERTAIN?.)
797 (if (or fixnum? (not fixnum-certain?))
799 (dotimes (i (length *raw-slot-data*))
800 (let ((data (svref *raw-slot-data* i)))
801 (when (sb!xc:subtypep type (raw-slot-data-raw-type data))
802 (return i)))))))
804 ;;; Allocate storage for a DSD in DD. This is where we decide whether
805 ;;; a slot is raw or not. Raw objects are aligned on the unit of their size.
806 (defun allocate-1-slot (dd dsd)
807 (let ((rsd-index (if (eq (dd-type dd) 'structure)
808 (structure-raw-slot-data-index (dsd-type dsd))
809 nil)))
810 (cond ((null rsd-index)
811 (setf (dsd-index dsd) (dd-length dd))
812 (incf (dd-length dd)))
814 (setf (dsd-%raw-type dsd) rsd-index)
815 (let* ((rsd (svref *raw-slot-data* rsd-index))
816 (words (raw-slot-data-n-words rsd))
817 (alignment (raw-slot-data-alignment rsd)))
818 #!-interleaved-raw-slots
819 (let ((off (rem (dd-raw-length dd) alignment)))
820 (unless (zerop off)
821 (incf (dd-raw-length dd) (- alignment off)))
822 (setf (dsd-index dsd) (dd-raw-length dd))
823 (incf (dd-raw-length dd) words))
824 #!+interleaved-raw-slots
825 (let ((len (dd-length dd)))
826 (setf (dd-length dd)
827 ;; this formula works but can it be made less unclear?
828 (- len (nth-value 1 (ceiling (1- len) alignment))))
829 (setf (dsd-index dsd) (dd-length dd))
830 (incf (dd-length dd) words))))))
831 (values))
833 (defun typed-structure-info-or-lose (name)
834 (or (info :typed-structure :info name)
835 (error ":TYPE'd DEFSTRUCT ~S not found for inclusion." name)))
837 ;;; Process any included slots pretty much like they were specified.
838 ;;; Also inherit various other attributes.
839 (defun frob-dd-inclusion-stuff (dd)
840 (destructuring-bind (included-name &rest modified-slots) (dd-include dd)
841 (let* ((type (dd-type dd))
842 (included-structure
843 (if (dd-class-p dd)
844 (layout-info (compiler-layout-or-lose included-name))
845 (typed-structure-info-or-lose included-name))))
847 ;; checks on legality
848 (unless (and (eq type (dd-type included-structure))
849 (type= (specifier-type (dd-element-type included-structure))
850 (specifier-type (dd-element-type dd))))
851 (error ":TYPE option mismatch between structures ~S and ~S"
852 (dd-name dd) included-name))
853 (let ((included-classoid (find-classoid included-name nil)))
854 (when included-classoid
855 ;; It's not particularly well-defined to :INCLUDE any of the
856 ;; CMU CL INSTANCE weirdosities like CONDITION or
857 ;; GENERIC-FUNCTION, and it's certainly not ANSI-compliant.
858 (let* ((included-layout (classoid-layout included-classoid))
859 (included-dd (layout-info included-layout)))
860 (when (dd-alternate-metaclass included-dd)
861 (error "can't :INCLUDE class ~S (has alternate metaclass)"
862 included-name)))))
864 ;; A few more sanity checks: every allegedly modified slot exists
865 ;; and no name appears more than once.
866 (flet ((included-slot-name (slot-desc)
867 (if (atom slot-desc) slot-desc (car slot-desc))))
868 (mapl (lambda (slots &aux (name (included-slot-name (car slots))))
869 (unless (find name (dd-slots included-structure)
870 :test #'string= :key #'dsd-name)
871 (error 'simple-program-error
872 :format-control "slot name ~S not present in included structure"
873 :format-arguments (list name)))
874 (when (find name (cdr slots)
875 :test #'string= :key #'included-slot-name)
876 (error 'simple-program-error
877 :format-control "included slot name ~S specified more than once"
878 :format-arguments (list name))))
879 modified-slots))
881 (incf (dd-length dd) (dd-length included-structure))
882 (when (dd-class-p dd)
883 (when (eq (dd-pure dd) :unspecified)
884 (setf (dd-pure dd) (dd-pure included-structure)))
885 #!-interleaved-raw-slots
886 (setf (dd-raw-length dd) (dd-raw-length included-structure)))
888 (setf (dd-inherited-accessor-alist dd)
889 (dd-inherited-accessor-alist included-structure))
890 (dolist (included-slot (dd-slots included-structure))
891 (let* ((included-name (dsd-name included-slot))
892 (modified (or (find included-name modified-slots
893 :key (lambda (x) (if (atom x) x (car x)))
894 :test #'string=)
895 `(,included-name))))
896 ;; We stash away an alist of accessors to parents' slots
897 ;; that have already been created to avoid conflicts later
898 ;; so that structures with :INCLUDE and :CONC-NAME (and
899 ;; other edge cases) can work as specified.
900 (when (dsd-accessor-name included-slot)
901 ;; the "oldest" (i.e. highest up the tree of inheritance)
902 ;; will prevail, so don't push new ones on if they
903 ;; conflict.
904 (pushnew (cons (dsd-accessor-name included-slot)
905 (dsd-index included-slot))
906 (dd-inherited-accessor-alist dd)
907 :test #'eq :key #'car))
908 (let ((new-slot (parse-1-dsd dd
909 modified
910 (copy-structure included-slot))))
911 (when (and (neq (dsd-type new-slot) (dsd-type included-slot))
912 (not (sb!xc:subtypep (dsd-type included-slot)
913 (dsd-type new-slot)))
914 (dsd-safe-p included-slot))
915 (setf (dsd-safe-p new-slot) nil)
916 ;; XXX: notify?
917 )))))))
919 ;;;; various helper functions for setting up DEFSTRUCTs
921 ;;; This function is called at macroexpand time to compute the INHERITS
922 ;;; vector for a structure type definition.
923 ;;; The cross-compiler is allowed to magically compute LAYOUT-INHERITS.
924 (defun !inherits-for-structure (info)
925 (declare (type defstruct-description info))
926 (let* ((include (dd-include info))
927 (superclass-opt (dd-alternate-metaclass info))
928 (super
929 (if include
930 (compiler-layout-or-lose (first include))
931 (classoid-layout (find-classoid
932 (or (first superclass-opt)
933 'structure-object))))))
934 (case (dd-name info)
935 ((ansi-stream)
936 ;; STREAM is an abstract class and you can't :include it,
937 ;; so the inheritance has to be hardcoded.
938 (concatenate 'simple-vector
939 (layout-inherits super)
940 (vector super (classoid-layout (find-classoid 'stream)))))
941 ((fd-stream) ; Similarly, FILE-STREAM is abstract
942 (concatenate 'simple-vector
943 (layout-inherits super)
944 (vector super
945 (classoid-layout (find-classoid 'file-stream)))))
946 ((sb!impl::string-input-stream ; etc
947 sb!impl::string-output-stream
948 sb!impl::fill-pointer-output-stream)
949 (concatenate 'simple-vector
950 (layout-inherits super)
951 (vector super
952 (classoid-layout (find-classoid 'string-stream)))))
953 (t (concatenate 'simple-vector
954 (layout-inherits super)
955 (vector super))))))
957 ;;; Do miscellaneous (LOAD EVAL) time actions for the structure
958 ;;; described by DD. Create the class and LAYOUT, checking for
959 ;;; incompatible redefinition.
960 (defun %defstruct (dd inherits source-location)
961 (declare (type defstruct-description dd))
963 ;; We set up LAYOUTs even in the cross-compilation host.
964 (multiple-value-bind (classoid layout old-layout)
965 (ensure-structure-class dd inherits "current" "new")
966 (cond ((not old-layout)
967 (unless (eq (classoid-layout classoid) layout)
968 (register-layout layout)))
970 (%redefine-defstruct classoid old-layout layout)
971 (let ((old-dd (layout-info old-layout)))
972 (when (defstruct-description-p old-dd)
973 (dolist (slot (dd-slots old-dd))
974 (fmakunbound (dsd-accessor-name slot))
975 (unless (dsd-read-only slot)
976 (fmakunbound `(setf ,(dsd-accessor-name slot)))))))
977 (setq layout (classoid-layout classoid))))
978 (setf (find-classoid (dd-name dd)) classoid)
980 (when source-location
981 (setf (layout-source-location layout) source-location))))
984 ;;; Return a form accessing the writable place used for the slot
985 ;;; described by DD and DSD in the INSTANCE (a form).
986 (defun %accessor-place-form (dd dsd instance)
987 (let (;; Compute REF even if not using it, as a sanity-check of DD-TYPE.
988 (ref (ecase (dd-type dd)
989 (structure '%instance-ref)
990 (list 'nth)
991 (vector 'aref)))
992 (index (dsd-index dsd))
993 (rsd (dsd-raw-slot-data dsd)))
994 (if (not rsd) ; if not raw slot
995 (multiple-value-call 'list ref
996 (if (eq ref 'nth) (values index instance) (values instance index)))
997 `(,(raw-slot-data-accessor-name rsd) ,instance ,index))))
999 ;;; Return the transform of conceptual FUNCTION one of {:READ,:WRITE,:SETF}
1000 ;;; as applied to ARGS, given SLOT-KEY which is a cons of a DD and a DSD.
1001 ;;; Return NIL on failure.
1002 (defun slot-access-transform (function args slot-key)
1003 (when (consp args) ; need at least one arg
1004 (let* ((dd (car slot-key))
1005 (dsd (cdr slot-key))
1006 ;; optimistically compute PLACE before checking length of ARGS
1007 ;; because we expect success, and this unifies the three cases.
1008 ;; :SETF is like an invocation of the SETF macro - newval is
1009 ;; the second arg, but :WRITER is #'(SETF fn) - newval is first.
1010 (place
1011 (%accessor-place-form
1012 dd dsd `(the ,(dd-name dd)
1013 ,(car (if (eq function :write) (cdr args) args)))))
1014 (type-spec (dsd-type dsd)))
1015 (if (eq function :read)
1016 (when (singleton-p args)
1017 (if (eq type-spec t)
1018 place
1019 `(,(if (dsd-safe-p dsd) 'truly-the 'the) ,type-spec ,place)))
1020 (when (singleton-p (cdr args))
1021 (let ((inverse (info :setf :inverse (car place))))
1022 (flet ((check (newval)
1023 (if (eq type-spec t) newval `(the ,type-spec ,newval))))
1024 (ecase function
1025 (:setf
1026 ;; Instance setters take newval last, which matches
1027 ;; the order in which a use of SETF has them.
1028 `(,inverse ,@(cdr place) ,(check (second args))))
1029 (:write
1030 ;; The call to #'(SETF fn) had newval first.
1031 ;; We need to preserve L-to-R evaluation.
1032 (once-only ((new (first args)))
1033 `(,inverse ,@(cdr place) ,(check new))))))))))))
1035 ;;; Return a LAMBDA form which can be used to set a slot
1036 (defun slot-setter-lambda-form (dd dsd)
1037 `(lambda (newval instance)
1038 ,(slot-access-transform :setf '(instance newval) (cons dd dsd))))
1040 ;;; Blow away all the compiler info for the structure CLASS. Iterate
1041 ;;; over this type, clearing the compiler structure type info, and
1042 ;;; undefining all the associated functions. If SUBCLASSES-P, also do
1043 ;;; the same for subclasses. FIXME: maybe rename UNDEFINE-FUN-NAME to
1044 ;;; UNDECLARE-FUNCTION-NAME?
1045 (defun undeclare-structure (classoid subclasses-p)
1046 (let ((info (layout-info (classoid-layout classoid))))
1047 (when (defstruct-description-p info)
1048 (let ((type (dd-name info)))
1049 (clear-info :type :compiler-layout type)
1050 ;; FIXME: shouldn't this undeclare any constructors too?
1051 (undefine-fun-name (dd-copier-name info))
1052 (undefine-fun-name (dd-predicate-name info))
1053 (dolist (slot (dd-slots info))
1054 (let ((fun (dsd-accessor-name slot)))
1055 (unless (accessor-inherited-data fun info)
1056 (undefine-fun-name fun)
1057 (unless (dsd-read-only slot)
1058 (undefine-fun-name `(setf ,fun)))))))
1059 ;; Clear out the SPECIFIER-TYPE cache so that subsequent
1060 ;; references are unknown types.
1061 (values-specifier-type-cache-clear)))
1062 (when subclasses-p
1063 (let ((subclasses (classoid-subclasses classoid)))
1064 (when subclasses
1065 (collect ((subs))
1066 (dohash ((classoid layout)
1067 subclasses
1068 :locked t)
1069 (declare (ignore layout))
1070 (undeclare-structure classoid nil)
1071 (subs (classoid-proper-name classoid)))
1072 ;; Is it really necessary to warn about
1073 ;; undeclaring functions for subclasses?
1074 (when (subs)
1075 (warn "undeclaring functions for old subclasses ~
1076 of ~S:~% ~S"
1077 (classoid-name classoid)
1078 (subs))))))))
1080 ;;; core compile-time setup of any class with a LAYOUT, used even by
1081 ;;; !DEFSTRUCT-WITH-ALTERNATE-METACLASS weirdosities
1082 (defun %compiler-set-up-layout (dd
1083 &optional
1084 ;; Several special cases
1085 ;; (STRUCTURE-OBJECT itself, and
1086 ;; structures with alternate
1087 ;; metaclasses) call this function
1088 ;; directly, and they're all at the
1089 ;; base of the instance class
1090 ;; structure, so this is a handy
1091 ;; default. (But note
1092 ;; FUNCALLABLE-STRUCTUREs need
1093 ;; assistance here)
1094 (inherits (vector (find-layout t))))
1096 (multiple-value-bind (classoid layout old-layout)
1097 (multiple-value-bind (clayout clayout-p)
1098 (info :type :compiler-layout (dd-name dd))
1099 (ensure-structure-class dd
1100 inherits
1101 (if clayout-p
1102 "The most recently compiled"
1103 "The current")
1104 "the most recently loaded"
1105 :compiler-layout clayout))
1106 (cond (old-layout
1107 (undeclare-structure (layout-classoid old-layout)
1108 (and (classoid-subclasses classoid)
1109 (not (eq layout old-layout))))
1110 (setf (layout-invalid layout) nil)
1111 ;; FIXME: it might be polite to hold onto old-layout and
1112 ;; restore it at the end of the file. -- RMK 2008-09-19
1113 ;; (International Talk Like a Pirate Day).
1114 (warn "~@<Clobbering the compiler's idea of the layout of ~A.~:@>"
1115 classoid))
1117 (unless (eq (classoid-layout classoid) layout)
1118 (register-layout layout :invalidate nil))
1119 (setf (find-classoid (dd-name dd)) classoid)))
1121 ;; At this point the class should be set up in the INFO database.
1122 ;; But the logic that enforces this is a little tangled and
1123 ;; scattered, so it's not obvious, so let's check.
1124 (aver (find-classoid (dd-name dd) nil))
1126 (setf (info :type :compiler-layout (dd-name dd)) layout))
1127 (values))
1129 (defun %proclaim-defstruct-ctors (dd)
1130 (dolist (ctor (dd-constructors dd))
1131 (let ((ftype (%struct-ctor-ftype dd (cdr ctor) (dd-element-type dd))))
1132 (sb!c:proclaim-ftype (car ctor) dd ftype :declared))))
1134 ;;; Do (COMPILE LOAD EVAL)-time actions for the normal (not
1135 ;;; ALTERNATE-LAYOUT) DEFSTRUCT described by DD.
1136 ;;; This includes generation of a style-warning about previously compiled
1137 ;;; calls to the accessors and/or predicate that weren't inlined.
1138 (defun %compiler-defstruct (dd inherits)
1139 (declare (type defstruct-description dd))
1141 (aver (dd-class-p dd)) ; LIST and VECTOR representation are not allowed
1142 (let ((check-inlining
1143 ;; Why use the secondary result of INFO, not the primary?
1144 ;; Because when DEFSTRUCT is evaluated, not via the file-compiler,
1145 ;; the first thing to happen is %DEFSTRUCT, which sets up FIND-CLASS.
1146 ;; Due to :COMPILER-LAYOUT's defaulting expression in globaldb,
1147 ;; it has a value - the layout of the classoid - that we don't want.
1148 ;; Also, since structures are technically not redefineable,
1149 ;; I don't worry about failure to inline a function that was
1150 ;; formerly not known as an accessor but now is.
1151 (null (nth-value 1 (info :type :compiler-layout (dd-name dd)))))
1152 (fnames))
1153 (%compiler-set-up-layout dd inherits)
1154 (%proclaim-defstruct-ctors dd)
1156 (awhen (dd-copier-name dd)
1157 (let ((dtype (dd-name dd)))
1158 (sb!xc:proclaim `(ftype (sfunction (,dtype) ,dtype) ,it))))
1160 (let ((predicate-name (dd-predicate-name dd)))
1161 (when predicate-name
1162 (when check-inlining
1163 (push predicate-name fnames))
1164 (setf (info :function :source-transform predicate-name)
1165 (cons dd :predicate))))
1167 (dolist (dsd (dd-slots dd))
1168 (let ((accessor-name (dsd-accessor-name dsd)))
1169 ;; Why this WHEN guard here, if there is neither a standards-specified
1170 ;; nor implementation-specific way to skip defining an accessor? Dunno.
1171 ;; And furthermore, by ignoring a package lock, it's possible to name
1172 ;; an accessor NIL: (defstruct (x (:conc-name "N")) IL)
1173 ;; making this test kinda bogus in two different ways.
1174 (when accessor-name
1175 (let ((inherited (accessor-inherited-data accessor-name dd)))
1176 (cond
1177 ((not inherited)
1178 (let ((writer `(setf ,accessor-name))
1179 (slot-key (cons dd dsd)))
1180 (when check-inlining
1181 (push accessor-name fnames))
1182 (setf (info :function :source-transform accessor-name)
1183 slot-key)
1184 (unless (dsd-read-only dsd)
1185 (when check-inlining
1186 (push writer fnames))
1187 (setf (info :function :source-transform writer) slot-key))))
1188 ((not (= (cdr inherited) (dsd-index dsd)))
1189 (style-warn "~@<Non-overwritten accessor ~S does not access ~
1190 slot with name ~S (accessing an inherited slot ~
1191 instead).~:@>"
1192 accessor-name
1193 (dsd-name dsd))))))))
1195 (awhen (remove-if-not #'sb!c::emitted-full-call-count fnames)
1196 (sb!c:compiler-style-warn
1197 'sb!c:inlining-dependency-failure
1198 ;; This message omits the http://en.wikipedia.org/wiki/Serial_comma
1199 :format-control
1200 (!uncross-format-control
1201 "~@<Previously compiled call~P to ~
1202 ~{~/sb!impl:print-symbol-with-prefix/~^~#[~; and~:;,~] ~} ~
1203 could not be inlined because the structure definition for ~
1204 ~/sb!impl:print-symbol-with-prefix/ was not yet seen. To avoid this warning, ~
1205 DEFSTRUCT should precede references to the affected functions, ~
1206 or they must be declared locally notinline at each call site.~@:>")
1207 :format-arguments (list (length it) (nreverse it) (dd-name dd))))))
1209 ;;;; redefinition stuff
1211 ;;; Compare the slots of OLD and NEW, returning 3 lists of slot names:
1212 ;;; 1. Slots which have moved,
1213 ;;; 2. Slots whose type has changed,
1214 ;;; 3. Deleted slots.
1215 (defun compare-slots (old new)
1216 (let* ((oslots (dd-slots old))
1217 (nslots (dd-slots new))
1218 (onames (mapcar #'dsd-name oslots))
1219 (nnames (mapcar #'dsd-name nslots)))
1220 (collect ((moved)
1221 (retyped))
1222 (dolist (name (intersection onames nnames))
1223 (let ((os (find name oslots :key #'dsd-name :test #'string=))
1224 (ns (find name nslots :key #'dsd-name :test #'string=)))
1225 (unless (sb!xc:subtypep (dsd-type ns) (dsd-type os))
1226 (retyped name))
1227 (unless (and (= (dsd-index os) (dsd-index ns))
1228 (eq (dsd-raw-type os) (dsd-raw-type ns)))
1229 (moved name))))
1230 (values (moved)
1231 (retyped)
1232 (set-difference onames nnames :test #'string=)))))
1234 ;;; If we are redefining a structure with different slots than in the
1235 ;;; currently loaded version, give a warning and return true.
1236 (defun redefine-structure-warning (classoid old new)
1237 (declare (type defstruct-description old new)
1238 (type classoid classoid)
1239 (ignore classoid))
1240 (let ((name (dd-name new)))
1241 (multiple-value-bind (moved retyped deleted) (compare-slots old new)
1242 (when (or moved retyped deleted)
1243 (warn
1244 "incompatibly redefining slots of structure class ~S~@
1245 Make sure any uses of affected accessors are recompiled:~@
1246 ~@[ These slots were moved to new positions:~% ~S~%~]~
1247 ~@[ These slots have new incompatible types:~% ~S~%~]~
1248 ~@[ These slots were deleted:~% ~S~%~]"
1249 name moved retyped deleted)
1250 t))))
1252 ;;; This function is called when we are incompatibly redefining a
1253 ;;; structure CLASS to have the specified NEW-LAYOUT. We signal an
1254 ;;; error with some proceed options and return the layout that should
1255 ;;; be used.
1256 (defun %redefine-defstruct (classoid old-layout new-layout)
1257 (declare (type classoid classoid)
1258 (type layout old-layout new-layout))
1259 (let ((name (classoid-proper-name classoid)))
1260 (restart-case
1261 (error "~@<attempt to redefine the ~S class ~S incompatibly with the current definition~:@>"
1262 'structure-object
1263 name)
1264 (continue ()
1265 :report (lambda (s)
1266 (format s
1267 "~@<Use the new definition of ~S, invalidating ~
1268 already-loaded code and instances.~@:>"
1269 name))
1270 (register-layout new-layout))
1271 (recklessly-continue ()
1272 :report (lambda (s)
1273 (format s
1274 "~@<Use the new definition of ~S as if it were ~
1275 compatible, allowing old accessors to use new ~
1276 instances and allowing new accessors to use old ~
1277 instances.~@:>"
1278 name))
1279 ;; classic CMU CL warning: "Any old ~S instances will be in a bad way.
1280 ;; I hope you know what you're doing..."
1281 (register-layout new-layout
1282 :invalidate nil
1283 :destruct-layout old-layout))
1284 (clobber-it ()
1285 ;; FIXME: deprecated 2002-10-16, and since it's only interactive
1286 ;; hackery instead of a supported feature, can probably be deleted
1287 ;; in early 2003
1288 :report "(deprecated synonym for RECKLESSLY-CONTINUE)"
1289 (register-layout new-layout
1290 :invalidate nil
1291 :destruct-layout old-layout))))
1292 (values))
1294 (declaim (inline dd-layout-length))
1295 (defun dd-layout-length (dd)
1296 (+ (dd-length dd) #!-interleaved-raw-slots (dd-raw-length dd)))
1298 (declaim (ftype (sfunction (defstruct-description) index) dd-instance-length))
1299 (defun dd-instance-length (dd)
1300 ;; Make sure the object ends at a two-word boundary. Note that this does
1301 ;; not affect the amount of memory used, since the allocator would add the
1302 ;; same padding anyway. However, raw slots are indexed from the length of
1303 ;; the object as indicated in the header, so the pad word needs to be
1304 ;; included in that length to guarantee proper alignment of raw double float
1305 ;; slots, necessary for (at least) the SPARC backend.
1306 ;; On backends with interleaved raw slots, the convention of having the
1307 ;; header possibly "lie" about an extra word is more of a bug than a feature.
1308 ;; Because the structure base is aligned, double-word raw slots are properly
1309 ;; aligned, and won't change alignment in descendant object types. It would
1310 ;; be correct to store the true instance length even though GC preserves
1311 ;; the extra data word (as it does for odd-length SIMPLE-VECTOR), treating
1312 ;; the total physical length as rounded-to-even. But having two different
1313 ;; conventions would be even more unnecessarily confusing, so we use
1314 ;; the not-sensible convention even when it does not make sense.
1315 (logior (dd-layout-length dd) 1))
1317 (defun dd-bitmap (dd)
1318 ;; The bitmap stores a 1 for each untagged word,
1319 ;; including any internal padding words for alignment.
1320 ;; The 0th bit is initialized to 0 because the LAYOUT is a tagged
1321 ;; slot that is not present in DD-SLOTS.
1322 ;; All other bits start as 1 and are cleared if the word is tagged.
1323 ;; A final padding word, if any, is regarded as tagged.
1324 (let ((bitmap (ldb (byte (dd-length dd) 0)
1325 (ash -1 sb!vm:instance-data-start))))
1326 (dolist (slot (dd-slots dd) bitmap)
1327 (when (eql t (dsd-raw-type slot))
1328 (setf (ldb (byte 1 (dsd-index slot)) bitmap) 0)))))
1330 ;;; This is called when we are about to define a structure class. It
1331 ;;; returns a (possibly new) class object and the layout which should
1332 ;;; be used for the new definition (may be the current layout, and
1333 ;;; also might be an uninstalled forward referenced layout.) The third
1334 ;;; value is true if this is an incompatible redefinition, in which
1335 ;;; case it is the old layout.
1336 (defun ensure-structure-class (info inherits old-context new-context
1337 &key compiler-layout)
1338 (declare (type defstruct-description info))
1339 (multiple-value-bind (class old-layout)
1340 (multiple-value-bind (class constructor)
1341 (acond ((cdr (dd-alternate-metaclass info))
1342 (values (first it) (second it)))
1344 (values 'structure-classoid 'make-structure-classoid)))
1345 (insured-find-classoid (dd-name info)
1346 (if (eq class 'structure-classoid)
1347 (lambda (x)
1348 (sb!xc:typep x 'structure-classoid))
1349 (lambda (x)
1350 (sb!xc:typep x (classoid-name (find-classoid class)))))
1351 (fdefinition constructor)))
1352 (setf (classoid-direct-superclasses class)
1353 (case (dd-name info)
1354 ((ansi-stream
1355 fd-stream
1356 sb!impl::string-input-stream sb!impl::string-output-stream
1357 sb!impl::fill-pointer-output-stream)
1358 (list (layout-classoid (svref inherits (1- (length inherits))))
1359 (layout-classoid (svref inherits (- (length inherits) 2)))))
1361 (list (layout-classoid
1362 (svref inherits (1- (length inherits))))))))
1363 (let* ((old-layout (or compiler-layout old-layout))
1364 (new-layout
1365 (when (or (not old-layout) *type-system-initialized*)
1366 (make-layout :classoid class
1367 :inherits inherits
1368 :depthoid (length inherits)
1369 :length (dd-layout-length info)
1370 :info info . #!-interleaved-raw-slots
1371 (:n-untagged-slots (dd-raw-length info))
1372 #!+interleaved-raw-slots
1373 (:untagged-bitmap (dd-bitmap info))))))
1374 (cond
1375 ((not old-layout)
1376 (values class new-layout nil))
1377 ((not new-layout)
1378 ;; The assignment of INFO here can almost be deleted,
1379 ;; except for a few magical types that don't d.t.r.t. in cold-init:
1380 ;; STRUCTURE-OBJECT, CONDITION, ALIEN-VALUE, INTERPRETED-FUNCTION
1381 (setf (layout-info old-layout) info)
1382 (values class old-layout nil))
1383 (;; This clause corresponds to an assertion in REDEFINE-LAYOUT-WARNING
1384 ;; of classic CMU CL. I moved it out to here because it was only
1385 ;; exercised in this code path anyway. -- WHN 19990510
1386 (not (eq (layout-classoid new-layout) (layout-classoid old-layout)))
1387 (error "shouldn't happen: weird state of OLD-LAYOUT?"))
1388 ((redefine-layout-warning old-context
1389 old-layout
1390 new-context
1391 (layout-length new-layout)
1392 (layout-inherits new-layout)
1393 (layout-depthoid new-layout)
1394 (layout-raw-slot-metadata new-layout))
1395 (values class new-layout old-layout))
1397 (let ((old-info (layout-info old-layout)))
1398 (if old-info
1399 (cond ((redefine-structure-warning class old-info info)
1400 (values class new-layout old-layout))
1402 (setf (layout-info old-layout) info)
1403 (values class old-layout nil)))
1404 (progn
1405 (setf (layout-info old-layout) info)
1406 (values class old-layout nil)))))))))
1408 ;;; Return a list of pairs (name . index). Used for :TYPE'd
1409 ;;; constructors to find all the names that we have to splice in &
1410 ;;; where. Note that these types don't have a layout, so we can't look
1411 ;;; at LAYOUT-INHERITS.
1412 (defun find-name-indices (defstruct)
1413 (collect ((res))
1414 (let ((infos ()))
1415 (do ((info defstruct
1416 (typed-structure-info-or-lose (first (dd-include info)))))
1417 ((not (dd-include info))
1418 (push info infos))
1419 (push info infos))
1421 (let ((i 0))
1422 (dolist (info infos)
1423 (incf i (or (dd-offset info) 0))
1424 (when (dd-named info)
1425 (res (cons (dd-name info) i)))
1426 (setq i (dd-length info)))))
1428 (res)))
1430 ;;; These functions are called to actually make a constructor after we
1431 ;;; have processed the arglist. The correct variant (according to the
1432 ;;; DD-TYPE) should be called. The function is defined with the
1433 ;;; specified name and arglist. VARS and TYPES are used for argument
1434 ;;; type declarations. VALUES are the values for the slots (in order.)
1436 ;;; This is split into two functions:
1437 ;;; * INSTANCE-CONSTRUCTOR-FORM has to deal with raw slots
1438 ;;; (there are two variations on this)
1439 ;;; * TYPED-CONSTRUCTOR-FORM deal with LIST & VECTOR
1440 ;;; which might have "name" symbols stuck in at various weird places.
1441 (defun instance-constructor-form (dd values)
1442 ;; The difference between the two implementations here is that on all
1443 ;; platforms we don't have the appropriate RAW-INSTANCE-INIT VOPS, which
1444 ;; must be able to deal with immediate values as well -- unlike
1445 ;; RAW-INSTANCE-SET VOPs, which never end up seeing immediate values. With
1446 ;; some additional cleverness we might manage without them and just a single
1447 ;; implementation here, though -- figure out a way to ensure that on those
1448 ;; platforms we always still get a non-immediate TN in every case...
1450 ;; Until someone does that, this means that instances with raw slots can be
1451 ;; DX allocated only on platforms with those additional VOPs.
1452 (let ((dd-slots (dd-slots dd)))
1453 (aver (= (length dd-slots) (length values)))
1454 #!+raw-instance-init-vops
1455 (collect ((slot-specs) (slot-values))
1456 (mapc (lambda (dsd value)
1457 (unless (eq value '.do-not-initialize-slot.)
1458 (slot-specs (list* :slot (dsd-raw-type dsd) (dsd-index dsd)))
1459 (slot-values value)))
1460 dd-slots values)
1461 `(%make-structure-instance-macro ,dd ',(slot-specs) ,@(slot-values)))
1462 #!-raw-instance-init-vops
1463 (collect ((slot-specs) (slot-values) (raw-slots) (raw-values))
1464 ;; Partition into non-raw and raw
1465 (mapc (lambda (dsd value)
1466 (unless (eq value '.do-not-initialize-slot.)
1467 (let ((raw-type (dsd-raw-type dsd)))
1468 (cond ((eq t raw-type)
1469 (slot-specs (list* :slot raw-type (dsd-index dsd)))
1470 (slot-values value))
1472 (raw-slots dsd)
1473 (raw-values value))))))
1474 dd-slots values)
1475 (let ((instance-form
1476 `(%make-structure-instance-macro ,dd
1477 ',(slot-specs) ,@(slot-values))))
1478 (if (raw-slots)
1479 (let ((temp (make-symbol "INSTANCE")))
1480 `(let ((,temp ,instance-form))
1481 ;; Transform to %RAW-INSTANCE-SET/foo, not SETF,
1482 ;; in case any slots are readonly.
1483 ,@(mapcar (lambda (dsd value)
1484 (slot-access-transform
1485 :setf (list temp value) (cons dd dsd)))
1486 (raw-slots) (raw-values))
1487 ,temp))
1488 instance-form)))))
1490 ;;; A "typed" constructors prefers to use a single call to LIST or VECTOR
1491 ;;; if possible, but can't always do that for VECTOR because it might not
1492 ;;; be a (VECTOR T). If not, we fallback to MAKE-ARRAY and (SETF AREF).
1493 (defun typed-constructor-form (dd values)
1494 (multiple-value-bind (operator initial-element)
1495 (cond ((and (eq (dd-type dd) 'vector) (eq (dd-element-type dd) t))
1496 (values 'vector 0))
1497 ((eq (dd-type dd) 'list)
1498 (values 'list nil)))
1499 (let* ((length (dd-length dd))
1500 (slots (dd-slots dd))
1501 ;; Possibly the most useless feature ever: more than one name slot.
1502 (names (find-name-indices dd)))
1503 (aver (= (length slots) (length values)))
1504 (if operator
1505 ;; The initial-element provides values for slots that are skipped
1506 ;; due to :initial-offset, not slots that are skipped due to
1507 ;; &AUX variables with no initial value.
1508 (let ((vals (make-list length :initial-element initial-element)))
1509 (dolist (x names)
1510 (setf (elt vals (cdr x)) `',(car x)))
1511 (mapc (lambda (dsd val)
1512 ;; For both vectors and lists, .DO-NOT-INITIALIZE-SLOT.
1513 ;; becomes 0 even though lists otherwise use NIL for slots
1514 ;; that are skipped to due :initial-offset.
1515 (setf (elt vals (dsd-index dsd))
1516 ;; All VALs have been wrapped in THE if necessary.
1517 (if (eq val '.do-not-initialize-slot.) 0 val)))
1518 slots values)
1519 (cons operator vals))
1520 (let ((temp (make-symbol "OBJ")))
1521 `(let ((,temp (make-array ,length
1522 :element-type ',(dd-element-type dd))))
1523 ,@(mapcar (lambda (x) `(setf (aref ,temp ,(cdr x)) ',(car x)))
1524 names)
1525 ,@(mapcan (lambda (dsd val)
1526 (unless (eq val '.do-not-initialize-slot.)
1527 `((setf (aref ,temp ,(dsd-index dsd)) ,val))))
1528 slots values)
1529 ,temp))))))
1531 ;;; Return the FTYPE for a DD constructor.
1532 ;;; This is tricky in uses such as the following:
1533 ;;; (DEFSTRUCT (S (:CONSTRUCTOR MS (A &AUX (A (ABS A))))) (A 0 :TYPE (MOD 4)))
1534 ;;; The constructor accepts integers betweeen -3 and 3 because the &AUX binding
1535 ;;; hides the positional argument A, and we can't actually put any constraint
1536 ;;; on A unless we figure out what the action of ABS is.
1538 ;;; The FTYPE is actually not a strong enough constraint anyway, so when IR1
1539 ;;; tests for the call compatibility it will test for correctness *after*
1540 ;;; argument defaulting.
1541 (defun %struct-ctor-ftype (dd args elt-type)
1542 (flet ((elt-type-intersect (dsd &aux (slot-type (dsd-type dsd)))
1543 (cond ((eq slot-type t) elt-type)
1544 ((eq elt-type t) slot-type)
1545 (t `(and ,elt-type ,slot-type)))))
1546 `(function
1547 ,(if (eq args :default)
1548 `(&key ,@(mapcar (lambda (dsd)
1549 `(,(keywordicate (dsd-name dsd))
1550 ,(elt-type-intersect dsd)))
1551 (dd-slots dd)))
1552 (destructuring-bind (llks &optional req opt rest keys aux) args
1553 (let ((aux (mapcar (lambda (var) (if (listp var) (car var) var))
1554 aux)))
1555 (flet ((get-arg-type (name)
1556 (let ((slot (unless (member name aux :test #'string=)
1557 (find name (dd-slots dd) :key #'dsd-name
1558 :test #'string=))))
1559 ;; If no slot, the arg restriction is T,
1560 ;; because we don't know where it goes.
1561 (if slot (elt-type-intersect slot) t))))
1562 (make-lambda-list
1563 llks nil (mapcar #'get-arg-type req)
1564 (mapcar (lambda (arg)
1565 (get-arg-type (parse-optional-arg-spec arg)))
1566 opt)
1567 (if rest (list t))
1568 (mapcar (lambda (arg)
1569 (multiple-value-bind (key var) (parse-key-arg-spec arg)
1570 `(,key ,(get-arg-type var))))
1571 keys))))))
1572 (values ,(cond ((dd-class-p dd) (dd-name dd))
1573 ((eq (dd-type dd) 'list) 'list)
1574 (t `(vector ,(dd-element-type dd) ,(dd-length dd))))
1575 &optional))))
1577 (defun struct-ctor-ftype (dd name)
1578 (let ((ctor (assq name (dd-constructors dd))))
1579 (aver ctor)
1580 (%struct-ctor-ftype dd (cdr ctor) (dd-element-type dd))))
1582 (defun proclaimed-ftype (name)
1583 (multiple-value-bind (info foundp) (info :function :type name)
1584 (values (cond ((defstruct-description-p info)
1585 (specifier-type (struct-ctor-ftype info name)))
1586 #-sb-xc-host ; PCL doesn't exist
1587 ((eq info :generic-function) (sb!pcl::compute-gf-ftype name))
1588 (t info))
1589 foundp)))
1591 ;;; Given a DD and a constructor spec (a cons of name and pre-parsed
1592 ;;; BOA lambda list, or the symbol :DEFAULT), return the effective
1593 ;;; lambda list and the body of the lambda.
1594 (defun structure-ctor-lambda-parts
1595 (dd args &aux (creator (ecase (dd-type dd)
1596 (structure #'instance-constructor-form)
1597 ((list vector) #'typed-constructor-form))))
1598 (when (eq args :default)
1599 (let ((lambda-list (mapcar (lambda (dsd)
1600 (let* ((temp (copy-symbol (dsd-name dsd)))
1601 (keyword (keywordicate temp)))
1602 `((,keyword ,temp) ,(dsd-default dsd))))
1603 (dd-slots dd))))
1604 (return-from structure-ctor-lambda-parts
1605 `((&key ,@lambda-list)
1606 (declare (explicit-check))
1607 ,(funcall creator dd
1608 (mapcar (lambda (dsd arg)
1609 (let ((type (dsd-type dsd))
1610 (var (cadar arg)))
1611 (if (eq type t) var `(the ,type ,var))))
1612 (dd-slots dd) lambda-list))))))
1613 (destructuring-bind (llks &optional req opt rest keys aux) args
1614 (collect ((vars (copy-list req)) ; list of bound vars
1615 (aux-vars)
1616 (skipped-vars))
1617 (dolist (binding aux)
1618 (let ((name (if (listp binding) (car binding) binding)))
1619 (aux-vars name)
1620 (unless (typep binding '(cons t cons))
1621 (skipped-vars name))))
1622 (macrolet ((rewrite (input key parse)
1623 `(mapcar
1624 (lambda (arg)
1625 (multiple-value-bind (,@key var def sup-p) (,parse arg)
1626 (declare (ignore ,@key def))
1627 (rewrite-1 arg var sup-p)))
1628 ,input)))
1629 (flet ((rewrite-1 (arg var sup-p-var)
1630 (vars var)
1631 (when sup-p-var (vars (car sup-p-var)))
1632 (let* ((slot (unless (member var (aux-vars) :test #'string=)
1633 (find var (dd-slots dd)
1634 :key #'dsd-name :test #'string=)))
1635 (default (and slot (dsd-default slot))))
1636 ;; If VAR initializes a slot and did not have a default in
1637 ;; the lambda list, and DSD-DEFAULT is not NIL,
1638 ;; then change the lambda-list's default for the variable.
1639 ;; Always prefer to insert (CAR ARG) if ARG was a list
1640 ;; so that (:KEY var) syntax is preserved.
1641 (if (and slot (not (typep arg '(cons t cons))) default)
1642 `(,(if (consp arg) (car arg) var) ,default ,@sup-p-var)
1643 arg)))) ; keep it as it was
1644 ;; Can we substitute symbols that are not EQ to symbols
1645 ;; naming slots, so we don't have to compare by STRING= later?
1646 ;; Probably not because other symbols could reference them.
1647 (setq opt (rewrite opt () parse-optional-arg-spec))
1648 (when rest (vars (car rest)))
1649 (setq keys (rewrite keys (key) parse-key-arg-spec))
1650 (dolist (arg (aux-vars)) (vars arg))))
1651 `(,(sb!c::make-lambda-list
1652 llks nil req opt rest keys
1653 ;; &AUX vars which do not initialize a slot are not mentioned
1654 ;; in the lambda list, though it's not clear what to do if
1655 ;; subsequent bindings refer to the deleted ones.
1656 ;; And worse, what if it's SETQd - is that even legal?
1657 (remove-if (lambda (x) (not (typep x '(cons t cons)))) aux))
1658 (declare (explicit-check))
1659 ,(funcall
1660 creator dd
1661 (mapcar
1662 (lambda (slot &aux (name (dsd-name slot)))
1663 (if (find name (skipped-vars) :test #'string=)
1664 ;; CLHS 3.4.6 Boa Lambda Lists
1665 '.do-not-initialize-slot.
1666 (let* ((type (dsd-type slot))
1667 (found (member (dsd-name slot) (vars) :test #'string=))
1668 (initform (if found (car found) (dsd-default slot))))
1669 ;; We can ignore the DD-ELEMENT-TYPE
1670 ;; because the container itself will check.
1671 (if (eq type t) initform `(the ,type ,initform)))))
1672 (dd-slots dd)))))))
1674 (defun accessor-definitions (dd)
1675 (loop for dsd in (dd-slots dd)
1676 for accessor-name = (dsd-accessor-name dsd)
1677 unless (accessor-inherited-data accessor-name dd)
1678 nconc (dx-let ((key (cons dd dsd)))
1679 `(,@(unless (dsd-read-only dsd)
1680 `((defun (setf ,accessor-name) (value instance)
1681 ,(slot-access-transform :setf '(instance value) key))))
1682 (defun ,accessor-name (instance)
1683 ,(slot-access-transform :read '(instance) key))))))
1685 ;;;; instances with ALTERNATE-METACLASS
1686 ;;;;
1687 ;;;; The CMU CL support for structures with ALTERNATE-METACLASS was a
1688 ;;;; fairly general extension embedded in the main DEFSTRUCT code, and
1689 ;;;; the result was an fairly impressive mess as ALTERNATE-METACLASS
1690 ;;;; extension mixed with ANSI CL generality (e.g. :TYPE and :INCLUDE)
1691 ;;;; and CMU CL implementation hairiness (esp. raw slots). This SBCL
1692 ;;;; version is much less ambitious, noticing that ALTERNATE-METACLASS
1693 ;;;; is only used to implement CONDITION, STANDARD-INSTANCE, and
1694 ;;;; GENERIC-FUNCTION, and defining a simple specialized
1695 ;;;; separate-from-DEFSTRUCT macro to provide only enough
1696 ;;;; functionality to support those.
1697 ;;;;
1698 ;;;; KLUDGE: The defining macro here is so specialized that it's ugly
1699 ;;;; in its own way. It also violates once-and-only-once by knowing
1700 ;;;; much about structures and layouts that is already known by the
1701 ;;;; main DEFSTRUCT macro. Hopefully it will go away presently
1702 ;;;; (perhaps when CL:CLASS and SB-PCL:CLASS meet) as per FIXME below.
1703 ;;;; -- WHN 2001-10-28
1704 ;;;;
1705 ;;;; FIXME: There seems to be no good reason to shoehorn CONDITION,
1706 ;;;; STANDARD-INSTANCE, and GENERIC-FUNCTION into mutated structures
1707 ;;;; instead of just implementing them as primitive objects. (This
1708 ;;;; reduced-functionality macro seems pretty close to the
1709 ;;;; functionality of !DEFINE-PRIMITIVE-OBJECT..)
1711 ;;; The complete list of alternate-metaclass DEFSTRUCTs:
1712 ;;; CONDITION SB-EVAL:INTERPRETED-FUNCTION
1713 ;;; SB-PCL::STANDARD-INSTANCE SB-PCL::STANDARD-FUNCALLABLE-INSTANCE
1714 ;;; SB-PCL::CTOR SB-PCL::%METHOD-FUNCTION
1716 (defun make-dd-with-alternate-metaclass (&key (class-name (missing-arg))
1717 (superclass-name (missing-arg))
1718 (metaclass-name (missing-arg))
1719 (dd-type (missing-arg))
1720 metaclass-constructor
1721 slot-names)
1722 (let* ((dd (make-defstruct-description t class-name))
1723 (conc-name (concatenate 'string (symbol-name class-name) "-"))
1724 (dd-slots (let ((reversed-result nil)
1725 ;; The index starts at 1 for ordinary named
1726 ;; slots because slot 0 is magical, used for
1727 ;; the LAYOUT in CONDITIONs and
1728 ;; FUNCALLABLE-INSTANCEs. (This is the same
1729 ;; in ordinary structures too: see (INCF
1730 ;; DD-LENGTH) in
1731 ;; PARSE-DEFSTRUCT-NAME-AND-OPTIONS).
1732 (index 1))
1733 (dolist (slot-name slot-names)
1734 (push (make-defstruct-slot-description
1735 :name slot-name
1736 :index index
1737 :accessor-name (symbolicate conc-name slot-name))
1738 reversed-result)
1739 (incf index))
1740 (nreverse reversed-result))))
1741 ;; We do *not* fill in the COPIER-NAME and PREDICATE-NAME
1742 ;; because none of the magical alternate-metaclass structures
1743 ;; have copiers and predicates that "Just work"
1744 (case dd-type
1745 ;; We don't support inheritance of alternate metaclass stuff,
1746 ;; and it's not a general-purpose facility, so sanity check our
1747 ;; own code.
1748 (structure
1749 (aver (eq superclass-name 't)))
1750 (funcallable-structure
1751 (aver (eq superclass-name 'function)))
1752 (t (bug "Unknown DD-TYPE in ALTERNATE-METACLASS: ~S" dd-type)))
1753 (setf (dd-alternate-metaclass dd) (list superclass-name
1754 metaclass-name
1755 metaclass-constructor)
1756 (dd-slots dd) dd-slots
1757 (dd-length dd) (1+ (length slot-names))
1758 (dd-type dd) dd-type)
1759 dd))
1761 ;;; make !DEFSTRUCT-WITH-ALTERNATE-METACLASS compilable by the host
1762 ;;; lisp, installing the information we need to reason about the
1763 ;;; structures (layouts and classoids).
1765 ;;; FIXME: we should share the parsing and the DD construction between
1766 ;;; this and the cross-compiler version, but my brain was too small to
1767 ;;; get that right. -- CSR, 2006-09-14
1768 #+sb-xc-host
1769 (defmacro !defstruct-with-alternate-metaclass
1770 (class-name &key
1771 (slot-names (missing-arg))
1772 (boa-constructor (missing-arg))
1773 (superclass-name (missing-arg))
1774 (metaclass-name (missing-arg))
1775 (metaclass-constructor (missing-arg))
1776 (dd-type (missing-arg))
1777 predicate
1778 (runtime-type-checks-p t))
1780 (declare (type (and list (not null)) slot-names))
1781 (declare (type (and symbol (not null))
1782 boa-constructor
1783 superclass-name
1784 metaclass-name
1785 metaclass-constructor))
1786 (declare (type symbol predicate))
1787 (declare (type (member structure funcallable-structure) dd-type))
1788 (declare (ignore boa-constructor predicate runtime-type-checks-p))
1790 (let* ((dd (make-dd-with-alternate-metaclass
1791 :class-name class-name
1792 :slot-names slot-names
1793 :superclass-name superclass-name
1794 :metaclass-name metaclass-name
1795 :metaclass-constructor metaclass-constructor
1796 :dd-type dd-type)))
1797 `(progn
1799 (eval-when (:compile-toplevel :load-toplevel :execute)
1800 (%compiler-set-up-layout ',dd ',(!inherits-for-structure dd))))))
1802 (sb!xc:defmacro !defstruct-with-alternate-metaclass
1803 (class-name &key
1804 (slot-names (missing-arg))
1805 (boa-constructor (missing-arg))
1806 (superclass-name (missing-arg))
1807 (metaclass-name (missing-arg))
1808 (metaclass-constructor (missing-arg))
1809 (dd-type (missing-arg))
1810 predicate
1811 (runtime-type-checks-p t))
1813 (declare (type (and list (not null)) slot-names))
1814 (declare (type (and symbol (not null))
1815 boa-constructor
1816 superclass-name
1817 metaclass-name
1818 metaclass-constructor))
1819 (declare (type symbol predicate))
1820 (declare (type (member structure funcallable-structure) dd-type))
1822 (let* ((dd (make-dd-with-alternate-metaclass
1823 :class-name class-name
1824 :slot-names slot-names
1825 :superclass-name superclass-name
1826 :metaclass-name metaclass-name
1827 :metaclass-constructor metaclass-constructor
1828 :dd-type dd-type))
1829 (dd-slots (dd-slots dd))
1830 (dd-length (1+ (length slot-names)))
1831 (object-gensym (make-symbol "OBJECT"))
1832 (new-value-gensym (make-symbol "NEW-VALUE"))
1833 (delayed-layout-form `(%delayed-get-compiler-layout ,class-name)))
1834 (multiple-value-bind (raw-maker-form raw-reffer-operator)
1835 (ecase dd-type
1836 (structure
1837 (values `(%make-structure-instance-macro ,dd nil)
1838 '%instance-ref))
1839 (funcallable-structure
1840 (values `(let ((,object-gensym
1841 (%make-funcallable-instance ,dd-length)))
1842 (setf (%funcallable-instance-layout ,object-gensym)
1843 ,delayed-layout-form)
1844 ,object-gensym)
1845 '%funcallable-instance-info)))
1846 `(progn
1848 (eval-when (:compile-toplevel :load-toplevel :execute)
1849 (%compiler-set-up-layout ',dd ',(!inherits-for-structure dd)))
1851 ;; slot readers and writers
1852 (declaim (inline ,@(mapcar #'dsd-accessor-name dd-slots)))
1853 ,@(mapcar (lambda (dsd)
1854 `(defun ,(dsd-accessor-name dsd) (,object-gensym)
1855 ,@(when runtime-type-checks-p
1856 `((declare (type ,class-name ,object-gensym))))
1857 (,raw-reffer-operator ,object-gensym
1858 ,(dsd-index dsd))))
1859 dd-slots)
1860 (declaim (inline ,@(mapcar (lambda (dsd)
1861 `(setf ,(dsd-accessor-name dsd)))
1862 dd-slots)))
1863 ,@(mapcar (lambda (dsd)
1864 `(defun (setf ,(dsd-accessor-name dsd)) (,new-value-gensym
1865 ,object-gensym)
1866 ,@(when runtime-type-checks-p
1867 `((declare (type ,class-name ,object-gensym))))
1868 (setf (,raw-reffer-operator ,object-gensym
1869 ,(dsd-index dsd))
1870 ,new-value-gensym)))
1871 dd-slots)
1873 ;; constructor
1874 (defun ,boa-constructor ,slot-names
1875 (let ((,object-gensym ,raw-maker-form))
1876 ,@(mapcar (lambda (slot-name)
1877 (let ((dsd (or (find slot-name dd-slots
1878 :key #'dsd-name :test #'string=)
1879 (bug "Bogus alt-metaclass boa ctor"))))
1880 `(setf (,(dsd-accessor-name dsd) ,object-gensym)
1881 ,slot-name)))
1882 slot-names)
1883 ,object-gensym))
1885 ;; predicate
1886 ,@(when predicate
1887 ;; Just delegate to the compiler's type optimization
1888 ;; code, which knows how to generate inline type tests
1889 ;; for the whole CMU CL INSTANCE menagerie.
1890 `(defun ,predicate (,object-gensym)
1891 (typep ,object-gensym ',class-name)))
1893 ;; Usually we AVER instead of ASSERT, but one alternate-metaclass
1894 ;; structure definition is cross-compiled before AVER is a known macro.
1895 ;; It could be a def!macro perhaps, but ASSERT works just fine here
1896 ;; without adding to image size, since these toplevel forms
1897 ;; belong to code that is discarded after cold-init.
1898 (assert (null (symbol-value '*defstruct-hooks*)))))))
1900 ;;;; finalizing bootstrapping
1902 ;;; Set up DD and LAYOUT for STRUCTURE-OBJECT class itself.
1904 ;;; Ordinary structure classes effectively :INCLUDE STRUCTURE-OBJECT
1905 ;;; when they have no explicit :INCLUDEs, so (1) it needs to be set up
1906 ;;; before we can define ordinary structure classes, and (2) it's
1907 ;;; special enough (and simple enough) that we just build it by hand
1908 ;;; instead of trying to generalize the ordinary DEFSTRUCT code.
1909 (defun !set-up-structure-object-class ()
1910 (let ((dd (make-defstruct-description t 'structure-object)))
1911 (setf
1912 (dd-slots dd) nil
1913 (dd-length dd) 1
1914 (dd-type dd) 'structure)
1915 (%compiler-set-up-layout dd)))
1916 #+sb-xc-host(!set-up-structure-object-class)
1918 ;;; early structure predeclarations: Set up DD and LAYOUT for ordinary
1919 ;;; (non-ALTERNATE-METACLASS) structures which are needed early.
1920 (dolist (args
1921 '#.(sb-cold:read-from-file
1922 "src/code/early-defstruct-args.lisp-expr"))
1923 (let* ((dd (parse-defstruct t (first args) (rest args)))
1924 (inherits (!inherits-for-structure dd)))
1925 (%compiler-defstruct dd inherits)))
1927 (defun find-defstruct-description (name &optional (errorp t))
1928 (let* ((classoid (find-classoid name errorp))
1929 (info (and classoid
1930 (layout-info (classoid-layout classoid)))))
1931 (cond ((defstruct-description-p info)
1932 info)
1933 (errorp
1934 (error "No DEFSTRUCT-DESCRIPTION for ~S." name)))))
1936 (defun structure-instance-accessor-p (name)
1937 (let ((info (info :function :source-transform name)))
1938 (and (listp info)
1939 (defstruct-slot-description-p (cdr info))
1940 info)))
1942 (defun dd-default-constructor (dd)
1943 (let ((ctor (first (dd-constructors dd))))
1944 (when (typep ctor '(cons t (eql :default)))
1945 (car ctor))))
1947 ;;; These functions are required to emulate SBCL kernel functions
1948 ;;; in a vanilla ANSI Common Lisp cross-compilation host.
1949 ;;; The emulation doesn't need to be efficient, since it's needed
1950 ;;; only for object dumping.
1951 #+sb-xc-host
1952 (progn
1953 (defun xc-dumpable-structure-instance-p (x)
1954 (and (typep x 'cl:structure-object)
1955 (let ((name (type-of x)))
1956 ;; Don't allow totally random structures, only ones that the
1957 ;; cross-compiler has been advised will work.
1958 (and (get name :sb-xc-allow-dumping-instances)
1959 ;; but we must also have cross-compiled it for real.
1960 (sb!kernel::compiler-layout-ready-p name)
1961 ;; and I don't know anything about raw slots
1962 ;; Coincidentally, in either representation of
1963 ;; raw-slot-metadata, 0 represents no untagged slots.
1964 (zerop (layout-raw-slot-metadata
1965 (info :type :compiler-layout name)))))))
1966 (defun %instance-layout (instance)
1967 (aver (or (typep instance 'structure!object)
1968 (xc-dumpable-structure-instance-p instance)))
1969 (classoid-layout (find-classoid (type-of instance))))
1970 (defun %instance-length (instance)
1971 ;; INSTANCE-LENGTH tells you how many data words the backend is able to
1972 ;; physically access in this structure. Since every structure occupies
1973 ;; an even number of words, the storage slots comprise an odd number
1974 ;; of words after subtracting 1 for the header.
1975 ;; And in fact the fasl dumper / loader do write and read potentially
1976 ;; one cell beyond the instance's LAYOUT-LENGTH if it was not odd.
1977 ;; I'm not sure whether that is a good or bad thing.
1978 ;; But be that as it may, in the cross-compiler you must not access
1979 ;; more cells than there are in the declared structure because there
1980 ;; is no lower level storage that you can peek at.
1981 ;; So INSTANCE-LENGTH is exactly the same as LAYOUT-LENGTH on the host.
1982 (layout-length (%instance-layout instance)))
1983 (defun %instance-ref (instance index)
1984 (let ((layout (%instance-layout instance)))
1985 ;; with compact headers, 0 is an ordinary slot index.
1986 ;; without, it's the layout.
1987 (if (eql index (1- sb!vm:instance-data-start))
1988 (error "XC Host should use %INSTANCE-LAYOUT, not %INSTANCE-REF 0")
1989 (let* ((dd (layout-info layout))
1990 ;; If data starts at 1, then subtract 1 from index.
1991 ;; otherwise use the index as-is.
1992 (dsd (elt (dd-slots dd)
1993 (- index sb!vm:instance-data-start)))
1994 (accessor-name (dsd-accessor-name dsd)))
1995 ;; Why AVER these: because it is slightly abstraction-breaking
1996 ;; to assume that the slot-index N is the NTH item in the DSDs.
1997 ;; The target Lisp never assumes that.
1998 (aver (and (eql (dsd-index dsd) index) (eq (dsd-raw-type dsd) t)))
1999 (funcall accessor-name instance)))))
2001 (defun %raw-instance-ref/word (instance index)
2002 (declare (ignore instance index))
2003 (error "No such thing as raw structure access on the host"))
2005 ;; Setting with (FUNCALL `(SETF ,accessor) ...) is unportable because
2006 ;; "The mechanism by which defstruct arranges for slot accessors to be
2007 ;; usable with setf is implementation-dependent; for example, it may
2008 ;; use setf functions, setf expanders, or some other
2009 ;; implementation-dependent mechanism ..."
2010 ;; But such capability seems not to be needed.
2011 (defun %instance-set (instance index new-value)
2012 (declare (ignore instance index new-value))
2013 (error "Can not use %INSTANCE-SET on cross-compilation host.")))
2015 ;;; If LAMBDA-LIST and BODY constitute an auto-generated structure function
2016 ;;; (accessor or predicate) for NAME, return the kind of thing it is.
2017 (defun defstruct-generated-defn-p (name lambda-list body)
2018 (unless (singleton-p body)
2019 (return-from defstruct-generated-defn-p nil))
2020 (let ((info (info :function :source-transform name))
2021 (form (car body)))
2022 (when (consp info)
2023 (when (and (eq (cdr info) :predicate)
2024 (equal lambda-list '(object))
2025 (typep form
2026 '(cons (eql typep)
2027 (cons (eql object)
2028 (cons (cons (eql quote) (cons t null))
2029 null))))
2030 ;; extract dd-name from `(TYPEP OBJECT ',THING)
2031 (eq (second (third form)) (dd-name (car info))))
2032 (return-from defstruct-generated-defn-p :predicate))
2033 (when (defstruct-slot-description-p (cdr info))
2034 (multiple-value-bind (mode expected-lambda-list xform-args)
2035 (if (consp name)
2036 (values :setf '(value instance) '(instance value))
2037 (values :read '(instance) '(instance)))
2038 (when (and (equal expected-lambda-list lambda-list)
2039 (equal (slot-access-transform mode xform-args info) form))
2040 (return-from defstruct-generated-defn-p :accessor)))))))
2042 (/show0 "code/defstruct.lisp end of file")