(defpackage #:jj
(:use #:common-lisp #:java)
(:export #:java-name #:lisp-name
- #:java-true #:java-false #:java-null
+ #:java-true #:java-false #:java-null #:jboolean
#:send #:send-class #:make #:make-java-array #:java-array
#:field #:class-field
#:magic-constant-case
(defconstant java-null (make-immediate-object nil :ref)
"A Java null reference.")
+(defun jboolean (thing)
+ "Return JAVA-TRUE if THING is non-nil, JAVA-FALSE if THING is nil."
+ (if thing java-true java-false))
+
(defmacro define-java-method (lisp-name class method &body args)
"Define a Lisp function LISP-NAME to call the named METHOD of CLASS on the
given arguments. The CLASS may be a string or symbol (it is converted by
(list (java-class-name java-class)
(cons :constructors
(expand-java-method (ensure-java-constructor java-class)))
- (loop for name being the hash-keys
- of (ensure-java-method-table java-class)
- using (hash-value method)
- collect (cons name (expand-java-method method)))))
+ (sort (loop for name being the hash-keys
+ of (ensure-java-method-table java-class)
+ using (hash-value method)
+ collect (cons name (expand-java-method method)))
+ (lambda (x y) (string< (car x) (car y))))))
(defparameter *conversions*
(let ((raw '((java.lang.*object boolean)
(defun jclass-convertible-p (from to)
"Return whether there is an automatic conversion between FROM and TO. This
can be considered a partial order on types."
- (or (jclass-superclass-p to from)
+ (or (null from)
+ (jclass-superclass-p to from)
(member from (assoc to *conversions* :test #'equal)
:test #'equal)))
(t (and (jclass-convertible-p (car first) (car second))
(argument-list-betterp (cdr first) (cdr second))))))
-(defun get-jmethod-for-argument-types (java-method argument-types)
+(defun get-jmethod-for-argument-types (java-class java-method argument-types)
"Given a JAVA-METHOD structure, return the best match overload for the
given list of ARGUMENT-TYPES.
(format t "*** chosen = ~S~%"
(expand-methodlist chosen)))
(cond ((null chosen)
- (error "No match found.~% method = ~A, args = ~A"
+ (error "No match found.~% ~
+ class = ~A, method = ~A~% ~
+ args = ~A"
+ (java-class-name java-class)
(java-method-name java-method)
(expand-arglist argument-types)))
((cdr chosen)
(defun find-jmethod (class name arg-types)
"Given a CLASS, a method NAME, and a list of ARG-TYPES, return the Java
method object for the best matching overload of the method."
- (get-jmethod-for-argument-types (find-java-method class name)
- (argument-type-list-from-names arg-types)))
+ (let ((java-class (find-java-class class)))
+ (get-jmethod-for-argument-types
+ java-class
+ (find-java-method java-class name)
+ (argument-type-list-from-names arg-types))))
(defun find-jconstructor (class arg-types)
"Given a CLASS and a list of ARG-TYPES, return the Java constructor object
for the best matching constructor overload."
- (get-jmethod-for-argument-types (find-java-constructor class)
- (argument-type-list-from-names arg-types)))
+ (let ((java-class (find-java-class class)))
+ (get-jmethod-for-argument-types
+ java-class
+ (find-java-constructor java-class)
+ (argument-type-list-from-names arg-types))))
(defun send (object message &rest arguments)
"Given an OBJECT, a MESSAGE name (Lisp symbol or Java name string) and
(let ((jargs (mapcar #'make-immediate-object arguments)))
(apply #'jcall
(find-jmethod (jobject-class object) message
- (mapcar (lambda (jarg) (jobject-class jarg)) jargs))
+ (mapcar (lambda (jarg)
+ (if (equal jarg java-null)
+ nil
+ (jobject-class jarg)))
+ jargs))
object
jargs)))