+;;;; target-only parts of the DEFSTRUCT top-level code
+
+;;; Catch attempts to mess up definitions of symbols in the CL package.
+(defun protect-cl (symbol)
+ (/show0 "entering PROTECT-CL, SYMBOL=..")
+ (/hexstr 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))
+ (/show0 "leaving PROTECT-CL")
+ (values))
+
+;;; the part of %DEFSTRUCT which sets up out-of-line implementations
+;;; of those structure functions which are sufficiently similar
+;;; between structures that they can be closures
+;;;
+;;; (The "static" in the name is because it needs to be done not only
+;;; in ordinary toplevel %DEFSTRUCT, but also in cold init as early as
+;;; possible, to simulate static linking of structure functions as
+;;; nearly as possible.)
+(defun %target-defstruct (dd layout)
+ (declare (type defstruct-description dd))
+ (declare (type layout layout))
+
+ (/show0 "entering %TARGET-DEFSTRUCT")
+
+ ;; (Constructors aren't set up here, because constructors are
+ ;; varied enough (possibly parsing any specified argument list)
+ ;; that we can't reasonably implement them as closures, and so
+ ;; implement them with DEFUN instead.)
+
+ ;; Set FDEFINITIONs for slot accessors.
+ (dolist (dsd (dd-slots dd))
+ (/show0 "doing FDEFINITION for slot accessor")
+ (let ((accessor-name (dsd-accessor-name dsd)))
+ (/show0 "ACCESSOR-NAME=..")
+ (/hexstr accessor-name)
+ (protect-cl accessor-name)
+ (/hexstr "getting READER-FUN and WRITER-FUN")
+ (multiple-value-bind (reader-fun writer-fun) (slot-accessor-funs dd dsd)
+ (declare (type function reader-fun writer-fun))
+ (/show0 "got READER-FUN and WRITER-FUN=..")
+ (/hexstr reader-fun)
+ (setf (symbol-function accessor-name) reader-fun)
+ (unless (dsd-read-only dsd)
+ (/show0 "setting FDEFINITION for WRITER-FUN=..")
+ (/hexstr writer-fun)
+ (setf (fdefinition `(setf ,accessor-name)) writer-fun)))))
+
+ ;; Set FDEFINITION for copier.
+ (when (dd-copier-name dd)
+ (/show0 "doing FDEFINITION for copier")
+ (protect-cl (dd-copier-name dd))
+ ;; We can't use COPY-STRUCTURE for other kinds of objects, notably
+ ;; funcallable structures, since it returns a STRUCTURE-OBJECT.
+ ;; (And funcallable instances don't need copiers anyway.)
+ (aver (eql (dd-type dd) 'structure))
+ (setf (symbol-function (dd-copier-name dd))
+ ;; FIXME: should use a closure which checks arg type before copying
+ #'copy-structure))
+
+ ;; Set FDEFINITION for predicate.
+ (when (dd-predicate-name dd)
+ (/show0 "doing FDEFINITION for predicate")
+ (protect-cl (dd-predicate-name dd))
+ (setf (symbol-function (dd-predicate-name dd))
+ (ecase (dd-type dd)
+ ;; structures with LAYOUTs
+ ((structure funcallable-structure)
+ (/show0 "with-LAYOUT case")
+ (lambda (object)
+ (declare (optimize (speed 3) (safety 0)))
+ (/noshow0 "in with-LAYOUT structure predicate closure, OBJECT,LAYOUT=..")
+ (/nohexstr object)
+ (/nohexstr layout)
+ (typep-to-layout object layout)))
+ ;; structures with no LAYOUT (i.e. :TYPE VECTOR or :TYPE LIST)
+ ;;
+ ;; FIXME: should handle the :NAMED T case in these cases
+ (vector
+ (/show0 ":TYPE VECTOR case")
+ #'vectorp)
+ (list
+ (/show0 ":TYPE LIST case")
+ #'listp))))
+
+ (/show0 "leaving %TARGET-DEFSTRUCT")
+ (values))
+\f