Christophe Weblog Wiki Code Publications Music
added GENERALIZERS-OF-USING-CLASS
authorJan Moringen <jmoringe@techfak.uni-bielefeld.de>
Mon, 10 Feb 2014 01:22:49 +0000 (02:22 +0100)
committerChristophe Rhodes <csr21@cantab.net>
Thu, 22 May 2014 09:13:18 +0000 (10:13 +0100)
src/specializable.lisp

index 8d01319b1267e28a5da465263fbb8b4df27163c5..7b8bcb6195eb44cf66031e6ac0f1925928edb1ff 100644 (file)
            "SPECIALIZER-ACCEPTS-P" "SPECIALIZER-ACCEPTS-GENERALIZER-P"
            "SPECIALIZER<"
 
+           "GENERALIZERS-OF-USING-CLASS"
            "GENERALIZER-OF-USING-CLASS"
            "COMPUTE-APPLICABLE-METHODS-USING-GENERALIZERS"
            "GENERALIZER-EQUAL-HASH-KEY"
-           
+
            "DEFINE-EXTENDED-SPECIALIZER"))
 
 (in-package "SPECIALIZABLE")
 ;;; (defun intern-extended-specializer (gf sname)
 ;;;   (destructuring-bind (kind &rest args) sname
 ;;;     (setf (gethash sname (generic-function-extended-specializers gf))
-;;;      (apply (or (get kind 'extended-specializer-parser)
-;;;                 (error "not declared as an extended specializer name: ~A"
-;;;                        kind))
-;;;             gf
-;;;             args))))
+;;;       (apply (or (get kind 'extended-specializer-parser)
+;;;                  (error "not declared as an extended specializer name: ~A"
+;;;                         kind))
+;;;              gf
+;;;              args))))
 
 (defun make-extended-specializer (sname)
   (destructuring-bind (kind &rest args) sname
 
 ;;; from Closette, changed to use some SBCL functions:
 
-;;; FIXME: this is not actually sufficient argument checking
-(defun required-portion (gf args)
-  (let ((number-required
-        (sb-pcl::arg-info-number-required (sb-pcl::gf-arg-info gf))))
-    (when (< (length args) number-required)
-      (error "Too few arguments to generic function ~S." gf))
-    (subseq args 0 number-required)))
-
 (defgeneric generalizer-equal-hash-key (generic-function generalizer))
 (defmethod generalizer-equal-hash-key
     ((gf specializable-generic-function) (g class))
   (cond
     ((not (slot-value gf 'cacheingp))
      (lambda (&rest args)
-       (let ((generalizers (mapcar (lambda (x) (generalizer-of-using-class gf x))
-                                   args)))
+       (let ((generalizers (generalizers-of-using-class gf args)))
          (slow-method-lookup-and-call gf args generalizers))))
     ((first-arg-only-special-case gf)
      (lambda (&rest args)
-       (let* ((g (generalizer-of-using-class gf (car args)))
-              (k (generalizer-equal-hash-key gf g))
-              (emfun (gethash k (emf-table gf) nil)))
+       (let* ((generalizer (first (generalizers-of-using-class gf args))) ; TODO defeats purpose of special case
+              (key (generalizer-equal-hash-key gf generalizer))
+              (emfun (gethash key (emf-table gf) nil)))
          (if emfun
              (sb-pcl::invoke-emf emfun args)
              (slow-method-lookup-and-call
-              gf args (cons g (mapcar (lambda (x) (generalizer-of-using-class gf x))
-                                      (cdr (required-portion gf args)))))))))
+              gf args (list* generalizer
+                             (mapcar (lambda (x) (generalizer-of-using-class gf x))
+                                     (rest (required-portion gf args)))))))))
     (t
      (lambda (&rest args)
-       (let* ((generalizers (mapcar (lambda (x) (generalizer-of-using-class gf x))
-                                    (required-portion gf args)))
+       (let* ((generalizers (generalizers-of-using-class gf args))
               (keys (mapcar (lambda (x) (generalizer-equal-hash-key gf x)) generalizers))
               (emfun (gethash keys (emf-table gf) nil)))
          (if emfun
         (sb-pcl::make-effective-method-function gf em))))
 
 ;; new, not in closette
+  ;;; FIXME: this is not actually sufficient argument checking
+(defun required-portion (gf args)
+  (let ((number-required
+          (sb-pcl::arg-info-number-required (sb-pcl::gf-arg-info gf))))
+    (when (< (length args) number-required)
+      (error "Too few arguments to generic function ~S." gf))
+    (subseq args 0 number-required)))
+
+(defgeneric generalizers-of-using-class (generic-function args))
+
+(defmethod generalizers-of-using-class ((generic-function specializable-generic-function) args)
+  (mapcar (lambda (arg) (generalizer-of-using-class generic-function arg))
+          (required-portion generic-function args)))
+
 (defgeneric generalizer-of-using-class (generic-function object))
 (defmethod generalizer-of-using-class ((generic-function specializable-generic-function) object)
   (class-of object))
                              (sb-mop:method-specializers method)
                              arguments))
                   (sb-mop:generic-function-methods gf)))
-   (let ((generalizers (mapcar (lambda (x) (generalizer-of-using-class gf x))
-                               (required-portion gf arguments))))
+   (let ((generalizers (generalizers-of-using-class gf arguments)))
      (lambda (m1 m2)
        (method-more-specific-p gf m1 m2 generalizers)))))