X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/2f8a99a834db051434d30471e9cc26a41f6a5fa7..refs/heads/master:/src/class-make-impl.lisp diff --git a/src/class-make-impl.lisp b/src/class-make-impl.lisp index da6cd2c..b3347bd 100644 --- a/src/class-make-impl.lisp +++ b/src/class-make-impl.lisp @@ -84,7 +84,7 @@ ;;; Slots. (defmethod make-sod-slot - ((class sod-class) name type pset &optional location) + ((class sod-class) name type pset &key location) (with-default-error-location (location) (when (typep type 'c-function-type) (error "Slot declarations cannot have function type")) @@ -99,8 +99,8 @@ (with-slots (slots) class (setf slots (append slots (list slot)))) (when initarg-name - (make-sod-slot-initarg-using-slot class initarg-name - slot pset location)) + (make-sod-slot-initarg-using-slot class initarg-name slot pset + :location location)) slot))) (defmethod shared-initialize :after ((slot sod-slot) slot-names &key pset) @@ -115,7 +115,8 @@ ;;; Slot initializers. (defmethod make-sod-instance-initializer - ((class sod-class) nick name value pset &optional location) + ((class sod-class) nick name value pset + &key location inhibit-initargs (add-to-class t)) (with-default-error-location (location) (let* ((slot (find-instance-slot-by-name class nick name)) (initarg-name (get-property pset :initarg :id)) @@ -126,24 +127,25 @@ (with-slots (instance-initializers) class (unless (or initarg-name initializer) (error "Slot initializer declaration with no effect")) - (when initarg-name - (make-sod-slot-initarg-using-slot class initarg-name slot - pset location)) - (when initializer + (when (and initarg-name (not inhibit-initargs)) + (make-sod-slot-initarg-using-slot class initarg-name slot pset + :location location)) + (when (and initializer add-to-class) (setf instance-initializers (append instance-initializers (list initializer))))) initializer))) (defmethod make-sod-class-initializer - ((class sod-class) nick name value pset &optional location) + ((class sod-class) nick name value pset &key location (add-to-class t)) (with-default-error-location (location) (let* ((slot (find-class-slot-by-name class nick name)) (initializer (make-sod-initializer-using-slot class slot 'sod-class-initializer value pset (file-location location)))) - (with-slots (class-initializers) class - (setf class-initializers - (append class-initializers (list initializer)))) + (when add-to-class + (with-slots (class-initializers) class + (setf class-initializers + (append class-initializers (list initializer))))) initializer))) (defmethod make-sod-initializer-using-slot @@ -165,7 +167,7 @@ nil) (defmethod make-sod-user-initarg - ((class sod-class) name type pset &optional default location) + ((class sod-class) name type pset &key default location) (with-slots (initargs) class (push (make-instance (get-property pset :initarg-class :symbol 'sod-user-initarg) @@ -174,19 +176,24 @@ initargs))) (defmethod make-sod-slot-initarg - ((class sod-class) name nick slot-name pset &optional location) + ((class sod-class) name nick slot-name pset &key location) (let ((slot (find-instance-slot-by-name class nick slot-name))) - (make-sod-slot-initarg-using-slot class name slot pset location))) + (make-sod-slot-initarg-using-slot class name slot pset + :location location))) (defmethod make-sod-slot-initarg-using-slot - ((class sod-class) name (slot sod-slot) pset &optional location) + ((class sod-class) name (slot sod-slot) pset &key location) (with-slots (initargs) class (with-slots ((type %type)) slot - (push (make-instance (get-property pset :initarg-class :symbol - 'sod-slot-initarg) - :location (file-location location) - :class class :name name :type type :slot slot) - initargs)))) + (setf initargs + (append initargs + (cons (make-instance (get-property pset :initarg-class + :symbol + 'sod-slot-initarg) + :location (file-location location) + :class class :name name + :type type :slot slot) + nil)))))) (defmethod sod-initarg-default ((initarg sod-initarg)) nil) @@ -199,13 +206,13 @@ ;;; Initialization and teardown fragments. (defmethod make-sod-class-initfrag - ((class sod-class) frag pset &optional location) + ((class sod-class) frag pset &key location) (declare (ignore pset location)) (with-slots (initfrags) class (setf initfrags (append initfrags (list frag))))) (defmethod make-sod-class-tearfrag - ((class sod-class) frag pset &optional location) + ((class sod-class) frag pset &key location) (declare (ignore pset location)) (with-slots (tearfrags) class (setf tearfrags (append tearfrags (list frag))))) @@ -214,7 +221,7 @@ ;;; Messages. (defmethod make-sod-message - ((class sod-class) name type pset &optional location) + ((class sod-class) name type pset &key location) (with-default-error-location (location) (let* ((msg-class (or (get-property pset :message-class :symbol) (and (get-property pset :combination :keyword) @@ -232,9 +239,11 @@ (defmethod shared-initialize :after ((message sod-message) slot-names &key pset) - (declare (ignore slot-names pset)) (with-slots ((type %type)) message - (check-message-type message type))) + (check-message-type message type)) + (default-slot-from-property (message 'readonlyp slot-names) + (pset :readonly :boolean) + nil)) (defmethod check-message-type ((message sod-message) (type c-function-type)) nil) @@ -246,7 +255,7 @@ ;;; Methods. (defmethod make-sod-method - ((class sod-class) nick name type body pset &optional location) + ((class sod-class) nick name type body pset &key location) (with-default-error-location (location) (let* ((message (find-message-by-name class nick name)) (method (make-sod-method-using-message message class @@ -338,4 +347,65 @@ (check-method-return-type-against-message type msgtype) (check-method-argument-lists type msgtype))) +;;;-------------------------------------------------------------------------- +;;; Static instances. + +(defmethod shared-initialize :after + ((instance static-instance) slot-names &key pset) + "Initialize a static instance." + (default-slot-from-property (instance 'externp slot-names) + (pset :extern :boolean) + nil) + (default-slot-from-property (instance 'constp slot-names) + (pset :const :boolean) + t)) + +(defmethod make-static-instance ((class sod-class) name initializers + pset location &key) + + ;; Check that the initializers are all for distinct slots. + (find-duplicates (lambda (initializer previous) + (let ((slot (sod-initializer-slot initializer))) + (cerror*-with-location initializer + "Duplicate initializer for ~ + instance slot `~A' in ~ + static instance `~A'" + slot name) + (info-with-location previous + "Previous definition was here"))) + initializers + :key #'sod-initializer-slot) + + ;; Ensure that every slot will have an initializer, either defined directly + ;; on the instance or as part of some class definition. + (let ((have (make-hash-table))) + + ;; First, populate the hash table with all of the slots for which we have + ;; initializers. + (flet ((seen-slot-initializer (init) + (setf (gethash (sod-initializer-slot init) have) t))) + (mapc #'seen-slot-initializer + initializers) + (dolist (super (sod-class-precedence-list class)) + (mapc #'seen-slot-initializer + (sod-class-instance-initializers super)))) + + ;; Now go through all of the slots and check that they have initializers. + (dolist (super (sod-class-precedence-list class)) + (dolist (slot (sod-class-slots super)) + (unless (gethash slot have) + (cerror*-with-location location + "No initializer for instance slot `~A', ~ + required by static instance `~A'" + slot name) + (info-with-location slot "Slot `~A' defined here" slot))))) + + ;; Make the instance. + (make-instance 'static-instance + :class class + :name name + :initializers initializers + :location (file-location location) + :pset pset)) + ;;;----- That's all, folks --------------------------------------------------