X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/sod/blobdiff_plain/3a774b55edfea441c1715994924c2999e9202143..d1c01c331ae3f2994d65b9d41655b0d4f2fcbf3d:/src/class-make-impl.lisp diff --git a/src/class-make-impl.lisp b/src/class-make-impl.lisp index 7495c01..5a897d4 100644 --- a/src/class-make-impl.lisp +++ b/src/class-make-impl.lisp @@ -28,32 +28,52 @@ (cl:in-package #:sod) ;;;-------------------------------------------------------------------------- ;;; Classes. +(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." + + (select-minimal-class-property (sod-class-direct-superclasses class) + #'sod-class-metaclass + #'sod-subclass-p class "metaclass")) + (defmethod shared-initialize :after ((class sod-class) slot-names &key pset) "Specific behaviour for SOD class initialization. Properties inspected are as follows: - * `:metaclass' names the metaclass to use. If unspecified, nil is - stored, and (unless you intervene later) `guess-metaclass' will be - called by `finalize-sod-class' to find a suitable default. + * `:metaclass' names the metaclass to use. If unspecified, this will be + left unbound, and (unless you intervene later) `guess-metaclass' will + be called by `finalize-sod-class' to find a suitable default. * `:nick' provides a nickname for the class. If unspecified, a default (the class's name, forced to lowercase) will be chosen in `finalize-sod-class'. * `:link' names the chained superclass. If unspecified, this class will - be left at the head of its chain." + be left at the head of its chain. + + Usually, the class's metaclass is determined here, either direcly from the + `:metaclass' property or by calling `guess-metaclass'. Guessing is + inhibited if the `:%bootstrapping' property is non-nil." ;; If no nickname, copy the class name. It won't be pretty, though. (default-slot-from-property (class 'nickname slot-names) (pset :nick :id) (string-downcase (slot-value class 'name))) - ;; Set the metaclass if the appropriate property has been provided; - ;; otherwise leave it unbound for now, and we'll sort out the mess during - ;; finalization. - (default-slot-from-property (class 'metaclass slot-names) - (pset :metaclass :id meta (find-sod-class meta))) + ;; Set the metaclass if the appropriate property has been provided or we're + ;; not bootstreapping; otherwise leave it unbound for now, and trust the + ;; caller to sort out the mess. + (multiple-value-bind (meta floc) (get-property pset :metaclass :id) + (cond (floc + (setf (slot-value class 'metaclass) + (with-default-error-location (floc) + (find-sod-class meta)))) + ((not (get-property pset :%bootstrapping :boolean)) + (default-slot (class 'metaclass slot-names) + (guess-metaclass class))))) ;; If no chain-link, then start a new chain here. (default-slot-from-property (class 'chain-link slot-names)