(lambda (dependent)
(apply #'update-dependent class dependent initargs))))
-(defmethod shared-initialize :after ((slotd structure-slot-definition)
- slot-names
- &key (allocation :instance))
- (declare (ignore slot-names))
+(defmethod shared-initialize :after
+ ((slotd structure-slot-definition) slot-names &key
+ (allocation :instance) allocation-class)
+ (declare (ignore slot-names allocation-class))
(unless (eq allocation :instance)
(error "Structure slots must have :INSTANCE allocation.")))
collect))
(nreverse collect)))
-(defun compute-layout (cpl instance-eslotds)
- (let* ((names
- (let (collect)
- (dolist (eslotd instance-eslotds)
- (when (eq (slot-definition-allocation eslotd) :instance)
- (push (slot-definition-name eslotd) collect)))
- (nreverse collect)))
- (order ()))
- (labels ((rwalk (tail)
- (when tail
- (rwalk (cdr tail))
- (dolist (ss (class-slots (car tail)))
- (let ((n (slot-definition-name ss)))
- (when (member n names)
- (setq order (cons n order)
- names (remove n names))))))))
- (rwalk (if (slot-boundp (car cpl) 'slots)
- cpl
- (cdr cpl)))
- (reverse (append names order)))))
-
(defun update-gfs-of-class (class)
(when (and (class-finalized-p class)
(let ((cpl (class-precedence-list class)))
;; The list is in most-specific-first order.
(let ((name-dslotds-alist ()))
(dolist (c (class-precedence-list class))
- (let ((dslotds (class-direct-slots c)))
- (dolist (d dslotds)
- (let* ((name (slot-definition-name d))
- (entry (assq name name-dslotds-alist)))
- (if entry
- (push d (cdr entry))
- (push (list name d) name-dslotds-alist))))))
+ (dolist (slot (class-direct-slots c))
+ (let* ((name (slot-definition-name slot))
+ (entry (assq name name-dslotds-alist)))
+ (if entry
+ (push slot (cdr entry))
+ (push (list name slot) name-dslotds-alist)))))
(mapcar (lambda (direct)
(compute-effective-slot-definition class
(nreverse (cdr direct))))
name-dslotds-alist)))
-(defmethod compute-slots :around ((class std-class))
+(defmethod compute-slots ((class standard-class))
+ (call-next-method))
+
+(defmethod compute-slots :around ((class standard-class))
(let ((eslotds (call-next-method))
- (cpl (class-precedence-list class))
- (instance-slots ())
- (class-slots ()))
- (dolist (eslotd eslotds)
- (let ((alloc (slot-definition-allocation eslotd)))
- (case alloc
- (:instance (push eslotd instance-slots))
- (:class (push eslotd class-slots)))))
- (let ((nlayout (compute-layout cpl instance-slots)))
- (dolist (eslotd instance-slots)
- (setf (slot-definition-location eslotd)
- (position (slot-definition-name eslotd) nlayout))))
- (dolist (eslotd class-slots)
+ (location -1))
+ (dolist (eslotd eslotds eslotds)
(setf (slot-definition-location eslotd)
- (assoc (slot-definition-name eslotd)
- (class-slot-cells (slot-definition-class eslotd)))))
- (mapc #'initialize-internal-slot-functions eslotds)
- eslotds))
+ (ecase (slot-definition-allocation eslotd)
+ (:instance
+ (incf location))
+ (:class
+ (let* ((name (slot-definition-name eslotd))
+ (from-class (slot-definition-allocation-class eslotd))
+ (cell (assq name (class-slot-cells from-class))))
+ (aver (consp cell))
+ cell))))
+ (initialize-internal-slot-functions eslotd))))
+
+(defmethod compute-slots ((class funcallable-standard-class))
+ (call-next-method))
+
+(defmethod compute-slots :around ((class funcallable-standard-class))
+ (labels ((instance-slot-names (slotds)
+ (let (collect)
+ (dolist (slotd slotds (nreverse collect))
+ (when (eq (slot-definition-allocation slotd) :instance)
+ (push (slot-definition-name slotd) collect)))))
+ ;; This sorts slots so that slots of classes later in the CPL
+ ;; come before slots of other classes. This is crucial for
+ ;; funcallable instances because it ensures that the slots of
+ ;; FUNCALLABLE-STANDARD-OBJECT, which includes the slots of
+ ;; KERNEL:FUNCALLABLE-INSTANCE, come first, which in turn
+ ;; makes it possible to treat FUNCALLABLE-STANDARD-OBJECT as
+ ;; a funcallable instance.
+ (compute-layout (eslotds)
+ (let ((first ())
+ (names (instance-slot-names eslotds)))
+ (dolist (class
+ (reverse (class-precedence-list class))
+ (nreverse (nconc names first)))
+ (dolist (ss (class-slots class))
+ (let ((name (slot-definition-name ss)))
+ (when (member name names)
+ (push name first)
+ (setq names (delete name names)))))))))
+ (let ((all-slotds (call-next-method))
+ (instance-slots ())
+ (class-slots ()))
+ (dolist (slotd all-slotds)
+ (ecase (slot-definition-allocation slotd)
+ (:instance (push slotd instance-slots))
+ (:class (push slotd class-slots))))
+ (let ((layout (compute-layout instance-slots)))
+ (dolist (slotd instance-slots)
+ (setf (slot-definition-location slotd)
+ (position (slot-definition-name slotd) layout))
+ (initialize-internal-slot-functions slotd)))
+ (dolist (slotd class-slots)
+ (let ((name (slot-definition-name slotd))
+ (from-class (slot-definition-allocation-class slotd)))
+ (setf (slot-definition-location slotd)
+ (assoc name (class-slot-cells from-class)))
+ (aver (consp (slot-definition-location slotd)))
+ (initialize-internal-slot-functions slotd)))
+ all-slotds)))
(defmethod compute-slots ((class structure-class))
(mapcan (lambda (superclass)
(initform nil)
(initargs nil)
(allocation nil)
+ (allocation-class nil)
(type t)
(namep nil)
(initp nil)
initp t)))
(unless allocp
(setq allocation (slot-definition-allocation slotd)
+ allocation-class (slot-definition-class slotd)
allocp t))
(setq initargs (append (slot-definition-initargs slotd) initargs))
(let ((slotd-type (slot-definition-type slotd)))
:initfunction initfunction
:initargs initargs
:allocation allocation
+ :allocation-class allocation-class
:type type
:class class)))