X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/88e0b18b06860ef094d97b7ac1a023eab78a5240..284f1fa2ace3e276052ff1bd7d66442500e693da:/src/method-aggregate.lisp diff --git a/src/method-aggregate.lisp b/src/method-aggregate.lisp index 155ccb7..ec0a119 100644 --- a/src/method-aggregate.lisp +++ b/src/method-aggregate.lisp @@ -96,6 +96,12 @@ (:method (message combination type) t)) +(defgeneric aggregating-message-method-return-type (message combination) + (:documentation + "Return the primary method return type for this MESSAGE and COMBINATION.") + (:method ((message aggregating-message) (combination t)) + (c-type-subtype (sod-message-type message)))) + (export 'aggregating-effective-method) (defclass aggregating-effective-method (simple-effective-method) () (:documentation "Effective method counterpart to `aggregating-message'.")) @@ -173,6 +179,19 @@ arg-names plist))))))) +(defmethod check-method-type + ((method sod-method) (message aggregating-message) + (type c-function-type)) + (let ((wanted (aggregating-message-method-return-type + message (sod-message-combination message))) + (msgtype (sod-message-type message))) + (unless (c-type-equal-p (c-type-subtype type) wanted) + (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)))) + ;;;-------------------------------------------------------------------------- ;;; Utilities. @@ -360,7 +379,7 @@ :methods (lambda (invoke) (funcall invoke val) (emit-inst codegen (make-if-inst (format nil "~A > ~A" acc val) - (make-set-inst acc val) nil)))) + (make-set-inst acc val))))) (define-aggregating-method-combination :max ((acc val) :codegen codegen) :first-method (lambda (invoke) @@ -369,34 +388,28 @@ :methods (lambda (invoke) (funcall invoke val) (emit-inst codegen (make-if-inst (format nil "~A < ~A" acc val) - (make-set-inst acc val) nil)))) + (make-set-inst acc val))))) -(define-aggregating-method-combination :and ((ret val) :codegen codegen) - :return-type int +(define-aggregating-method-combination :and ((ret) :codegen codegen) :around (lambda (body) (codegen-push codegen) - (deliver-expr codegen ret 0) (funcall body) - (deliver-expr codegen ret 1) (emit-inst codegen (make-do-while-inst (codegen-pop-block codegen) 0))) :methods (lambda (invoke) - (funcall invoke val) - (emit-inst codegen (make-if-inst (format nil "!~A" val) - (make-break-inst) nil)))) + (funcall invoke ret) + (emit-inst codegen (make-if-inst (format nil "!~A" ret) + (make-break-inst))))) -(define-aggregating-method-combination :or ((ret val) :codegen codegen) - :return-type int +(define-aggregating-method-combination :or ((ret) :codegen codegen) :around (lambda (body) (codegen-push codegen) - (deliver-expr codegen ret 1) (funcall body) - (deliver-expr codegen ret 0) (emit-inst codegen (make-do-while-inst (codegen-pop-block codegen) 0))) :methods (lambda (invoke) - (funcall invoke val) - (emit-inst codegen (make-if-inst val (make-break-inst) nil)))) + (funcall invoke ret) + (emit-inst codegen (make-if-inst ret (make-break-inst))))) ;;;-------------------------------------------------------------------------- ;;; A customizable aggregating method combination. @@ -405,6 +418,7 @@ ((message aggregating-message) (combination (eql :custom))) '(:retvar :id :valvar :id + :methty :type :decls :fragment :before :fragment :first :fragment @@ -412,16 +426,22 @@ :after :fragment :count :id)) +(defmethod aggregating-message-method-return-type + ((message aggregating-message) (combination (eql :custom))) + (getf (sod-message-plist message) :methty + (c-type-subtype (sod-message-type message)))) + (defmethod compute-aggregating-message-kernel ((message aggregating-message) (combination (eql :custom)) codegen target methods arg-names - &key (retvar "sod_ret") (valvar "sod_val") + &key (retvar "sod_ret") (valvar "sod_val") (methty nil methtyp) decls before each (first each) after count) (let* ((type (c-type-subtype (sod-message-type message))) - (not-void-p (not (eq type c-type-void)))) - (when not-void-p - (ensure-var codegen retvar type) - (ensure-var codegen valvar type)) + (methty (if methtyp methty type))) + (unless (eq type c-type-void) + (ensure-var codegen retvar type)) + (unless (eq methty c-type-void) + (ensure-var codegen valvar methty)) (when count (ensure-var codegen count c-type-size-t (length methods))) (when decls @@ -429,7 +449,8 @@ (labels ((maybe-emit (fragment) (when fragment (emit-inst codegen fragment))) (invoke (method fragment) - (invoke-method codegen (if not-void-p valvar :void) + (invoke-method codegen + (if (eq methty c-type-void) :void valvar) arg-names method) (maybe-emit fragment))) (maybe-emit before)