chiark / gitweb /
src/class-finalize-{proto,impl}.lisp (finalize-sod-class): Add `:around'.
[sod] / src / class-finalize-impl.lisp
index a51075b6d94245aafe8ca8582d849eec462659c9..32bc29b812037e8663fc19fb67b89e5177da8248 100644 (file)
@@ -421,67 +421,81 @@ (defmethod check-sod-class ((class sod-class))
 ;;;--------------------------------------------------------------------------
 ;;; Finalization.
 
-(defmethod finalize-sod-class ((class sod-class))
+(defmethod finalize-sod-class :around ((class sod-class))
+  "Common functionality for `finalize-sod-class'.
 
-  ;; CLONE-AND-HACK WARNING: Note that `bootstrap-classes' has a (very brief)
-  ;; clone of the CPL and chain establishment code.  If the interface changes
-  ;; then `bootstrap-classes' will need to be changed too.
+     * If an attempt to finalize the CLASS has been made before, then we
+       don't try again.  Similarly, attempts to finalize a class recursively
+       will fail.
 
+     * A condition handler is established to keep track of whether any errors
+       are signalled during finalization.  The CLASS is only marked as
+       successfully finalized if no (unhandled) errors are encountered."
   (with-default-error-location (class)
     (ecase (sod-class-state class)
       ((nil)
 
-       ;; If this fails, mark the class as a loss.
+       ;; If this fails, leave the class marked as a loss.
        (setf (slot-value class 'state) :broken)
 
-       ;; Set up the metaclass if it's not been set already.  This is delayed
-       ;; to give bootstrapping a chance to set up metaclass and superclass
-       ;; circularities.
-       (default-slot (class 'metaclass) (guess-metaclass class))
-
-       ;; Finalize all of the superclasses.  There's some special pleading
-       ;; here to make bootstrapping work: we don't try to finalize the
-       ;; metaclass if we're a root class (no direct superclasses -- because
-       ;; in that case the metaclass will have to be a subclass of us!), or
-       ;; if it's equal to us.  This is enough to tie the knot at the top of
-       ;; the class graph.
-       (with-slots (name direct-superclasses metaclass) class
-        (dolist (super direct-superclasses)
-          (finalize-sod-class super))
-        (unless (or (null direct-superclasses)
-                    (eq class metaclass))
-          (finalize-sod-class metaclass)))
-
-       ;; Stash the class's type.
-       (setf (slot-value class '%type)
-            (make-class-type (sod-class-name class)))
-
-       ;; Clobber the lists of items if they've not been set.
-       (dolist (slot '(slots instance-initializers class-initializers
-                      messages methods))
-        (unless (slot-boundp class slot)
-          (setf (slot-value class slot) nil)))
-
-       ;; If the CPL hasn't been done yet, compute it.
-       (with-slots (class-precedence-list) class
-        (unless (slot-boundp class 'class-precedence-list)
-          (setf class-precedence-list (compute-cpl class))))
-
-       ;; Check that the class is fairly sane.
-       (check-sod-class class)
-
-       ;; Determine the class's layout.
-       (with-slots (chain-head chain chains) class
-        (setf (values chain-head chain chains) (compute-chains class)))
-
-       ;; Done.
+       ;; Invoke the finalization method proper.
+       (call-next-method)
        (setf (slot-value class 'state) :finalized)
        t)
 
+      ;; If the class is broken, we're not going to be able to fix it now.
       (:broken
        nil)
 
+      ;; If we already finalized it, there's no point doing it again.
       (:finalized
        t))))
 
+(defmethod finalize-sod-class ((class sod-class))
+
+  ;; CLONE-AND-HACK WARNING: Note that `bootstrap-classes' has a (very brief)
+  ;; clone of the CPL and chain establishment code.  If the interface changes
+  ;; then `bootstrap-classes' will need to be changed too.
+
+  ;; Set up the metaclass if it's not been set already.  This is delayed
+  ;; to give bootstrapping a chance to set up metaclass and superclass
+  ;; circularities.
+  (default-slot (class 'metaclass) (guess-metaclass class))
+
+  ;; Finalize all of the superclasses.  There's some special pleading here to
+  ;; make bootstrapping work: we don't try to finalize the metaclass if we're
+  ;; a root class (no direct superclasses -- because in that case the
+  ;; metaclass will have to be a subclass of us!), or if it's equal to us.
+  ;; This is enough to tie the knot at the top of the class graph.
+  (with-slots (name direct-superclasses metaclass) class
+    (dolist (super direct-superclasses)
+      (finalize-sod-class super))
+    (unless (or (null direct-superclasses)
+               (eq class metaclass))
+      (finalize-sod-class metaclass)))
+
+  ;; Stash the class's type.
+  (setf (slot-value class '%type)
+       (make-class-type (sod-class-name class)))
+
+  ;; Clobber the lists of items if they've not been set.
+  (dolist (slot '(slots instance-initializers class-initializers
+                 messages methods))
+    (unless (slot-boundp class slot)
+      (setf (slot-value class slot) nil)))
+
+  ;; If the CPL hasn't been done yet, compute it.
+  (with-slots (class-precedence-list) class
+    (unless (slot-boundp class 'class-precedence-list)
+      (setf class-precedence-list (compute-cpl class))))
+
+  ;; Check that the class is fairly sane.
+  (check-sod-class class)
+
+  ;; Determine the class's layout.
+  (setf (values (slot-value class 'chain-head)
+               (slot-value class 'chain)
+               (slot-value class 'chains))
+       (compute-chains class)))
+
 ;;;----- That's all, folks --------------------------------------------------