chiark / gitweb /
src/method-aggregate.lisp: `and' and `or' combinations return decisive value.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 21 Oct 2015 23:46:28 +0000 (00:46 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 25 Nov 2015 10:55:56 +0000 (10:55 +0000)
Rather than canonifying to an integer result, effective methods with
`and' and `or' method combination now return the decisive value -- which
means that they can be used with any scalar return type (so the type
restriction has been removed).

Most significantly, the `or' combination is very useful with pointer
returns: it returns the result of the most specific direct method which
returns a non-null value.

src/method-aggregate.lisp

index 9446820b1e189e3a99c749fbd02470757ceb7097..c8791affff2125030214eb43e7822517bda07ace 100644 (file)
@@ -390,32 +390,26 @@ (define-aggregating-method-combination :max ((acc val) :codegen codegen)
             (emit-inst codegen (make-if-inst (format nil "~A < ~A" acc val)
                                              (make-set-inst acc val) nil))))
 
-(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)
+            (funcall invoke ret)
+            (emit-inst codegen (make-if-inst (format nil "!~A" ret)
                                              (make-break-inst) nil))))
 
-(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) nil))))
 
 ;;;--------------------------------------------------------------------------
 ;;; A customizable aggregating method combination.