1.0.0.27: various PCL cleanups in cache.lisp
[sbcl.git] / src / code / defstruct.lisp
index 89a8b9c..a3dbf1e 100644 (file)
               `((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))
 ;;; !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)