src/class-make-impl.lisp: Don't store `nil' in the `metaclass' slot.
[sod] / src / class-finalize-impl.lisp
index 25ce1c2..23d7107 100644 (file)
                                         (cdr class-precedence-list)))))))))
 
 ;;;--------------------------------------------------------------------------
+;;; Metaclasses.
+
+(defun maximum (items order what)
+  "Return a maximum item according to the non-strict partial ORDER."
+  (reduce (lambda (best this)
+           (cond ((funcall order best this) best)
+                 ((funcall order this best) this)
+                 (t (error "Unable to choose best ~A." what))))
+         items))
+
+(defmethod guess-metaclass ((class sod-class))
+  "Default metaclass-guessing function for classes.
+
+   Return the most specific metaclass of any of the CLASS's direct
+   superclasses."
+
+  ;; During bootstrapping, our superclasses might not have their own
+  ;; metaclasses resolved yet.  If we find this, then throw `bootstrapping'
+  ;; so that `shared-initialize' on `sod-class' can catch it (or as a shot
+  ;; across the bows of anyone else who calls us).
+  (maximum (mapcar (lambda (super)
+                    (if (slot-boundp super 'metaclass)
+                        (slot-value super 'metaclass)
+                        (throw 'bootstrapping nil)))
+                  (sod-class-direct-superclasses class))
+          #'sod-subclass-p
+          (format nil "metaclass for `~A'" class)))
+
+;;;--------------------------------------------------------------------------
 ;;; Sanity checking.
 
 (defmethod check-sod-class ((class sod-class))
        ;; If this fails, mark the class 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