[armedbear-cvs] r13566 - in trunk/abcl: src/org/armedbear/lisp test/lisp/abcl

ehuelsmann at common-lisp.net ehuelsmann at common-lisp.net
Sat Sep 3 22:57:11 UTC 2011


Author: ehuelsmann
Date: Sat Sep  3 15:57:09 2011
New Revision: 13566

Log:
More D-M-C tests and fixes.

Modified:
   trunk/abcl/src/org/armedbear/lisp/clos.lisp
   trunk/abcl/test/lisp/abcl/mop-tests.lisp

Modified: trunk/abcl/src/org/armedbear/lisp/clos.lisp
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/clos.lisp	Sat Sep  3 12:18:23 2011	(r13565)
+++ trunk/abcl/src/org/armedbear/lisp/clos.lisp	Sat Sep  3 15:57:09 2011	(r13566)
@@ -1941,6 +1941,22 @@
 (defun around-method-p (method)
   (equal '(:around) (method-qualifiers method)))
 
+(defun process-next-method-list (gf next-method-list)
+  (mapcar #'(lambda (next-method-form)
+              (cond
+                ((listp next-method-form)
+                 (assert (eq (first next-method-form) 'make-method))
+                 (let* ((rest-sym (gensym)))
+                   (make-instance-standard-method
+                    nil ;; ignored
+                    :lambda-list (list '&rest rest-sym)
+                    :function (compute-method-function `(lambda (&rest ,rest-sym)
+                                                          ,(second next-method-form))))))
+                (t
+                 (assert (typep next-method-form 'method))
+                 next-method-form)))
+          next-method-list))
+
 (defun std-compute-effective-method-function (gf methods)
   (let* ((mc (generic-function-method-combination gf))
          (mc-name (if (atom mc) mc (%car mc)))
@@ -1950,7 +1966,7 @@
          (arounds '())
          around
          emf-form
-         (long-method-combination-p 
+         (long-method-combination-p
           (typep (get mc-name 'method-combination-object) 'long-method-combination)))
     (unless long-method-combination-p
       (dolist (m methods)
@@ -2021,14 +2037,34 @@
               (arguments (rest (slot-value gf 'method-combination))))
          (assert (typep mc-obj 'long-method-combination))
          (assert function)
-         (setf emf-form 
+         (setf emf-form
                (let ((result (if arguments
                                  (apply function gf methods arguments)
                                  (funcall function gf methods))))
                  `(lambda (args)
                     (let ((gf-args-var args))
                       (macrolet ((call-method (method &optional next-method-list)
-                                   `(funcall ,(%method-function method) args nil)))
+                                   `(funcall
+                                     ,(cond
+                                       ((listp method)
+                                        (assert (eq (first method) 'make-method))
+                                        ;; by generating an inline expansion we prevent allocation
+                                        ;; of a method instance which will be discarded immediately
+                                        ;; after reading the METHOD-FUNCTION slot
+                                        (compute-method-function `(lambda (&rest ,(gensym))
+                                                   ;;### FIXME
+                                                   ;; the MAKE-METHOD body form gets evaluated in
+                                                   ;; the null lexical environment augmented
+                                                   ;; with a binding for CALL-METHOD
+                                                   ;; ... it's the latter we're not doing here...
+                                                                    ,(second method))))
+                                       (t (%method-function method)))
+                                     args
+                                     ,(unless (null next-method-list)
+                                        ;; by not generating an emf when there are no next methods,
+                                        ;; we ensure next-method-p returns NIL
+                                        (compute-effective-method-function ,gf
+                                           (process-next-method-list ,gf next-method-list))))))
                         ,result)))))))
       (t
        (let ((mc-obj (get mc-name 'method-combination-object)))

Modified: trunk/abcl/test/lisp/abcl/mop-tests.lisp
==============================================================================
--- trunk/abcl/test/lisp/abcl/mop-tests.lisp	Sat Sep  3 12:18:23 2011	(r13565)
+++ trunk/abcl/test/lisp/abcl/mop-tests.lisp	Sat Sep  3 15:57:09 2011	(r13566)
@@ -360,6 +360,58 @@
   1)
 
 
+;; Completely DIY -- also taken from SBCL:
+(define-method-combination dmc-test-mc.2 ()
+  ((all-methods *))
+  (do ((methods all-methods (rest methods))
+       (primary nil)
+       (around nil))
+      ((null methods)
+       (let ((primary (nreverse primary))
+             (around (nreverse around)))
+         (if primary
+              (let ((form (if (rest primary)
+                             `(call-method ,(first primary) ,(rest primary))
+                             `(call-method ,(first primary)))))
+                (if around
+                    `(call-method ,(first around) (,@(rest around)
+                                                   (make-method ,form)))
+                    form))
+              `(make-method (error "No primary methods")))))
+    (let* ((method (first methods))
+           (qualifier (first (method-qualifiers method))))
+      (cond
+        ((equal :around qualifier)
+         (push method around))
+        ((null qualifier)
+         (push method primary))))))
+
+(defgeneric dmc-test-mc.2a (val)
+  (:method-combination dmc-test-mc.2))
+
+(defmethod dmc-test-mc.2a ((val number))
+  (+ val (if (next-method-p) (call-next-method) 0)))
+
+(deftest dmc-test-mc.2a
+    (= (dmc-test-mc.2a 13) 13)
+  T)
+
+(defgeneric dmc-test-mc.2b (val)
+  (:method-combination dmc-test-mc.2))
+
+(defmethod dmc-test-mc.2b ((val number))
+  (+ val (if (next-method-p) (call-next-method) 0)))
+
+(defmethod dmc-test-mc.2b :around ((val number))
+  (+ val (if (next-method-p) (call-next-method) 0)))
+
+(deftest dmc-test-mc.2b
+    (= 26 (dmc-test-mc.2b 13))
+  T)
+
+
+
+
 (defclass foo-class (standard-class))
 (defmethod mop:validate-superclass ((class foo-class) (superclass standard-object))
   t)




More information about the armedbear-cvs mailing list