"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)))))