This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Parameterizing on incomplete types


On Dec 5, 2011, at 5:57 PM, Per Bothner wrote:

Looks good - or at least enough for now

Could you write some test-cases?  I'd like both some
tests where the base and derived class are in the same module,
and ones where they're compiled separately.

I'm working on this now. To test for the existence of a method with a particular signature I wrote this function:

(define (method-exists? (cls ::class)
                        (name ::String)
                        (ptypes ::class[])
                        (return-type ::class))
  ::boolean
  (define methods ::java.lang.reflect.Method[] (*:get-methods cls))
  (let loop ((i ::int 0))
    (and (< i methods:length)
         (let ((mtd (methods i)))
           (or (and (eq? mtd:declaring-class cls)
                    (eq? mtd:name name)
                    (eq? mtd:return-type return-type)
                    (equal? ptypes mtd:parameter-types))
               (loop (+ i 1)))))))


The "(eq? mtd:declaring-class cls)" filters out methods inherited
from a superclass, so for instance:

(method-exists? java.lang.Object "toString" (class[]) String) => #t

but

(method-exists? java.lang.Math "toString" (class[]) String) => #f

even though

(*:get-method java.lang.Math "toString")
=> public java.lang.String java.lang.Object.toString().

So, I can search for a bridge method and it won't give me a false
positive by finding an inherited method.


But, I've stumbled upon what appears to be a Kawa bug that's preventing me from evaluating an expression containing two class literals when both are defined in the REPL (or in the same test script). The following exchange is from a clean checkout of r7103.

/tmp/trunk $ rlwrap java -jar kawa-1.11.jar
#|kawa:1|# (define-simple-class A ())
#|kawa:2|# (list A)
(class A)
#|kawa:3|# (list A java.lang.String)
(class A class java.lang.String)
#|kawa:4|# (define-simple-class B ())
#|kawa:5|# (list B)
(class B)
#|kawa:6|# (list java.lang.Object B)
(class java.lang.Object class B)
#|kawa:7|# (list A B)
java.lang.NoSuchFieldError: A
	at atInteractiveLevel$7.run(stdin:7)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:279)
	at gnu.expr.ModuleExp.evalModule(ModuleExp.java:180)
	at kawa.Shell.run(Shell.java:280)
	at kawa.Shell.run(Shell.java:194)
	at kawa.Shell.run(Shell.java:175)
	at kawa.repl.main(repl.java:884)
#|kawa:8|# (define-simple-class C (A))
#|kawa:9|# (list A C)
java.lang.NoSuchFieldError: A
	at atInteractiveLevel$9.run(stdin:9)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:279)
	at gnu.expr.ModuleExp.evalModule(ModuleExp.java:180)
	at kawa.Shell.run(Shell.java:280)
	at kawa.Shell.run(Shell.java:194)
	at kawa.Shell.run(Shell.java:175)
	at kawa.repl.main(repl.java:884)
#|kawa:10|# (list C A)
java.lang.NoSuchFieldError: C
	at atInteractiveLevel$10.run(stdin:10)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:279)
	at gnu.expr.ModuleExp.evalModule(ModuleExp.java:180)
	at kawa.Shell.run(Shell.java:280)
	at kawa.Shell.run(Shell.java:194)
	at kawa.Shell.run(Shell.java:175)
	at kawa.repl.main(repl.java:884)
#|kawa:11|# (list java.lang.Object A B)
java.lang.NoSuchFieldError: A
	at atInteractiveLevel$11.run(stdin:11)
	at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:279)
	at gnu.expr.ModuleExp.evalModule(ModuleExp.java:180)
	at kawa.Shell.run(Shell.java:280)
	at kawa.Shell.run(Shell.java:194)
	at kawa.Shell.run(Shell.java:175)
	at kawa.repl.main(repl.java:884)



Whichever locally-defined class appears first falls victim to a NoSuchFieldError. So if I write a test like

(define-simple-class A ()  ((get) ::A #!null))
(define-simple-class B (A) ((get) ::B #!null))

(test-equal #t (method-exists? B "get" (class[]) A))

then the test fails with an error complaining about B instead of
letting method-exists? return #t or #f.

I've worked around it for my set of tests by currying method-exists?
so that I don't have two class literals appearing together:

(define (method-returning-A-exists? (cls ::class)
                                    (name ::String)
                                    (ptypes ::class[]))
  ::boolean
  (method-exists? cls name ptypes A))

but I'd rather not have to do that. Anyway, here's what I've got.

-Jamie

--
Jamison Hope
The PTR Group
www.theptrgroup.com


Attachment: bridge.scm
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]