chiark / gitweb /
src/module-parse.lisp (parse-class-body): Refactor superclass list.
[sod] / src / class-make-impl.lisp
index 7495c0182e631b4b02eb49fb0a9ab8995c2e1101..5a897d409a05e2ca3b8765b138bed95e7db440c9 100644 (file)
@@ -28,32 +28,52 @@ (cl:in-package #:sod)
 ;;;--------------------------------------------------------------------------
 ;;; Classes.
 
 ;;;--------------------------------------------------------------------------
 ;;; 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:
 
 (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
 
      * `: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)))
 
 
   ;; 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)
 
   ;; If no chain-link, then start a new chain here.
   (default-slot-from-property (class 'chain-link slot-names)