`((setf (structure-classoid-constructor (find-classoid ',name))
#',def-con))))))))
-;;; shared logic for CL:DEFSTRUCT and SB!XC:DEFSTRUCT
+;;; shared logic for host macroexpansion for SB!XC:DEFSTRUCT and
+;;; cross-compiler macroexpansion for CL:DEFSTRUCT
(defmacro !expander-for-defstruct (name-and-options
slot-descriptions
expanding-into-code-for-xc-host-p)
;; class.
(with-single-package-locked-error
(:symbol ',name "defining ~A as a structure"))
- (%defstruct ',dd ',inherits)
+ (%defstruct ',dd ',inherits (sb!c:source-location))
(eval-when (:compile-toplevel :load-toplevel :execute)
(%compiler-defstruct ',dd ',inherits))
,@(unless expanding-into-code-for-xc-host-p
(:symbol ',name "defining ~A as a structure"))
(eval-when (:compile-toplevel :load-toplevel :execute)
(setf (info :typed-structure :info ',name) ',dd))
+ (eval-when (:load-toplevel :execute)
+ (setf (info :source-location :typed-structure ',name)
+ (sb!c:source-location)))
,@(unless expanding-into-code-for-xc-host-p
(append (typed-accessor-definitions dd)
(typed-predicate-definitions dd)
(typed-copier-definitions dd)
- (constructor-definitions dd)))
+ (constructor-definitions dd)
+ (when (dd-doc dd)
+ `((setf (fdocumentation ',(dd-name dd) 'structure)
+ ',(dd-doc dd))))))
',name)))))
(sb!xc:defmacro defstruct (name-and-options &rest slot-descriptions)
;;; incompatible redefinition. Define those functions which are
;;; sufficiently stereotyped that we can implement them as standard
;;; closures.
-(defun %defstruct (dd inherits)
+(defun %defstruct (dd inherits source-location)
(declare (type defstruct-description dd))
;; We set up LAYOUTs even in the cross-compilation host.
(setq layout (classoid-layout classoid))))
(setf (find-classoid (dd-name dd)) classoid)
+ (sb!c:with-source-location (source-location)
+ (setf (layout-source-location layout) source-location))
+
;; Various other operations only make sense on the target SBCL.
#-sb-xc-host
(%target-defstruct dd layout))
;;; Return a LAMBDA form which can be used to set a slot.
(defun slot-setter-lambda-form (dd dsd)
- `(lambda (new-value instance)
- ,(funcall (nth-value 1 (slot-accessor-transforms dd dsd))
- '(dummy new-value instance))))
+ ;; KLUDGE: Evaluating the results of SLOT-ACCESSOR-TRANSFORMS needs
+ ;; a lexenv.
+ (let ((sb!c:*lexenv* (if (boundp 'sb!c:*lexenv*)
+ sb!c:*lexenv*
+ (sb!c::make-null-lexenv))))
+ `(lambda (new-value instance)
+ ,(funcall (nth-value 1 (slot-accessor-transforms dd dsd))
+ '(dummy new-value instance)))))
;;; 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))))
+ ;; 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. (But note
+ ;; FUNCALLABLE-STRUCTUREs need
+ ;; assistance here)
+ (inherits (vector (find-layout t))))
(multiple-value-bind (classoid layout old-layout)
(multiple-value-bind (clayout clayout-p)
(lambda (x)
(sb!xc:typep x 'structure-classoid))
(lambda (x)
- (sb!xc:typep x (find-classoid class))))
+ (sb!xc:typep x (classoid-name (find-classoid class)))))
(fdefinition constructor)))
(setf (classoid-direct-superclasses class)
(case (dd-name info)
(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.
+ ;; The index starts at 1 for ordinary named
+ ;; slots because slot 0 is magical, used for
+ ;; the LAYOUT in CONDITIONs and
+ ;; FUNCALLABLE-INSTANCEs. (This is the same
+ ;; in ordinary structures too: see (INCF
+ ;; DD-LENGTH) in
+ ;; PARSE-DEFSTRUCT-NAME-AND-OPTIONS).
(index 1))
(dolist (slot-name slot-names)
(push (make-defstruct-slot-description
reversed-result)
(incf index))
(nreverse reversed-result))))
+ (case dd-type
+ ;; We don't support inheritance of alternate metaclass stuff,
+ ;; and it's not a general-purpose facility, so sanity check our
+ ;; own code.
+ (structure
+ (aver (eq superclass-name 't)))
+ (funcallable-structure
+ (aver (eq superclass-name 'function)))
+ (t (bug "Unknown DD-TYPE in ALTERNATE-METACLASS: ~S" dd-type)))
(setf (dd-alternate-metaclass dd) (list superclass-name
metaclass-name
metaclass-constructor)
(dd-type dd) dd-type)
dd))
+;;; make !DEFSTRUCT-WITH-ALTERNATE-METACLASS compilable by the host
+;;; lisp, installing the information we need to reason about the
+;;; structures (layouts and classoids).
+;;;
+;;; FIXME: we should share the parsing and the DD construction between
+;;; this and the cross-compiler version, but my brain was too small to
+;;; get that right. -- CSR, 2006-09-14
+#+sb-xc-host
+(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))
+ (declare (ignore boa-constructor predicate runtime-type-checks-p))
+
+ (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)))
+ `(progn
+
+ (eval-when (:compile-toplevel :load-toplevel :execute)
+ (%compiler-set-up-layout ',dd ',(inherits-for-structure dd))))))
+
(sb!xc:defmacro !defstruct-with-alternate-metaclass
(class-name &key
(slot-names (missing-arg))
,object-gensym)
'%instance-ref))
(funcallable-structure
- (values `(%make-funcallable-instance ,dd-length
- ,delayed-layout-form)
+ (values `(let ((,object-gensym
+ (%make-funcallable-instance ,dd-length)))
+ (setf (%funcallable-instance-layout ,object-gensym)
+ ,delayed-layout-form)
+ ,object-gensym)
'%funcallable-instance-info)))
`(progn
(eval-when (:compile-toplevel :load-toplevel :execute)
- (%compiler-set-up-layout ',dd))
+ (%compiler-set-up-layout ',dd ',(inherits-for-structure dd)))
;; slot readers and writers
(declaim (inline ,@(mapcar #'dsd-accessor-name dd-slots)))
;; 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-alternate-metaclass dd) '(t)
(dd-slots dd) nil
(dd-length dd) 1
(dd-type dd) 'structure)
(inherits (inherits-for-structure dd)))
(%compiler-defstruct dd inherits)))
+;;; finding these beasts
+(defun find-defstruct-description (name &optional (errorp t))
+ (let ((info (layout-info (classoid-layout (find-classoid name errorp)))))
+ (if (defstruct-description-p info)
+ info
+ (when errorp
+ (error "No DEFSTRUCT-DESCRIPTION for ~S." name)))))
+
(/show0 "code/defstruct.lisp end of file")