mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
Accessor methods only apply to subclasses with their slot
* libguile/goops.c (is_accessor_method, scm_compute_applicable_methods): Fix regression from51f66c9120
(2009). Accessor methods are added on each subclass on which the slot is present; therefore if a subclass doesn't have a method, then the methods doesn't apply. Truly fixes #17355, unlike583a23bf10
. * module/oop/goops.scm (compute-cmethod, compute-getter-method) (compute-setter-method): Revert earlier changes. * test-suite/tests/goops.test ("accessor slots"): Update for new expectations, in agreement with Guile 1.8.
This commit is contained in:
parent
583a23bf10
commit
649ec8d823
3 changed files with 35 additions and 36 deletions
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2014
|
/* Copyright (C) 1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011,2012,2014,2015
|
||||||
* Free Software Foundation, Inc.
|
* Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
|
@ -2053,6 +2053,11 @@ sort_applicable_methods (SCM method_list, long size, SCM const *targs)
|
||||||
return scm_vector_to_list (vector);
|
return scm_vector_to_list (vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
is_accessor_method (SCM method) {
|
||||||
|
return SCM_IS_A_P (method, scm_class_accessor_method);
|
||||||
|
}
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
|
scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
|
||||||
{
|
{
|
||||||
|
@ -2088,6 +2093,10 @@ scm_compute_applicable_methods (SCM gf, SCM args, long len, int find_method_p)
|
||||||
for (l = scm_generic_function_methods (gf); !scm_is_null (l); l = SCM_CDR (l))
|
for (l = scm_generic_function_methods (gf); !scm_is_null (l); l = SCM_CDR (l))
|
||||||
{
|
{
|
||||||
fl = SPEC_OF (SCM_CAR (l));
|
fl = SPEC_OF (SCM_CAR (l));
|
||||||
|
/* Only accept accessors which match exactly in first arg. */
|
||||||
|
if ((scm_is_null (fl) || types[0] != SCM_CAR (fl))
|
||||||
|
&& is_accessor_method (SCM_CAR (l)))
|
||||||
|
continue;
|
||||||
for (i = 0; ; i++, fl = SCM_CDR (fl))
|
for (i = 0; ; i++, fl = SCM_CDR (fl))
|
||||||
{
|
{
|
||||||
if (SCM_INSTANCEP (fl)
|
if (SCM_INSTANCEP (fl)
|
||||||
|
|
|
@ -107,35 +107,14 @@
|
||||||
(define (compute-cmethod methods types)
|
(define (compute-cmethod methods types)
|
||||||
(match methods
|
(match methods
|
||||||
((method . methods)
|
((method . methods)
|
||||||
(cond
|
(let ((make-procedure (slot-ref method 'make-procedure)))
|
||||||
((is-a? method <accessor-method>)
|
(if make-procedure
|
||||||
(match types
|
(make-procedure
|
||||||
((class . _)
|
(if (null? methods)
|
||||||
(let* ((name (car (accessor-method-slot-definition method)))
|
(lambda args
|
||||||
(g-n-s (assq name (slot-ref class 'getters-n-setters)))
|
(no-next-method (method-generic-function method) args))
|
||||||
(init-thunk (cadr g-n-s))
|
(compute-cmethod methods types)))
|
||||||
(g-n-s (cddr g-n-s)))
|
(method-procedure method))))))
|
||||||
(match types
|
|
||||||
((class)
|
|
||||||
(cond ((pair? g-n-s)
|
|
||||||
(make-generic-bound-check-getter (car g-n-s)))
|
|
||||||
(init-thunk
|
|
||||||
(standard-get g-n-s))
|
|
||||||
(else
|
|
||||||
(bound-check-get g-n-s))))
|
|
||||||
((class value)
|
|
||||||
(if (pair? g-n-s)
|
|
||||||
(cadr g-n-s)
|
|
||||||
(standard-set g-n-s))))))))
|
|
||||||
(else
|
|
||||||
(let ((make-procedure (slot-ref method 'make-procedure)))
|
|
||||||
(if make-procedure
|
|
||||||
(make-procedure
|
|
||||||
(if (null? methods)
|
|
||||||
(lambda args
|
|
||||||
(no-next-method (method-generic-function method) args))
|
|
||||||
(compute-cmethod methods types)))
|
|
||||||
(method-procedure method))))))))
|
|
||||||
|
|
||||||
|
|
||||||
(eval-when (expand load eval)
|
(eval-when (expand load eval)
|
||||||
|
@ -1138,17 +1117,26 @@
|
||||||
slots (slot-ref class 'getters-n-setters)))
|
slots (slot-ref class 'getters-n-setters)))
|
||||||
|
|
||||||
(define-method (compute-getter-method (class <class>) g-n-s)
|
(define-method (compute-getter-method (class <class>) g-n-s)
|
||||||
(let ((name (car g-n-s)))
|
(let ((init-thunk (cadr g-n-s))
|
||||||
|
(g-n-s (cddr g-n-s)))
|
||||||
(make <accessor-method>
|
(make <accessor-method>
|
||||||
#:specializers (list class)
|
#:specializers (list class)
|
||||||
#:procedure (lambda (o) (slot-ref o name))
|
#:procedure (cond ((pair? g-n-s)
|
||||||
|
(make-generic-bound-check-getter (car g-n-s)))
|
||||||
|
(init-thunk
|
||||||
|
(standard-get g-n-s))
|
||||||
|
(else
|
||||||
|
(bound-check-get g-n-s)))
|
||||||
#:slot-definition g-n-s)))
|
#:slot-definition g-n-s)))
|
||||||
|
|
||||||
(define-method (compute-setter-method (class <class>) g-n-s)
|
(define-method (compute-setter-method (class <class>) g-n-s)
|
||||||
(let ((name (car g-n-s)))
|
(let ((init-thunk (cadr g-n-s))
|
||||||
|
(g-n-s (cddr g-n-s)))
|
||||||
(make <accessor-method>
|
(make <accessor-method>
|
||||||
#:specializers (list class <top>)
|
#:specializers (list class <top>)
|
||||||
#:procedure (lambda (o v) (slot-set! o name v))
|
#:procedure (if (pair? g-n-s)
|
||||||
|
(cadr g-n-s)
|
||||||
|
(standard-set g-n-s))
|
||||||
#:slot-definition g-n-s)))
|
#:slot-definition g-n-s)))
|
||||||
|
|
||||||
(define (make-generic-bound-check-getter proc)
|
(define (make-generic-bound-check-getter proc)
|
||||||
|
|
|
@ -626,8 +626,10 @@
|
||||||
(pass-if-equal "a accessor on a" 'a (a-accessor a))
|
(pass-if-equal "a accessor on a" 'a (a-accessor a))
|
||||||
(pass-if-equal "a accessor on ab" 'a (a-accessor ab))
|
(pass-if-equal "a accessor on ab" 'a (a-accessor ab))
|
||||||
(pass-if-equal "a accessor on ba" 'a (a-accessor ba))
|
(pass-if-equal "a accessor on ba" 'a (a-accessor ba))
|
||||||
(pass-if-equal "a accessor on cab" 'a (a-accessor cab))
|
(pass-if-exception "a accessor on cab" exception:no-applicable-method
|
||||||
(pass-if-equal "a accessor on cba" 'a (a-accessor cba))
|
(a-accessor cab))
|
||||||
|
(pass-if-exception "a accessor on cba" exception:no-applicable-method
|
||||||
|
(a-accessor cba))
|
||||||
(pass-if-equal "b accessor on a" 'b (b-accessor b))
|
(pass-if-equal "b accessor on a" 'b (b-accessor b))
|
||||||
(pass-if-equal "b accessor on ab" 'b (b-accessor ab))
|
(pass-if-equal "b accessor on ab" 'b (b-accessor ab))
|
||||||
(pass-if-equal "b accessor on ba" 'b (b-accessor ba))
|
(pass-if-equal "b accessor on ba" 'b (b-accessor ba))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue