X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e0808c472145fc81e52898bc9ac289e10c4f4f41..91d9ba3cb6ed57640dc29c2b2e73bb89e2628484:/src/class-finalize-impl.lisp diff --git a/src/class-finalize-impl.lisp b/src/class-finalize-impl.lisp index 25ce1c2..36d56e0 100644 --- a/src/class-finalize-impl.lisp +++ b/src/class-finalize-impl.lisp @@ -276,6 +276,35 @@ (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)) @@ -352,6 +381,11 @@ ;; 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 @@ -397,13 +431,13 @@ (:finalized t)))) -(macrolet ((define-layout-slot (slot (class) &body body) - `(define-on-demand-slot sod-class ,slot (,class) - (check-class-is-finalized ,class) - ,@body))) - (flet ((check-class-is-finalized (class) - (unless (eq (sod-class-state class) :finalized) - (error "Class ~S is not finalized" class)))) +(flet ((check-class-is-finalized (class) + (unless (eq (sod-class-state class) :finalized) + (error "Class ~S is not finalized" class)))) + (macrolet ((define-layout-slot (slot (class) &body body) + `(define-on-demand-slot sod-class ,slot (,class) + (check-class-is-finalized ,class) + ,@body))) (define-layout-slot %ilayout (class) (compute-ilayout class)) (define-layout-slot effective-methods (class)