diff options
author | Andy Wingo <wingo@pobox.com> | 2014-12-18 21:57:24 +0100 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2015-01-23 16:15:59 +0100 |
commit | 3a0d1412335b175a1a432e62f1e23740ef31a880 (patch) | |
tree | 02f437c53e0b883062901f0a99436b22a515a7c2 /module/oop | |
parent | e4aa440a2f6cb341ea187c63dc4fe310f4f148af (diff) | |
download | guile-3a0d1412335b175a1a432e62f1e23740ef31a880.tar.gz |
Rewrite %method-more-specific? to be in Scheme
* libguile/goops.h:
* libguile/goops.c (more_specificp, scm_sys_method_more_specific_p):
* module/oop/goops.scm (%method-more-specific?): Rewrite in Scheme. We
remove the scm_sys_method_more_specific_p interface as it is a private
interface and it's not extensible.
Diffstat (limited to 'module/oop')
-rw-r--r-- | module/oop/goops.scm | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/module/oop/goops.scm b/module/oop/goops.scm index a0c6119dc..ebc47eb30 100644 --- a/module/oop/goops.scm +++ b/module/oop/goops.scm @@ -508,6 +508,49 @@ ;;; {Methods} ;;; +;; Note: `a' and `b' can have unequal lengths (i.e. one can be one +;; element longer than the other when we have a dotted parameter +;; list). For instance, with the call +;; +;; (M 1) +;; +;; with +;; +;; (define-method M (a . l) ....) +;; (define-method M (a) ....) +;; +;; we consider that the second method is more specific. +;; +;; Precondition: `a' and `b' are methods and are applicable to `types'. +(define (%method-more-specific? a b types) + (let lp ((a-specializers (method-specializers a)) + (b-specializers (method-specializers b)) + (types types)) + (cond + ;; (a) less specific than (a b ...) or (a . b) + ((null? a-specializers) #t) + ;; (a b ...) or (a . b) less specific than (a) + ((null? b-specializers) #f) + ;; (a . b) less specific than (a b ...) + ((not (pair? a-specializers)) #f) + ;; (a b ...) more specific than (a . b) + ((not (pair? b-specializers)) #t) + (else + (let ((a-specializer (car a-specializers)) + (b-specializer (car b-specializers)) + (a-specializers (cdr a-specializers)) + (b-specializers (cdr b-specializers)) + (type (car types)) + (types (cdr types))) + (if (eq? a-specializer b-specializer) + (lp a-specializers b-specializers types) + (let lp ((cpl (class-precedence-list type))) + (let ((elt (car cpl))) + (cond + ((eq? a-specializer elt) #t) + ((eq? b-specializer elt) #f) + (else (lp (cdr cpl)))))))))))) + (define (%sort-applicable-methods methods types) (sort methods (lambda (a b) (%method-more-specific? a b types)))) |