chiark / gitweb /
Made toggle reference depend on glib2.8
[clg] / glib / pcl.lisp
index 39b973a57819ab8a36fbed1e224f0fbc2a217254..334fc28a06d313c54aa44c06983d10a1c1fc1be0 100644 (file)
 ;;;
 
 ;;; Modifications for better AMOP conformance
-;;; Copyright (C) 2001 Espen S. Johnsen <esj@stud.cs.uit.no>
+;;; by Espen S. Johnsen <espen@users.sf.net>
 
-(in-package "PCL")
-
-;;;; Adding initargs parameter to change-class
 
-(defun change-class-internal (instance new-class initargs)
-  (let* ((old-class (class-of instance))
-        (copy (allocate-instance new-class))
-        (new-wrapper (get-wrapper copy))
-        (old-wrapper (class-wrapper old-class))
-        (old-layout (wrapper-instance-slots-layout old-wrapper))
-        (new-layout (wrapper-instance-slots-layout new-wrapper))
-        (old-slots (get-slots instance))
-        (new-slots (get-slots copy))
-        (old-class-slots (wrapper-class-slots old-wrapper)))
+(eval-when (:compile-toplevel :load-toplevel :execute)
+  (setf (ext:package-lock (find-package "PCL")) nil))
 
-    ;;
-    ;; "The values of local slots specified by both the class Cto and
-    ;; Cfrom are retained.  If such a local slot was unbound, it remains
-    ;; unbound."
-    ;;     
-    (iterate ((new-slot (list-elements new-layout))
-             (new-position (interval :from 0)))
-      (let ((old-position (posq new-slot old-layout)))
-       (when old-position
-         (setf (instance-ref new-slots new-position)
-               (instance-ref old-slots old-position)))))
+(in-package "PCL")
 
+(defstruct slot-info
+  (name nil :type symbol)
+  ;;
+  ;; Specified slot allocation.or :INSTANCE.
+  (allocation :instance :type (or (member :class :instance) t))
+  ;;
+  ;; Specified slot type or T.
+  (type t :type (or symbol list)))
+
+
+(defmethod compute-slots :around ((class standard-class))
+  (loop with slotds = (call-next-method) and location = -1
+       for slot in slotds do
+         (setf (slot-definition-location slot)
+               (case (slot-definition-allocation slot)
+                 (:instance
+                  (incf location))
+                 (:class
+                  (let* ((name (slot-definition-name slot))
+                         (from-class (slot-definition-allocation-class slot))
+                         (cell (assq name (class-slot-cells from-class))))
+                    (assert (consp cell))
+                    cell))))
+         (initialize-internal-slot-functions slot)
+       finally
+         (return slotds)))
+
+
+
+(defun update-slots (class eslotds)
+  (collect ((instance-slots) (class-slots))
+    (dolist (eslotd eslotds)
+      (case (slot-definition-allocation eslotd)
+       (:instance (instance-slots eslotd))
+       (:class (class-slots eslotd))))
     ;;
-    ;; "The values of slots specified as shared in the class Cfrom and
-    ;; as local in the class Cto are retained."
-    ;;
-    (iterate ((slot-and-val (list-elements old-class-slots)))
-      (let ((position (posq (car slot-and-val) new-layout)))
-       (when position
-         (setf (instance-ref new-slots position) (cdr slot-and-val)))))
-
-    ;; Make the copy point to the old instance's storage, and make the
-    ;; old instance point to the new storage.
-    (swap-wrappers-and-slots instance copy)
-
-    (apply #'update-instance-for-different-class copy instance initargs)
-    instance))
-
-
-(fmakunbound 'change-class)
-(defgeneric change-class (instance new-class &rest initargs))
-
-(defmethod change-class ((instance standard-object)
-                        (new-class standard-class)
-                        &rest initargs)
-  (change-class-internal instance new-class initargs))
-
-(defmethod change-class ((instance funcallable-standard-object)
-                        (new-class funcallable-standard-class)
-                        &rest initargs)
-  (change-class-internal instance new-class initargs))
-
-(defmethod change-class ((instance standard-object)
-                        (new-class funcallable-standard-class)
-                        &rest initargs)
-  (declare (ignore initargs))
-  (error "Can't change the class of ~S to ~S~@
-          because it isn't already an instance with metaclass ~S."
-        instance new-class 'standard-class))
-
-(defmethod change-class ((instance funcallable-standard-object)
-                        (new-class standard-class)
-                        &rest initargs)
-  (declare (ignore initargs))
-  (error "Can't change the class of ~S to ~S~@
-          because it isn't already an instance with metaclass ~S."
-        instance new-class 'funcallable-standard-class))
-
-(defmethod change-class ((instance t) (new-class symbol) &rest initargs)
-  (change-class instance (find-class new-class) initargs))
-
-
-;;;; Make the class finalization protocol behave as specified in AMOP
-
-(defmethod ensure-class-using-class (name (class pcl-class) &rest args &key)
-  (multiple-value-bind (meta initargs)
-      (ensure-class-values class args)
-    (if (eq (class-of class) meta)
-       (apply #'reinitialize-instance class initargs)
-      (apply #'change-class class meta initargs))
-    (setf (find-class name) class)
-    (inform-type-system-about-class class name)
-    class))
-
-(defmethod finalize-inheritance ((class std-class))
-  (dolist (super (class-direct-superclasses class))
-    (unless (class-finalized-p super) (finalize-inheritance super)))
-  (update-cpl class (compute-class-precedence-list class))
-  (update-slots class (compute-slots class))
-  (update-gfs-of-class class)
-  (update-inits class (compute-default-initargs class))
-  (update-make-instance-function-table class))
-
-(defmethod finalize-inheritance ((class forward-referenced-class))
-  (error "~A can't be finalized" class))
-
-(defun update-class (class &optional finalizep)  
-  (declare (ignore finalizep))
-  (unless (class-has-a-forward-referenced-superclass-p class)
-    (finalize-inheritance class)
-    (dolist (sub (class-direct-subclasses class))
-      (update-class sub))))
-
+    ;; If there is a change in the shape of the instances then the
+    ;; old class is now obsolete.
+    (let* ((nlayout (mapcar #'slot-definition-name
+                           (sort (instance-slots) #'<
+                                 :key #'slot-definition-location)))
+          (nslots (length nlayout))
+          (nwrapper-class-slots (compute-class-slots (class-slots)))
+          (owrapper (when (class-finalized-p class)
+                      (class-wrapper class)))
+          (olayout (when owrapper
+                     (wrapper-instance-slots-layout owrapper)))
+          (nwrapper
+           (cond ((null owrapper)
+                  (make-wrapper nslots class))
+                 ;;
+                 ;; We cannot reuse the old wrapper easily when it
+                 ;; has class slot cells, even if these cells are
+                 ;; EQUAL to the ones used in the new wrapper.  The
+                 ;; class slot cells of OWRAPPER may be referenced
+                 ;; from caches, and if we don't change the wrapper,
+                 ;; the caches won't notice that something has
+                 ;; changed.  We could do something here manually,
+                 ;; but I don't think it's worth it.
+                 ((and (equal nlayout olayout)
+                       (null (wrapper-class-slots owrapper)))
+                  owrapper)
+                 (t
+                  ;;
+                  ;; This will initialize the new wrapper to have the same
+                  ;; state as the old wrapper.  We will then have to change
+                  ;; that.  This may seem like wasted work (it is), but the
+                  ;; spec requires that we call make-instances-obsolete.
+                  (make-instances-obsolete class)
+                  (class-wrapper class)))))
+
+      (with-slots (wrapper slots finalized-p) class
+       (update-lisp-class-layout class nwrapper)
+       (setf slots eslotds
+             (wrapper-instance-slots-layout nwrapper) nlayout
+             (wrapper-class-slots nwrapper) nwrapper-class-slots
+             (wrapper-no-of-instance-slots nwrapper) nslots
+             wrapper nwrapper
+             finalized-p t))
+
+      (unless (eq owrapper nwrapper)
+       (update-inline-access class)
+       (update-pv-table-cache-info class)
+       (maybe-update-standard-class-locations class)))))
+
+
+(pushnew :non-broken-pcl *features*)