;;; Return the compiler layout for NAME. (The class referred to by
;;; NAME must be a structure-like class.)
(defun compiler-layout-or-lose (name)
+ #+sb-xc (/show0 "entering COMPILER-LAYOUT-OR-LOSE")
(let ((res (info :type :compiler-layout name)))
(cond ((not res)
(error "Class is not yet defined or was undefined: ~S" name))
(t res))))
;;; Delay looking for compiler-layout until the constructor is being
-;;; compiled, since it doesn't exist until after the eval-when
-;;; (compile) is compiled.
+;;; compiled, since it doesn't exist until after the EVAL-WHEN (COMPILE)
+;;; stuff is compiled.
(sb!xc:defmacro %delayed-get-compiler-layout (name)
`',(compiler-layout-or-lose name))
#-sb-xc-host (:pure t)
(:constructor make-defstruct-description (name)))
;; name of the structure
- (name (required-argument) :type symbol)
+ (name (missing-arg) :type symbol)
;; documentation on the structure
(doc nil :type (or string null))
;; prefix for slot names. If NIL, none.
;; the arguments to the :INCLUDE option, or NIL if no included
;; structure
(include nil :type list)
- ;; The arguments to the :ALTERNATE-METACLASS option (an extension
- ;; used to define structure-like objects with an arbitrary
- ;; superclass and that may not have STRUCTURE-CLASS as the
- ;; metaclass.) Syntax is:
+ ;; properties used to define structure-like classes with an
+ ;; arbitrary superclass and that may not have STRUCTURE-CLASS as the
+ ;; metaclass. Syntax is:
;; (superclass-name metaclass-name metaclass-constructor)
(alternate-metaclass nil :type list)
;; a list of DEFSTRUCT-SLOT-DESCRIPTION objects for all slots
(print-unreadable-object (x stream :type t)
(prin1 (dd-name x) stream)))
-;;; Is DD a structure with a class?
-(defun dd-class-p (defstruct)
- (member (dd-type defstruct) '(structure funcallable-structure)))
+;;; Does DD describe a structure with a class?
+(defun dd-class-p (dd)
+ (member (dd-type dd)
+ '(structure funcallable-structure)))
+
+;;; a type name which can be used when declaring things which operate
+;;; on structure instances
+(defun dd-declarable-type (dd)
+ (if (dd-class-p dd)
+ ;; Native classes are known to the type system, and we can
+ ;; declare them as types.
+ (dd-name dd)
+ ;; Structures layered on :TYPE LIST or :TYPE VECTOR aren't part
+ ;; of the type system, so all we can declare is the underlying
+ ;; LIST or VECTOR type.
+ (dd-type dd)))
(defun dd-layout-or-lose (dd)
(compiler-layout-or-lose (dd-name dd)))
;; string name of slot
%name
;; its position in the implementation sequence
- (index (required-argument) :type fixnum)
+ (index (missing-arg) :type fixnum)
;; the name of the accessor function
;;
;; (CMU CL had extra complexity here ("..or NIL if this accessor has
(list 'list)
(vector `(simple-array ,(dd-element-type defstruct) (*)))))
\f
-;;;; checking structure types
-
-;;; Check that X is an instance of the named structure type.
-(defmacro %check-structure-type-from-name (x name)
- `(%check-structure-type-from-layout ,x ,(compiler-layout-or-lose name)))
-
-;;; Check that X is a structure of the type described by DD.
-(defmacro %check-structure-type-from-dd (x dd)
- (declare (type defstruct-description dd))
- (let ((class-name (dd-name dd)))
- (ecase (dd-type dd)
- ((structure funcallable-instance)
- `(%check-structure-type-from-layout
- ,x
- ,(compiler-layout-or-lose class-name)))
- ((vector)
- (let ((xx (gensym "X")))
- `(let ((,xx ,x))
- (declare (type vector ,xx))
- ,@(when (dd-named dd)
- `((unless (eql (aref ,xx 0) ',class-name)
- (error
- 'simple-type-error
- :datum (aref ,xx 0)
- :expected-type `(member ,class-name)
- :format-control
- "~@<missing name in instance of ~
- VECTOR-typed structure ~S: ~2I~_S~:>"
- :format-arguments (list ',class-name ,xx)))))))
- (values))
- ((list)
- (let ((xx (gensym "X")))
- `(let ((,xx ,x))
- (declare (type list ,xx))
- ,@(when (dd-named dd)
- `((unless (eql (first ,xx) ',class-name)
- (error
- 'simple-type-error
- :datum (aref ,xx 0)
- :expected-type `(member ,class-name)
- :format-control
- "~@<missing name in instance of LIST-typed structure ~S: ~
- ~2I~_S~:>"
- :format-arguments (list ',class-name ,xx)))))
- (values)))))))
-
-;;; Check that X is an instance of the structure class with layout LAYOUT.
-(defun %check-structure-type-from-layout (x layout)
- (unless (typep-to-layout x layout)
- (error 'simple-type-error
- :datum x
- :expected-type (sb!xc:class-name (layout-class layout))))
- (values))
-\f
;;;; shared machinery for inline and out-of-line slot accessor functions
;;; an alist mapping from raw slot type to the operator used to access
\f
;;;; generating out-of-line slot accessor functions
-;;; code generators for cases of DEFUN SLOT-ACCESSOR-FUNS
-;;;
-;;; (caution: These macros are sleazily specialized for use only in
-;;; DEFUN SLOT-ACCESSOR-FUNS, not anywhere near fully parameterized:
-;;; they grab symbols like INSTANCE and DSD-FOO automatically.
-;;; Logically they probably belong in a MACROLET inside the DEFUN, but
-;;; separating them like this makes it easier to experiment with them
-;;; in the interpreter and reduces indentation hell.)
-;;;
;;; FIXME: Ideally, the presence of the type checks in the functions
;;; here would be conditional on the optimization policy at the point
;;; of expansion of DEFSTRUCT. (For now we're just doing the simpler
;;; thing, putting in the type checks unconditionally.)
-(eval-when (:compile-toplevel)
-
- ;; code shared between funcallable instance case and the ordinary
- ;; STRUCTURE-OBJECT case: Handle native structures with LAYOUTs and
- ;; (possibly) raw slots.
- (defmacro %native-slot-accessor-funs (dd-ref-fun-name)
- (let ((instance-type-check-form '(%check-structure-type-from-layout
- instance layout)))
- `(let ((layout (dd-layout-or-lose dd))
- (dsd-raw-type (dsd-raw-type dsd)))
- ;; Map over all the possible RAW-TYPEs, compiling a different
- ;; closure-function for each one, so that once the COND over
- ;; RAW-TYPEs happens (at the time closure is allocated) there
- ;; are no more decisions to be made and things execute
- ;; reasonably efficiently.
- (cond
- ;; nonraw slot case
- ((eql (dsd-raw-type dsd) t)
- (%slotplace-accessor-funs (,dd-ref-fun-name instance dsd-index)
- ,instance-type-check-form))
- ;; raw slot cases
- ,@(mapcar (lambda (raw-type-and-rawref-fun-name)
- (destructuring-bind (raw-type . rawref-fun-name)
- raw-type-and-rawref-fun-name
- `((equal dsd-raw-type ',raw-type)
- (let ((raw-index (dd-raw-index dd)))
- (%slotplace-accessor-funs
- (,rawref-fun-name (,dd-ref-fun-name instance
- raw-index)
- dsd-index)
- ,instance-type-check-form)))))
- *raw-type->rawref-fun-name*)))))
-
- ;; code shared between DEFSTRUCT :TYPE LIST and
- ;; DEFSTRUCT :TYPE VECTOR cases: Handle the "typed structure" case,
- ;; with no LAYOUTs and no raw slots.
- (defmacro %colontyped-slot-accessor-funs () (error "stub"))
-
- ;; the common structure of the raw-slot and not-raw-slot cases,
- ;; defined in terms of the writable SLOTPLACE. All possible flavors
- ;; of slot access should be able to pass through here.
- (defmacro %slotplace-accessor-funs (slotplace instance-type-check-form)
- (cl-user:/show slotplace instance-type-check-form)
- `(values (lambda (instance)
- ,instance-type-check-form
- ,slotplace)
- (let ((typecheckfun (typespec-typecheckfun dsd-type)))
- (lambda (new-value instance)
- ,instance-type-check-form
- (funcall typecheckfun new-value)
- (setf ,slotplace new-value))))))
;;; Return (VALUES SLOT-READER-FUN SLOT-WRITER-FUN).
(defun slot-accessor-funs (dd dsd)
- (let ((dsd-index (dsd-index dsd))
- (dsd-type (dsd-type dsd)))
+ #+sb-xc (/show0 "entering SLOT-ACCESSOR-FUNS")
+
+ ;; various code generators
+ ;;
+ ;; Note: They're only minimally parameterized, and cavalierly grab
+ ;; things like INSTANCE and DSD-INDEX from the namespace they're
+ ;; expanded in.
+ (macrolet (;; code shared between funcallable instance case and the
+ ;; ordinary STRUCTURE-OBJECT case: Handle native
+ ;; structures with LAYOUTs and (possibly) raw slots.
+ (%native-slot-accessor-funs (dd-ref-fun-name)
+ (let ((instance-type-check-form
+ '(%check-structure-type-from-layout instance layout)))
+ (/show "macroexpanding %NATIVE-SLOT-ACCESSOR-FUNS" dd-ref-fun-name instance-type-check-form)
+ `(let ((layout (dd-layout-or-lose dd))
+ (dsd-raw-type (dsd-raw-type dsd)))
+ #+sb-xc (/show0 "in %NATIVE-SLOT-ACCESSOR-FUNS macroexpanded code")
+ ;; Map over all the possible RAW-TYPEs, compiling
+ ;; a different closure-function for each one, so
+ ;; that once the COND over RAW-TYPEs happens (at
+ ;; the time closure is allocated) there are no
+ ;; more decisions to be made and things execute
+ ;; reasonably efficiently.
+ (cond
+ ;; nonraw slot case
+ ((eql dsd-raw-type t)
+ #+sb-xc (/show0 "in nonraw slot case")
+ (%slotplace-accessor-funs
+ (,dd-ref-fun-name instance dsd-index)
+ ,instance-type-check-form))
+ ;; raw slot cases
+ ,@(mapcar (lambda (raw-type-and-rawref-fun-name)
+ (destructuring-bind (raw-type
+ . rawref-fun-name)
+ raw-type-and-rawref-fun-name
+ `((equal dsd-raw-type ',raw-type)
+ #+sb-xc (/show0 "in raw slot case")
+ (let ((raw-index (dd-raw-index dd)))
+ (%slotplace-accessor-funs
+ (,rawref-fun-name (,dd-ref-fun-name
+ instance
+ raw-index)
+ dsd-index)
+ ,instance-type-check-form)))))
+ *raw-type->rawref-fun-name*)
+ ;; oops
+ (t
+ (error "internal error: unexpected DSD-RAW-TYPE ~S"
+ dsd-raw-type))))))
+ ;; code shared between DEFSTRUCT :TYPE LIST and
+ ;; DEFSTRUCT :TYPE VECTOR cases: Handle the "typed
+ ;; structure" case, with no LAYOUTs and no raw slots.
+ (%colontyped-slot-accessor-funs () (error "stub"))
+ ;; the common structure of the raw-slot and not-raw-slot
+ ;; cases, defined in terms of the writable SLOTPLACE. All
+ ;; possible flavors of slot access should be able to pass
+ ;; through here.
+ (%slotplace-accessor-funs (slotplace instance-type-check-form)
+ (/show "macroexpanding %SLOTPLACE-ACCESSOR-FUNS" slotplace instance-type-check-form)
+ `(values (lambda (instance)
+ (/noshow0 "in %SLOTPLACE-ACCESSOR-FUNS-defined reader")
+ ,instance-type-check-form
+ (/noshow0 "back from INSTANCE-TYPE-CHECK-FORM")
+ ,slotplace)
+ (let ((typecheckfun (typespec-typecheckfun dsd-type)))
+ (lambda (new-value instance)
+ (/noshow0 "in %SLOTPLACE-ACCESSOR-FUNS-defined writer")
+ ,instance-type-check-form
+ (/noshow0 "back from INSTANCE-TYPE-CHECK-FORM")
+ (funcall typecheckfun new-value)
+ (/noshow0 "back from TYPECHECKFUN")
+ (setf ,slotplace new-value))))))
+
+ (let ((dsd-index (dsd-index dsd))
+ (dsd-type (dsd-type dsd)))
+ #+sb-xc (/show0 "got DSD-TYPE=..")
+ #+sb-xc (/hexstr dsd-type)
(ecase (dd-type dd)
;; native structures
- (structure (%native-slot-accessor-funs %instance-ref))
- (funcallable-structure (%native-slot-accessor-funs
- %funcallable-instance-info))
+ (structure
+ #+sb-xc (/show0 "case of DSD-TYPE = STRUCTURE")
+ (%native-slot-accessor-funs %instance-ref))
;; structures with the :TYPE option
;; layout completely, so that raw slots are impossible.
(list
(dd-type-slot-accessor-funs nth-but-with-sane-arg-order
- `(%check-structure-type-from-dd
- :maybe-raw-p nil))
+ `(%check-structure-type-from-dd
+ :maybe-raw-p nil))
(vector
(dd-type-slot-accessor-funs aref
- :maybe-raw-p nil)))
+ :maybe-raw-p nil)))
|#
- )))
+ ))))
\f
-;;;; REMOVEME: baby steps for the new out-of-line slot accessor functions
+;;;; baby steps for the new out-of-line slot accessor functions
+;;;;
+;;;; REMOVEME after new structure code works
#|
(in-package :sb-kernel)
;; non-compact code. In this context, we'd rather have
;; compact, cold-loadable code. -- WHN 19990928
(declare (notinline sb!xc:find-class))
+ #+sb-xc (/show0 "beginning CLASS-METHOD-DEFINITIONS forms")
,@(let ((pf (dd-print-function defstruct))
(po (dd-print-object defstruct))
(x (gensym))
,@(let ((def-con (dd-default-constructor defstruct)))
(when (and def-con (not (dd-alternate-metaclass defstruct)))
`((setf (structure-class-constructor (sb!xc:find-class ',name))
- #',def-con))))))))
+ #',def-con))))
+ #+sb-xc (/show0 "done with CLASS-METHOD-DEFINITIONS forms")))))
;;; FIXME: I really would like to make structure accessors less
;;; special, just ordinary inline functions. (Or perhaps inline
;;; functions with special compact implementations of their
(if (dd-class-p dd)
(let ((inherits (inherits-for-structure dd)))
`(progn
+ (/show0 "beginning macroexpanded DEFSTRUCT code")
(eval-when (:compile-toplevel :load-toplevel :execute)
(%compiler-defstruct ',dd ',inherits))
+ (/show0 "back from %COMPILER-DEFSTRUCT")
(%defstruct ',dd ',inherits)
+ (/show0 "back from %DEFSTRUCT")
,@(unless expanding-into-code-for-xc-host-p
- (append (raw-accessor-definitions dd)
+ (append #|(raw-accessor-definitions dd)|# ; REMOVEME
(predicate-definitions dd)
;; FIXME: We've inherited from CMU CL nonparallel
;; code for creating copiers for typed and untyped
;(copier-definition dd)
(constructor-definitions dd)
(class-method-definitions dd)))
+ (/show0 "done with macroexpanded DEFSTRUCT code")
',name))
`(progn
+ (/show0 "beginning macroexpanded typed DEFSTRUCT code")
(eval-when (:compile-toplevel :load-toplevel :execute)
(setf (info :typed-structure :info ',name) ',dd))
,@(unless expanding-into-code-for-xc-host-p
(typed-predicate-definitions dd)
(typed-copier-definitions dd)
(constructor-definitions dd)))
+ (/show0 "done with macroexpanded typed DEFSTRUCT code")
',name)))))
(sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions)
\f
;;;; functions to generate code for various parts of DEFSTRUCT definitions
-;;; Catch requests to mess up definitions in COMMON-LISP.
-#-sb-xc-host
-(eval-when (:compile-toplevel :load-toplevel :execute)
- (defun protect-cl (symbol)
- (when (and *cold-init-complete-p*
- (eq (symbol-package symbol) *cl-package*))
- (cerror "Go ahead and patch the system."
- "attempting to modify a symbol in the COMMON-LISP package: ~S"
- symbol))))
-
+;;; REMOVEME: no longer used
+#|
;;; Return forms to define readers and writers for raw slots as inline
;;; functions.
(defun raw-accessor-definitions (dd)
- (let* ((name (dd-name dd)))
+ (let* ((name (dd-name dd))
+ (dtype (dd-declarable-type dd)))
(collect ((res))
(dolist (slot (dd-slots dd))
(let ((slot-type (dsd-type slot))
;; When accessor exists and is raw
(when (and accessor-name
(not (eq accessor-name '%instance-ref)))
+ (res `(/show0 "doing one slot, ACCESSOR-NAME=.."))
+ (res `(/hexstr ',accessor-name))
(res `(declaim (inline ,accessor-name)))
- (res `(declaim (ftype (function (,name) ,slot-type)
+ (res `(/show0 "done with reader DECLAIM INLINE"))
+ (res `(declaim (ftype (function (,dtype) ,slot-type)
,accessor-name)))
+ (res `(/show0 "done with reader DECLAIM FTYPE, doing DEFUN"))
(res `(defun ,accessor-name (,argname)
;; Note: The DECLARE here might seem redundant
;; with the DECLAIM FTYPE above, but it's not:
;; If we're not at toplevel, the PROCLAIM inside
;; the DECLAIM doesn't get executed until after
;; this function is compiled.
- (declare (type ,name ,argname))
+ (declare (type ,dtype ,argname))
(truly-the ,slot-type (,accessor ,data ,offset))))
(unless (dsd-read-only slot)
+ (res `(/show0 "doing writer DECLAIM INLINE"))
(res `(declaim (inline (setf ,accessor-name))))
- (res `(declaim (ftype (function (,slot-type ,name) ,slot-type)
+ (res `(/show0 "doing writer DECLAIM FTYPE"))
+ (res `(declaim (ftype (function (,slot-type ,dtype) ,slot-type)
(setf ,accessor-name))))
;; FIXME: I rewrote this somewhat from the CMU CL definition.
;; Do some basic tests to make sure that reading and writing
;; raw slots still works correctly.
+ (res `(/show0 "doing writer DEFUN"))
(res `(defun (setf ,accessor-name) (,nvname ,argname)
- (declare (type ,name ,argname))
+ (declare (type ,dtype ,argname))
(setf (,accessor ,data ,offset) ,nvname)
- ,nvname)))))))
- (res))))
+ ,nvname)))
+ (res `(/show0 "done with one slot"))))))
+ `((/show0 "beginning RAW-ACCESSOR-DEFINITIONS forms")
+ ,@(res)
+ (/show0 "done with RAW-ACCESSOR-DEFINITIONS forms")))))
+|#
;;; Return a list of forms which create a predicate for an untyped DEFSTRUCT.
(defun predicate-definitions (dd)
(let ((pred (dd-predicate-name dd))
- (argname (gensym)))
- (when pred
- (if (eq (dd-type dd) 'funcallable-structure)
- ;; FIXME: Why does this need to be special-cased for
- ;; FUNCALLABLE-STRUCTURE? CMU CL did it, but without explanation.
- ;; Could we do without it? What breaks if we do? Or could we
- ;; perhaps get by with no predicates for funcallable structures?
- `((declaim (inline ,pred))
- (defun ,pred (,argname) (typep ,argname ',(dd-name dd))))
- `((protect-cl ',pred)
- (declaim (inline ,pred))
- (defun ,pred (,argname)
- (declare (optimize (speed 3) (safety 0)))
- (typep-to-layout ,argname
- (compile-time-find-layout ,(dd-name dd)))))))))
+ (argname (gensym "ARG")))
+ (and pred
+ `((/show0 "beginning PREDICATE-DEFINITIONS forms")
+ (protect-cl ',pred)
+ (declaim (inline ,pred))
+ (defun ,pred (,argname)
+ (declare (optimize (speed 3) (safety 0)))
+ (typep-to-layout ,argname
+ (compile-time-find-layout ,(dd-name dd))))
+ (/show0 "done with PREDICATE-DEFINITIONS forms")))))
;;; Return a list of forms which create a predicate function for a typed
;;; DEFSTRUCT.
#|
;;; Return the copier definition for an untyped DEFSTRUCT.
(defun copier-definition (dd)
- (when (and (dd-copier dd)
- ;; FUNCALLABLE-STRUCTUREs don't need copiers, and this
- ;; implementation wouldn't work for them anyway, since
- ;; COPY-STRUCTURE returns a STRUCTURE-OBJECT and they're not.
- (not (eq (dd-type info) 'funcallable-structure)))
+ (when (dd-copier dd)
(let ((argname (gensym)))
`(progn
(protect-cl ',(dd-copier dd))
`((setf (fdefinition ',(dd-copier-name defstruct)) #'copy-seq)
(declaim (ftype function ,(dd-copier-name defstruct))))))
-;;; Return a list of function definitions for accessing and setting the
-;;; slots of a typed DEFSTRUCT. The functions are proclaimed to be inline,
-;;; and the types of their arguments and results are declared as well. We
-;;; count on the compiler to do clever things with ELT.
+;;; Return a list of function definitions for accessing and setting
+;;; the slots of a typed DEFSTRUCT. The functions are proclaimed to be
+;;; inline, and the types of their arguments and results are declared
+;;; as well. We count on the compiler to do clever things with ELT.
(defun typed-accessor-definitions (defstruct)
(collect ((stuff))
(let ((ltype (dd-lisp-type defstruct)))
(when (dd-include dd)
(error "more than one :INCLUDE option"))
(setf (dd-include dd) args))
- (:alternate-metaclass
- (setf (dd-alternate-metaclass dd) args))
(:print-function
(require-no-print-options-so-far dd)
(setf (dd-print-function dd)
(the (or symbol cons) args)))
(:type
(destructuring-bind (type) args
- (cond ((eq type 'funcallable-structure)
- (setf (dd-type dd) type))
- ((member type '(list vector))
+ (cond ((member type '(list vector))
(setf (dd-element-type dd) t)
(setf (dd-type dd) type))
((and (consp type) (eq (first type) 'vector))
(aver name) ; A null name doesn't seem to make sense here.
(let ((dd (make-defstruct-description name)))
(dolist (option options)
- (cond ((consp option)
- (parse-1-dd-option option dd))
- ((eq option :named)
+ (cond ((eq option :named)
(setf (dd-named dd) t))
- ((member option '(:constructor :copier :predicate :named))
+ ((consp option)
+ (parse-1-dd-option option dd))
+ ((member option '(:conc-name :constructor :copier :predicate))
(parse-1-dd-option (list option) dd))
(t
(error "unrecognized DEFSTRUCT option: ~S" option))))
(when (dd-offset dd)
(error ":OFFSET can't be specified unless :TYPE is specified."))
(unless (dd-include dd)
+ ;; FIXME: It'd be cleaner to treat no-:INCLUDE as defaulting
+ ;; to :INCLUDE STRUCTURE-OBJECT, and then let the general-case
+ ;; (INCF (DD-LENGTH DD) (DD-LENGTH included-DD)) logic take
+ ;; care of this. (Except that the :TYPE VECTOR and :TYPE
+ ;; LIST cases, with their :NAMED and un-:NAMED flavors,
+ ;; make that messy, alas.)
(incf (dd-length dd))))
- (funcallable-structure)
(t
(require-no-print-options-so-far dd)
(when (dd-named dd)
(style-warn
"~@<The structure accessor name ~S is the same as the name of the ~
structure type predicate. ANSI doesn't specify what to do in ~
- this case; this implementation chooses to overwrite the type ~
- predicate with the slot accessor.~@:>"
+ this case. We'll overwrite the type predicate with the slot ~
+ accessor, but you can't rely on this behavior, so it'd be wise to ~
+ remove the ambiguity in your code.~@:>"
accessor-name)
(setf (dd-predicate-name defstruct) nil)))
;;; yet for the raw data vector, then do it. Raw objects are aligned
;;; on the unit of their size.
(defun allocate-1-slot (dd dsd)
+ #+sb-xc (/show0 "entering ALLOCATE-1-SLOT")
(multiple-value-bind (raw? raw-type words)
(if (eq (dd-type dd) 'structure)
(structure-raw-slot-type-and-size (dsd-type dsd))
(setf (dsd-raw-type dsd) raw-type)
(setf (dsd-index dsd) (dd-raw-length dd))
(incf (dd-raw-length dd) words))))
+ #+sb-xc (/show0 "leaving ALLOCATE-1-SLOT")
(values))
(defun typed-structure-info-or-lose (name)
(if (dd-class-p dd)
(layout-info (compiler-layout-or-lose included-name))
(typed-structure-info-or-lose included-name))))
+
+ ;; checks on legality
(unless (and (eq type (dd-type included-structure))
(type= (specifier-type (dd-element-type included-structure))
(specifier-type (dd-element-type dd))))
(error ":TYPE option mismatch between structures ~S and ~S"
(dd-name dd) included-name))
+ (let ((included-class (sb!xc:find-class included-name nil)))
+ (when included-class
+ ;; It's not particularly well-defined to :INCLUDE any of the
+ ;; CMU CL INSTANCE weirdosities like CONDITION or
+ ;; GENERIC-FUNCTION, and it's certainly not ANSI-compliant.
+ (let* ((included-layout (class-layout included-class))
+ (included-dd (layout-info included-layout)))
+ (when (and (dd-alternate-metaclass included-dd)
+ ;; As of sbcl-0.pre7.73, anyway, STRUCTURE-OBJECT
+ ;; is represented with an ALTERNATE-METACLASS. But
+ ;; it's specifically OK to :INCLUDE (and PCL does)
+ ;; so in this one case, it's OK to include
+ ;; something with :ALTERNATE-METACLASS after all.
+ (not (eql included-name 'structure-object)))
+ (error "can't :INCLUDE class ~S (has alternate metaclass)"
+ included-name)))))
(incf (dd-length dd) (dd-length included-structure))
(when (dd-class-p dd)
(class-layout (sb!xc:find-class
(or (first superclass-opt)
'structure-object))))))
- (if (eq (dd-name info) 'lisp-stream)
- ;; a hack to added the stream class as a mixin for LISP-STREAMs
+ (if (eq (dd-name info) 'ansi-stream)
+ ;; a hack to add the CL:STREAM class as a mixin for ANSI-STREAMs
(concatenate 'simple-vector
(layout-inherits super)
(vector super
;;; Do miscellaneous (LOAD EVAL) time actions for the structure
;;; described by DD. Create the class & LAYOUT, checking for
-;;; incompatible redefinition. Define setters, accessors, copier,
-;;; predicate, documentation, instantiate definition in load-time
-;;; environment.
+;;; incompatible redefinition. Define those functions which are
+;;; sufficiently stereotyped that we can implement them as standard
+;;; closures.
(defun %defstruct (dd inherits)
(declare (type defstruct-description dd))
- (remhash (dd-name dd) *typecheckfuns*)
+
+ #+sb-xc (/show0 "entering %DEFSTRUCT")
+
+ ;; We set up LAYOUTs even in the cross-compilation host.
(multiple-value-bind (class layout old-layout)
(ensure-structure-class dd inherits "current" "new")
(cond ((not old-layout)
(unless (eq (class-layout class) layout)
(register-layout layout)))
(t
- (let ((old-dd (layout-dd old-layout)))
+ (let ((old-dd (layout-info old-layout)))
(when (defstruct-description-p old-dd)
(dolist (slot (dd-slots old-dd))
(fmakunbound (dsd-accessor-name slot))
(fmakunbound `(setf ,(dsd-accessor-name slot)))))))
(%redefine-defstruct class old-layout layout)
(setq layout (class-layout class))))
-
(setf (sb!xc:find-class (dd-name dd)) class)
- ;; Set FDEFINITIONs for structure accessors, setters, predicates,
- ;; and copiers.
+ ;; It doesn't make sense to do these in the cross-compilation host.
#-sb-xc-host
- (unless (eq (dd-type dd) 'funcallable-structure)
-
- (dolist (slot (dd-slots dd))
- (let ((dsd slot))
- (when (and (dsd-accessor-name slot)
- (eq (dsd-raw-type slot) t))
- (protect-cl (dsd-accessor-name slot))
- (setf (symbol-function (dsd-accessor-name slot))
- (structure-slot-getter layout dsd))
- (unless (dsd-read-only slot)
- (setf (fdefinition `(setf ,(dsd-accessor-name slot)))
- (structure-slot-setter layout dsd))))))
-
- ;; FIXME: Someday it'd probably be good to go back to using
- ;; closures for the out-of-line forms of structure accessors.
- #|
- (when (dd-predicate dd)
- (protect-cl (dd-predicate dd))
- (setf (symbol-function (dd-predicate dd))
- #'(lambda (object)
- (declare (optimize (speed 3) (safety 0)))
- (typep-to-layout object layout))))
- |#
-
- (when (dd-copier-name dd)
- (protect-cl (dd-copier-name dd))
- (setf (symbol-function (dd-copier-name dd))
- #'(lambda (structure)
- (declare (optimize (speed 3) (safety 0)))
- (flet ((layout-test (structure)
- (typep-to-layout structure layout)))
- (unless (layout-test structure)
- (error 'simple-type-error
- :datum structure
- :expected-type '(satisfies layout-test)
- :format-control
- "Structure for copier is not a ~S:~% ~S"
- :format-arguments
- (list (sb!xc:class-name (layout-class layout))
- structure))))
- (copy-structure structure))))))
-
- (when (dd-doc dd)
- (setf (fdocumentation (dd-name dd) 'type)
- (dd-doc dd)))
-
+ (progn
+ #+sb-xc (/show0 "doing #+SB-XC stuff in %DEFSTRUCT")
+ (remhash (dd-name dd) *typecheckfuns*)
+ (%target-defstruct dd layout)
+ (when (dd-doc dd)
+ (setf (fdocumentation (dd-name dd) 'type)
+ (dd-doc dd)))
+ #+sb-xc (/show0 "done with #+SB-XC stuff in %DEFSTRUCT")
+ ))
+
+ #+sb-xc (/show0 "leaving %DEFSTRUCT")
(values))
-
+\f
;;; Return a form describing the writable place used for this slot
;;; in the instance named INSTANCE-NAME.
(defun %accessor-place-form (dd dsd instance-name)
;; the case of a raw slot, to read the vector of raw slots
(ref (ecase (dd-type dd)
(structure '%instance-ref)
- (funcallable-structure '%funcallable-instance-info)
(list 'nth-but-with-sane-arg-order)
(vector 'aref)))
(raw-type (dsd-raw-type dsd)))
(declare (type ,(dd-name dd) structure-object))
(setf ,(%accessor-place-form dd dsd 'instance) new-value)))))
-;;; Do (COMPILE LOAD EVAL)-time actions for the defstruct described by DD.
-(defun %compiler-defstruct (dd inherits)
- (declare (type defstruct-description dd))
+;;; core compile-time setup of any class with a LAYOUT, used even by
+;;; !DEFSTRUCT-WITH-ALTERNATE-METACLASS weirdosities
+(defun %compiler-set-up-layout (dd
+ &optional
+ ;; Several special cases (STRUCTURE-OBJECT
+ ;; itself, and structures with alternate
+ ;; metaclasses) call this function directly,
+ ;; and they're all at the base of the
+ ;; instance class structure, so this is
+ ;; a handy default.
+ (inherits (vector (find-layout t)
+ (find-layout 'instance))))
+
+ (/show "entering %COMPILER-SET-UP-LAYOUT for" (dd-name dd))
+
(multiple-value-bind (class layout old-layout)
(multiple-value-bind (clayout clayout-p)
(info :type :compiler-layout (dd-name dd))
"compiled"
:compiler-layout clayout))
(cond (old-layout
+ (/show "non-NIL" old-layout)
(undefine-structure (layout-class old-layout))
(when (and (class-subclasses class)
(not (eq layout old-layout)))
(register-layout layout :invalidate nil))
(setf (sb!xc:find-class (dd-name dd)) class)))
+ ;; At this point the class should be set up in the INFO database.
+ ;; But the logic that enforces this is a little tangled and
+ ;; scattered, so it's not obvious, so let's check.
+ (aver (sb!xc:find-class (dd-name dd) nil))
+
(setf (info :type :compiler-layout (dd-name dd)) layout))
+ (/show0 "leaving %COMPILER-SET-UP-LAYOUT")
+
+ (values))
+
+;;; Do (COMPILE LOAD EVAL)-time actions for the normal (not
+;;; ALTERNATE-LAYOUT) DEFSTRUCT described by DD.
+(defun %compiler-defstruct (dd inherits)
+ (declare (type defstruct-description dd))
+ #+sb-xc (/show0 "entering %COMPILER-DEFSTRUCT")
+
+ (%compiler-set-up-layout dd inherits)
+
(let* ((dd-name (dd-name dd))
+ (dtype (dd-declarable-type dd))
(class (sb!xc:find-class dd-name)))
(let ((copier-name (dd-copier-name dd)))
(when copier-name
- (sb!xc:proclaim `(ftype (function (,dd-name) ,dd-name) ,copier-name))))
+ (sb!xc:proclaim `(ftype (function (,dtype) ,dtype) ,copier-name))))
(let ((predicate-name (dd-predicate-name dd)))
(when predicate-name
(when accessor-name
(multiple-value-bind (reader-designator writer-designator)
(accessor-inline-expansion-designators dd dsd)
- (sb!xc:proclaim `(ftype (function (,dd-name) ,dsd-type)
+ (sb!xc:proclaim `(ftype (function (,dtype) ,dsd-type)
,accessor-name))
(setf (info :function
:inline-expansion-designator
(unless (dsd-read-only dsd)
(let ((setf-accessor-name `(setf ,accessor-name)))
(sb!xc:proclaim
- `(ftype (function (,dsd-type ,dd-name) ,dsd-type)
+ `(ftype (function (,dsd-type ,dtype) ,dsd-type)
,setf-accessor-name))
(setf (info :function
:inline-expansion-designator
(info :function :inlinep setf-accessor-name)
:inline))))))))
+ #+sb-xc (/show0 "leaving %COMPILER-DEFSTRUCT")
(values))
\f
;;;; redefinition stuff
;;; be used.
(defun %redefine-defstruct (class old-layout new-layout)
(declare (type sb!xc:class class) (type layout old-layout new-layout))
+ #+sb-xc (/show0 "entering %REDEFINE-DEFSTRUCT")
(let ((name (class-proper-name class)))
(restart-case
(error "redefining class ~S incompatibly with the current definition"
name)
(register-layout new-layout :invalidate nil
:destruct-layout old-layout))))
+ #+sb-xc (/show0 "leaving %REDEFINE-DEFSTRUCT")
(values))
;;; This is called when we are about to define a structure class. It
(sb!xc:typep x (sb!xc:find-class class))))
(fdefinition constructor)))
(setf (class-direct-superclasses class)
- (if (eq (dd-name info) 'lisp-stream)
- ;; a hack to add STREAM as a superclass mixin to LISP-STREAMs
+ (if (eq (dd-name info) 'ansi-stream)
+ ;; a hack to add CL:STREAM as a superclass mixin to ANSI-STREAMs
(list (layout-class (svref inherits (1- (length inherits))))
(layout-class (svref inherits (- (length inherits) 2))))
(list (layout-class (svref inherits (1- (length inherits)))))))
;;; over this type, clearing the compiler structure type info, and
;;; undefining all the associated functions.
(defun undefine-structure (class)
+ #+sb-xc (/show0 "entering UNDEFINE-STRUCTURE")
(let ((info (layout-info (class-layout class))))
(when (defstruct-description-p info)
(let ((type (dd-name info)))
+ (remhash type *typecheckfuns*)
(setf (info :type :compiler-layout type) nil)
(undefine-fun-name (dd-copier-name info))
(undefine-fun-name (dd-predicate-name info))
;; Clear out the SPECIFIER-TYPE cache so that subsequent
;; references are unknown types.
(values-specifier-type-cache-clear)))
+ #+sb-xc (/show0 "leaving UNDEFINE-STRUCTURE")
(values))
\f
;;; Return a list of pairs (name . index). Used for :TYPE'd
#!+long-float
(complex-long-float '%raw-ref-complex-long)
(unsigned-byte 'aref)
- ((t)
- (if (eq (dd-type defstruct) 'funcallable-structure)
- '%funcallable-instance-info
- '%instance-ref)))
+ ((t) '%instance-ref))
(case rtype
#!+long-float
(complex-long-float
;;; These functions are called to actually make a constructor after we
;;; have processed the arglist. The correct variant (according to the
;;; DD-TYPE) should be called. The function is defined with the
-;;; specified name and arglist. Vars and Types are used for argument
-;;; type declarations. Values are the values for the slots (in order.)
+;;; specified name and arglist. VARS and TYPES are used for argument
+;;; type declarations. VALUES are the values for the slots (in order.)
;;;
-;;; This is split four ways because:
-;;; 1] list & vector structures need "name" symbols stuck in at
-;;; various weird places, whereas STRUCTURE structures have
-;;; a LAYOUT slot.
-;;; 2] We really want to use LIST to make list structures, instead of
-;;; MAKE-LIST/(SETF ELT).
-;;; 3] STRUCTURE structures can have raw slots that must also be
-;;; allocated and indirectly referenced. We use SLOT-ACCESSOR-FORM
-;;; to compute how to set the slots, which deals with raw slots.
-;;; 4] Funcallable structures are weird.
-(defun create-vector-constructor
- (defstruct cons-name arglist vars types values)
+;;; This is split three ways because:
+;;; * LIST & VECTOR structures need "name" symbols stuck in at
+;;; various weird places, whereas STRUCTURE structures have
+;;; a LAYOUT slot.
+;;; * We really want to use LIST to make list structures, instead of
+;;; MAKE-LIST/(SETF ELT).
+;;; * STRUCTURE structures can have raw slots that must also be
+;;; allocated and indirectly referenced. We use SLOT-ACCESSOR-FORM
+;;; to compute how to set the slots, which deals with raw slots.
+(defun create-vector-constructor (dd cons-name arglist vars types values)
(let ((temp (gensym))
- (etype (dd-element-type defstruct)))
+ (etype (dd-element-type dd)))
`(defun ,cons-name ,arglist
(declare ,@(mapcar #'(lambda (var type) `(type (and ,type ,etype) ,var))
vars types))
- (let ((,temp (make-array ,(dd-length defstruct)
- :element-type ',(dd-element-type defstruct))))
+ (let ((,temp (make-array ,(dd-length dd)
+ :element-type ',(dd-element-type dd))))
,@(mapcar #'(lambda (x)
`(setf (aref ,temp ,(cdr x)) ',(car x)))
- (find-name-indices defstruct))
+ (find-name-indices dd))
,@(mapcar #'(lambda (dsd value)
`(setf (aref ,temp ,(dsd-index dsd)) ,value))
- (dd-slots defstruct) values)
+ (dd-slots dd) values)
,temp))))
-(defun create-list-constructor
- (defstruct cons-name arglist vars types values)
- (let ((vals (make-list (dd-length defstruct) :initial-element nil)))
- (dolist (x (find-name-indices defstruct))
+(defun create-list-constructor (dd cons-name arglist vars types values)
+ (let ((vals (make-list (dd-length dd) :initial-element nil)))
+ (dolist (x (find-name-indices dd))
(setf (elt vals (cdr x)) `',(car x)))
- (loop for dsd in (dd-slots defstruct) and val in values do
+ (loop for dsd in (dd-slots dd) and val in values do
(setf (elt vals (dsd-index dsd)) val))
`(defun ,cons-name ,arglist
(declare ,@(mapcar #'(lambda (var type) `(type ,type ,var))
vars types))
(list ,@vals))))
-(defun create-structure-constructor
- (defstruct cons-name arglist vars types values)
+(defun create-structure-constructor (dd cons-name arglist vars types values)
(let* ((temp (gensym))
- (raw-index (dd-raw-index defstruct))
+ (raw-index (dd-raw-index dd))
(n-raw-data (when raw-index (gensym))))
`(defun ,cons-name ,arglist
(declare ,@(mapcar #'(lambda (var type) `(type ,type ,var))
vars types))
- (let ((,temp (truly-the ,(dd-name defstruct)
- (%make-instance ,(dd-length defstruct))))
+ (let ((,temp (truly-the ,(dd-name dd)
+ (%make-instance ,(dd-length dd))))
,@(when n-raw-data
`((,n-raw-data
- (make-array ,(dd-raw-length defstruct)
+ (make-array ,(dd-raw-length dd)
:element-type '(unsigned-byte 32))))))
(setf (%instance-layout ,temp)
- (%delayed-get-compiler-layout ,(dd-name defstruct)))
+ (%delayed-get-compiler-layout ,(dd-name dd)))
,@(when n-raw-data
`((setf (%instance-ref ,temp ,raw-index) ,n-raw-data)))
,@(mapcar (lambda (dsd value)
(multiple-value-bind (accessor index data)
- (slot-accessor-form defstruct dsd temp n-raw-data)
+ (slot-accessor-form dd dsd temp n-raw-data)
`(setf (,accessor ,data ,index) ,value)))
- (dd-slots defstruct)
+ (dd-slots dd)
values)
,temp))))
-(defun create-fin-constructor
- (defstruct cons-name arglist vars types values)
- (let ((temp (gensym)))
- `(defun ,cons-name ,arglist
- (declare ,@(mapcar #'(lambda (var type) `(type ,type ,var))
- vars types))
- (let ((,temp (truly-the
- ,(dd-name defstruct)
- (%make-funcallable-instance
- ,(dd-length defstruct)
- (%delayed-get-compiler-layout ,(dd-name defstruct))))))
- ,@(mapcar #'(lambda (dsd value)
- `(setf (%funcallable-instance-info
- ,temp ,(dsd-index dsd))
- ,value))
- (dd-slots defstruct) values)
- ,temp))))
;;; Create a default (non-BOA) keyword constructor.
(defun create-keyword-constructor (defstruct creator)
(defaults ())
(creator (ecase (dd-type defstruct)
(structure #'create-structure-constructor)
- (funcallable-structure #'create-fin-constructor)
(vector #'create-vector-constructor)
(list #'create-list-constructor))))
(dolist (constructor (dd-constructors defstruct))
(dolist (boa boas)
(res (create-boa-constructor defstruct boa creator)))
- (res))))
+ `((/show0 "beginning CONSTRUCTOR-DEFINITIONS forms")
+ ,@(res)
+ (/show0 "done with CONSTRUCTOR-DEFINITIONS forms")))))
+\f
+;;;; instances with ALTERNATE-METACLASS
+;;;;
+;;;; The CMU CL support for structures with ALTERNATE-METACLASS was a
+;;;; fairly general extension embedded in the main DEFSTRUCT code, and
+;;;; the result was an fairly impressive mess as ALTERNATE-METACLASS
+;;;; extension mixed with ANSI CL generality (e.g. :TYPE and :INCLUDE)
+;;;; and CMU CL implementation hairiness (esp. raw slots). This SBCL
+;;;; version is much less ambitious, noticing that ALTERNATE-METACLASS
+;;;; is only used to implement CONDITION, STANDARD-INSTANCE, and
+;;;; GENERIC-FUNCTION, and defining a simple specialized
+;;;; separate-from-DEFSTRUCT macro to provide only enough
+;;;; functionality to support those.
+;;;;
+;;;; KLUDGE: The defining macro here is so specialized that it's ugly
+;;;; in its own way. It also violates once-and-only-once by knowing
+;;;; much about structures and layouts that is already known by the
+;;;; main DEFSTRUCT macro. Hopefully it will go away presently
+;;;; (perhaps when CL:CLASS and SB-PCL:CLASS meet) as per FIXME below.
+;;;; -- WHN 2001-10-28
+;;;;
+;;;; FIXME: There seems to be no good reason to shoehorn CONDITION,
+;;;; STANDARD-INSTANCE, and GENERIC-FUNCTION into mutated structures
+;;;; instead of just implementing them as primitive objects. (This
+;;;; reduced-functionality macro seems pretty close to the
+;;;; functionality of DEFINE-PRIMITIVE-OBJECT..)
+
+(defun make-dd-with-alternate-metaclass (&key (class-name (missing-arg))
+ (superclass-name (missing-arg))
+ (metaclass-name (missing-arg))
+ (dd-type (missing-arg))
+ metaclass-constructor
+ slot-names)
+ (let* ((dd (make-defstruct-description class-name))
+ (conc-name (concatenate 'string (symbol-name class-name) "-"))
+ (dd-slots (let ((reversed-result nil)
+ ;; The index starts at 1 for ordinary
+ ;; named slots because slot 0 is
+ ;; magical, used for LAYOUT in
+ ;; CONDITIONs or for something (?) in
+ ;; funcallable instances.
+ (index 1))
+ (dolist (slot-name slot-names)
+ (push (make-defstruct-slot-description
+ :%name (symbol-name slot-name)
+ :index index
+ :accessor-name (symbolicate conc-name slot-name))
+ reversed-result)
+ (incf index))
+ (nreverse reversed-result))))
+ (setf (dd-alternate-metaclass dd) (list superclass-name
+ metaclass-name
+ metaclass-constructor)
+ (dd-slots dd) dd-slots
+ (dd-length dd) (1+ (length slot-names))
+ (dd-type dd) dd-type)
+ dd))
+
+(sb!xc:defmacro !defstruct-with-alternate-metaclass
+ (class-name &key
+ (slot-names (missing-arg))
+ (boa-constructor (missing-arg))
+ (superclass-name (missing-arg))
+ (metaclass-name (missing-arg))
+ (metaclass-constructor (missing-arg))
+ (dd-type (missing-arg))
+ predicate
+ (runtime-type-checks-p t))
+
+ (declare (type (and list (not null)) slot-names))
+ (declare (type (and symbol (not null))
+ boa-constructor
+ superclass-name
+ metaclass-name
+ metaclass-constructor))
+ (declare (type symbol predicate))
+ (declare (type (member structure funcallable-structure) dd-type))
+
+ (/show "entering !DEFSTRUCT-WITH-ALTERNATE-METACLASS expander" class-name)
+ (let* ((dd (make-dd-with-alternate-metaclass
+ :class-name class-name
+ :slot-names slot-names
+ :superclass-name superclass-name
+ :metaclass-name metaclass-name
+ :metaclass-constructor metaclass-constructor
+ :dd-type dd-type))
+ (conc-name (concatenate 'string (symbol-name class-name) "-"))
+ (dd-slots (dd-slots dd))
+ (dd-length (1+ (length slot-names)))
+ (object-gensym (gensym "OBJECT"))
+ (new-value-gensym (gensym "NEW-VALUE-"))
+ (delayed-layout-form `(%delayed-get-compiler-layout ,class-name)))
+ (multiple-value-bind (raw-maker-form raw-reffer-operator)
+ (ecase dd-type
+ (structure
+ (values `(let ((,object-gensym (%make-instance ,dd-length)))
+ (setf (%instance-layout ,object-gensym)
+ ,delayed-layout-form)
+ ,object-gensym)
+ '%instance-ref))
+ (funcallable-structure
+ (values `(%make-funcallable-instance ,dd-length
+ ,delayed-layout-form)
+ '%funcallable-instance-info)))
+ (/show dd raw-maker-form raw-reffer-operator)
+ `(progn
+
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ (%compiler-set-up-layout ',dd))
+
+ ;; slot readers and writers
+ (declaim (inline ,@(mapcar #'dsd-accessor-name dd-slots)))
+ ,@(mapcar (lambda (dsd)
+ `(defun ,(dsd-accessor-name dsd) (,object-gensym)
+ ,@(when runtime-type-checks-p
+ `((declare (type ,class-name ,object-gensym))))
+ (,raw-reffer-operator ,object-gensym
+ ,(dsd-index dsd))))
+ dd-slots)
+ (declaim (inline ,@(mapcar (lambda (dsd)
+ `(setf ,(dsd-accessor-name dsd)))
+ dd-slots)))
+ ,@(mapcar (lambda (dsd)
+ `(defun (setf ,(dsd-accessor-name dsd)) (,new-value-gensym
+ ,object-gensym)
+ ,@(when runtime-type-checks-p
+ `((declare (type ,class-name ,object-gensym))))
+ (setf (,raw-reffer-operator ,object-gensym
+ ,(dsd-index dsd))
+ ,new-value-gensym)))
+ dd-slots)
+
+ ;; constructor
+ (defun ,boa-constructor ,slot-names
+ (let ((,object-gensym ,raw-maker-form))
+ ,@(mapcar (lambda (slot-name)
+ (let ((dsd (find (symbol-name slot-name) dd-slots
+ :key #'dsd-%name
+ :test #'string=)))
+ `(setf (,(dsd-accessor-name dsd) ,object-gensym)
+ ,slot-name)))
+ slot-names)
+ ,object-gensym))
+
+ ;; predicate
+ ,@(when predicate
+ ;; Just delegate to the compiler's type optimization
+ ;; code, which knows how to generate inline type tests
+ ;; for the whole CMU CL INSTANCE menagerie.
+ `(defun ,predicate (,object-gensym)
+ (typep ,object-gensym ',class-name)))))))
\f
;;;; finalizing bootstrapping
-;;; early structure placeholder definitions: Set up layout and class
-;;; data for structures which are needed early.
+;;; Set up DD and LAYOUT for STRUCTURE-OBJECT class itself.
+;;;
+;;; Ordinary structure classes effectively :INCLUDE STRUCTURE-OBJECT
+;;; when they have no explicit :INCLUDEs, so (1) it needs to be set up
+;;; before we can define ordinary structure classes, and (2) it's
+;;; special enough (and simple enough) that we just build it by hand
+;;; instead of trying to generalize the ordinary DEFSTRUCT code.
+(defun !set-up-structure-object-class ()
+ (/show0 "entering !SET-UP-STRUCTURE-OBJECT-CLASS")
+ (let ((dd (make-defstruct-description 'structure-object)))
+ (setf
+ ;; Note: This has an ALTERNATE-METACLASS only because of blind
+ ;; clueless imitation of the CMU CL code -- dunno if or why it's
+ ;; needed. -- WHN
+ (dd-alternate-metaclass dd) '(instance)
+ (dd-slots dd) nil
+ (dd-length dd) 1
+ (dd-type dd) 'structure)
+ (/show0 "about to %COMPILER-SET-UP-LAYOUT")
+ (%compiler-set-up-layout dd))
+ (/show0 "leaving !SET-UP-STRUCTURE-OBJECT-CLASS"))
+(!set-up-structure-object-class)
+
+;;; early structure predeclarations: Set up DD and LAYOUT for ordinary
+;;; (non-ALTERNATE-METACLASS) structures which are needed early.
(dolist (args
'#.(sb-cold:read-from-file
"src/code/early-defstruct-args.lisp-expr"))