X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/284f1fa2ace3e276052ff1bd7d66442500e693da..c34b237da0bb4bf08a3531a2e11442623df7e9d4:/src/class-make-impl.lisp diff --git a/src/class-make-impl.lisp b/src/class-make-impl.lisp index dba6965..7263e44 100644 --- a/src/class-make-impl.lisp +++ b/src/class-make-impl.lisp @@ -72,9 +72,13 @@ :name name :type type :location (file-location location) - :pset pset))) + :pset pset)) + (initarg-name (get-property pset :initarg :id))) (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)) slot))) (defmethod shared-initialize :after ((slot sod-slot) slot-names &key pset) @@ -89,41 +93,43 @@ ;;; Slot initializers. (defmethod make-sod-instance-initializer - ((class sod-class) nick name value-kind value-form pset - &optional location) + ((class sod-class) nick name value pset &optional location) (with-default-error-location (location) (let* ((slot (find-instance-slot-by-name class nick name)) - (initializer (make-sod-initializer-using-slot - class slot 'sod-instance-initializer - value-kind value-form pset - (file-location location)))) + (initarg-name (get-property pset :initarg :id)) + (initializer (and value + (make-sod-initializer-using-slot + class slot 'sod-instance-initializer + value pset (file-location location))))) (with-slots (instance-initializers) class - (setf instance-initializers - (append instance-initializers (list initializer)))) + (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 + (setf instance-initializers + (append instance-initializers (list initializer))))) initializer))) (defmethod make-sod-class-initializer - ((class sod-class) nick name value-kind value-form pset - &optional location) + ((class sod-class) nick name value pset &optional location) (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-kind value-form pset - (file-location location)))) + value pset (file-location location)))) (with-slots (class-initializers) class (setf class-initializers (append class-initializers (list initializer)))) initializer))) (defmethod make-sod-initializer-using-slot - ((class sod-class) (slot sod-slot) - init-class value-kind value-form pset location) + ((class sod-class) (slot sod-slot) init-class value pset location) (make-instance (get-property pset :initializer-class :symbol init-class) :class class :slot slot - :value-kind value-kind - :value-form value-form + :value value :location (file-location location) :pset pset)) @@ -136,6 +142,51 @@ (declare (ignore slot-names pset)) nil) +(defmethod make-sod-user-initarg + ((class sod-class) name type pset &optional default location) + (declare (ignore pset)) + (with-slots (initargs) class + (push (make-instance 'sod-user-initarg :location (file-location location) + :class class :name name :type type :default default) + initargs))) + +(defmethod make-sod-slot-initarg + ((class sod-class) name nick slot-name pset &optional location) + (let ((slot (find-instance-slot-by-name class nick slot-name))) + (make-sod-slot-initarg-using-slot class name slot pset location))) + +(defmethod make-sod-slot-initarg-using-slot + ((class sod-class) name (slot sod-slot) pset &optional location) + (declare (ignore pset)) + (with-slots (initargs) class + (with-slots ((type %type)) slot + (push (make-instance 'sod-slot-initarg + :location (file-location location) + :class class :name name :type type :slot slot) + initargs)))) + +(defmethod sod-initarg-default ((initarg sod-initarg)) nil) + +(defmethod sod-initarg-argument ((initarg sod-initarg)) + (make-argument (sod-initarg-name initarg) + (sod-initarg-type initarg) + (sod-initarg-default initarg))) + +;;;-------------------------------------------------------------------------- +;;; Initialization and teardown fragments. + +(defmethod make-sod-class-initfrag + ((class sod-class) frag pset &optional 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) + (declare (ignore pset location)) + (with-slots (tearfrags) class + (setf tearfrags (append tearfrags (list frag))))) + ;;;-------------------------------------------------------------------------- ;;; Messages. @@ -221,15 +272,47 @@ ((method sod-method) (message sod-message) (type c-type)) (error "Methods must have function type, not ~A" type)) +(export 'check-method-return-type) +(defun check-method-return-type (method-type wanted-type) + "Signal an error unless METHOD-TYPE does not return the WANTED-TYPE." + (let ((method-returns (c-type-subtype method-type))) + (unless (c-type-equal-p method-returns wanted-type) + (error "Method return type ~A should be ~A" + method-returns wanted-type)))) + +(export 'check-method-return-type-against-message) +(defun check-method-return-type-against-message (method-type message-type) + "Signal an error unless METHOD-TYPE and MESSAGE-TYPE return the same type." + (let ((message-returns (c-type-subtype message-type)) + (method-returns (c-type-subtype method-type))) + (unless (c-type-equal-p message-returns method-returns) + (error "Method return type ~A doesn't match message ~A" + method-returns message-returns)))) + +(export 'check-method-argument-lists) +(defun check-method-argument-lists (method-type message-type) + "Signal an error unless METHOD-TYPE and MESSAGE-TYPE have matching argument + lists. + + This checks that (a) the two types have matching lists of mandatory + arguments, and (b) that either both or neither types accept keyword + arguments." + (let ((message-keywords-p (typep message-type 'c-keyword-function-type)) + (method-keywords-p (typep method-type 'c-keyword-function-type))) + (cond (message-keywords-p + (unless method-keywords-p + (error "Method must declare a keyword argument list"))) + (method-keywords-p + (error "Method must not declare a keyword argument list")))) + (unless (argument-lists-compatible-p (c-function-arguments message-type) + (c-function-arguments method-type)) + (error "Method arguments ~A don't match message ~A" + method-type message-type))) + (defmethod check-method-type ((method sod-method) (message sod-message) (type c-function-type)) (with-slots ((msgtype %type)) message - (unless (c-type-equal-p (c-type-subtype msgtype) - (c-type-subtype type)) - (error "Method return type ~A doesn't match message ~A" - (c-type-subtype msgtype) (c-type-subtype type))) - (unless (argument-lists-compatible-p (c-function-arguments msgtype) - (c-function-arguments type)) - (error "Method arguments ~A don't match message ~A" type msgtype)))) + (check-method-return-type-against-message type msgtype) + (check-method-argument-lists type msgtype))) ;;;----- That's all, folks --------------------------------------------------