chiark / gitweb /
src/class-make-{proto,impl}.lisp: Don't always add initializers to classes.
[sod] / src / class-make-proto.lisp
index d075304787914bd94055251078a470cb34c61013..09b9f98e6fae7ad4e3d13f02b673d04bc3a42a4d 100644 (file)
@@ -28,8 +28,16 @@ (cl:in-package #:sod)
 ;;;--------------------------------------------------------------------------
 ;;; Classes.
 
+(export 'guess-metaclass)
+(defgeneric guess-metaclass (class)
+  (:documentation
+   "Determine a suitable metaclass for the CLASS.
+
+   The default behaviour is to choose the most specific metaclass of any of
+   the direct superclasses of CLASS, or to signal an error if that failed."))
+
 (export 'make-sod-class)
-(defun make-sod-class (name superclasses pset &optional location)
+(defun make-sod-class (name superclasses pset &key location)
   "Construct and return a new SOD class with the given NAME and SUPERCLASSES.
 
    This is the main constructor function for classes.  The protocol works as
@@ -46,12 +54,13 @@ (defun make-sod-class (name superclasses pset &optional location)
   (with-default-error-location (location)
     (let* ((pset (property-set pset))
           (best-class (or (get-property pset :lisp-metaclass :symbol nil)
-                          (if superclasses
-                              (maximum (mapcar #'class-of superclasses)
-                                       #'subtypep
-                                       (format nil "Lisp metaclass for ~A"
-                                               name))
-                              'sod-class)))
+                          (select-minimal-class-property
+                           superclasses #'class-of #'subtypep 'sod-class
+                           "Lisp metaclass"
+                           :present (lambda (class)
+                                      (format nil "`~S'"
+                                              (class-name class)))
+                           :allow-empty t)))
           (class (make-instance best-class
                                 :name name
                                 :superclasses superclasses
@@ -63,7 +72,7 @@ (defun make-sod-class (name superclasses pset &optional location)
 ;;; Slots and slot initializers.
 
 (export 'make-sod-slot)
-(defgeneric make-sod-slot (class name type pset &optional location)
+(defgeneric make-sod-slot (class name type pset &key location)
   (:documentation
    "Construct, add, and attach a new slot with given NAME and TYPE, to CLASS.
 
@@ -77,7 +86,7 @@ (defgeneric make-sod-slot (class name type pset &optional location)
 
 (export 'make-sod-instance-initializer)
 (defgeneric make-sod-instance-initializer
-    (class nick name value pset &optional location)
+    (class nick name value pset &key location inhibit-initargs add-to-class)
   (:documentation
    "Construct and attach an instance slot initializer, to CLASS.
 
@@ -86,11 +95,17 @@ (defgeneric make-sod-instance-initializer
    construction process.  The default method looks up the slot using
    `find-instance-slot-by-name', calls `make-sod-initializer-using-slot' to
    actually make the initializer object, and adds it to the appropriate list
-   in CLASS."))
+   in CLASS unless ADD-TO-CLASS is nil.
+
+   Usually, if an `initarg' property is set on PSET, then a slot initarg is
+   created and attached to the slot; this can be prevented by setting
+   INHIBIT-INITARGS non-nil.  This is needed when creating a slot and
+   initializer from the same property set, in order to prevent creation of a
+   duplicate initarg."))
 
 (export 'make-sod-class-initializer)
 (defgeneric make-sod-class-initializer
-    (class nick name value pset &optional location)
+    (class nick name value pset &key location add-to-class)
   (:documentation
    "Construct and attach a class slot initializer, to CLASS.
 
@@ -99,7 +114,7 @@ (defgeneric make-sod-class-initializer
    construction process.  The default method looks up the slot using
    `find-class-slot-by-name', calls `make-sod-initializer-using-slot' to
    actually make the initializer object, and adds it to the appropriate list
-   in CLASS."))
+   in CLASS unless ADD-TO-CLASS is nil."))
 
 (export 'make-sod-initializer-using-slot)
 (defgeneric make-sod-initializer-using-slot
@@ -126,7 +141,7 @@ (defgeneric make-sod-initializer-using-slot
 
 (export 'make-sod-user-initarg)
 (defgeneric make-sod-user-initarg
-    (class name type pset &optional default location)
+    (class name type pset &key default location)
   (:documentation
    "Attach a user-defined initialization keyword argument to the CLASS.
 
@@ -136,7 +151,7 @@ (defgeneric make-sod-user-initarg
 
 (export 'make-sod-slot-initarg)
 (defgeneric make-sod-slot-initarg
-    (class name nick slot-name pset &optional location)
+    (class name nick slot-name pset &key location)
   (:documentation
    "Attach an initialization keyword argument to a slot by name.
 
@@ -145,7 +160,7 @@ (defgeneric make-sod-slot-initarg
 
 (export 'make-sod-slot-initarg-using-slot)
 (defgeneric make-sod-slot-initarg-using-slot
-    (class name slot pset &optional location)
+    (class name slot pset &key location)
   (:documentation
    "Attach an initialization keyword argument to a SLOT.
 
@@ -160,7 +175,7 @@ (defgeneric sod-initarg-argument (initarg)
   (:documentation "Returns an `argument' object for the initarg."))
 
 (export 'make-sod-class-initfrag)
-(defgeneric make-sod-class-initfrag (class frag pset &optional location)
+(defgeneric make-sod-class-initfrag (class frag pset &key location)
   (:documentation
    "Attach an initialization fragment FRAG to the CLASS.
 
@@ -168,7 +183,7 @@ (defgeneric make-sod-class-initfrag (class frag pset &optional location)
    list."))
 
 (export 'make-sod-class-tearfrag)
-(defgeneric make-sod-class-tearfrag (class frag pset &optional location)
+(defgeneric make-sod-class-tearfrag (class frag pset &key location)
   (:documentation
    "Attach a teardown fragment FRAG to the CLASS.
 
@@ -179,7 +194,7 @@ (defgeneric make-sod-class-tearfrag (class frag pset &optional location)
 ;;; Messages and methods.
 
 (export 'make-sod-message)
-(defgeneric make-sod-message (class name type pset &optional location)
+(defgeneric make-sod-message (class name type pset &key location)
   (:documentation
    "Construct and attach a new message with given NAME and TYPE, to CLASS.
 
@@ -195,7 +210,7 @@ (defgeneric make-sod-message (class name type pset &optional location)
 
 (export 'make-sod-method)
 (defgeneric make-sod-method
-    (class nick name type body pset &optional location)
+    (class nick name type body pset &key location)
   (:documentation
    "Construct and attach a new method to CLASS.