Further fixes for JSS

JAVAPARSER now "stacks" its macro definition on the existing one it
inherits from JSS.

Refactor all tests to just pollute CL-USER where necessary (strictly
speaking it shouldn't be necessary as all PROVE tests should be able
to use lexical bindings.

Document existence of Java field access via SHARPSIGN-QUOTATION_MARK,


and the new Java DSL

    (asdf:make :javaparser)
    (#"'#1"new ByteBuddy()
      .intercept(FixedValue.value("Hello World!"))
parent 9ba092a1
......@@ -52,8 +52,8 @@ to call, and calls it.
An interactive restart is available to resolve class ambiguity.
Static calls are possible as well with the #" macro, but the
first argument MUST BE A SYMBOL to distinguish
Static calls are possible as well with the SHARPSIGN-QUOTATION_MARK
macro, but the first argument *must* be a symbol to distinguish
(#"getProperties" "java.lang.System")
......@@ -96,9 +96,31 @@ method is looked up based on the arguments passed, and thereafter
that method is called directly. Doesn't work for static methods at
the moment (lazy)
(japropos string) finds all class names matching string
(japropos string)
(jcmn class-name) lists the names of all methods for the class
finds all class names matching STRING.
(jcmn class-name)
lists the names of all methods for the CLASS-NAME.
Java static fields may be addressed via the SHARPSIGN-QUOTATION_MARK macro as
### Javaparser
On the reference of the JAVAPARSER system, one may use a Java DSL to
specify invocation and chains:
(asdf:make :javaparser)
(#"'#1"new ByteBuddy()
.intercept(FixedValue.value("Hello World!"))
......@@ -133,7 +155,7 @@ abcl-contrib: http://abcl.org/svn/trunk/abcl/contrib/
<> dc:created "2005" ;
dc:author "Mark <evenson.not.org@gmail.com>";
dc:revised "06-DEC-2012" ;
<> abcl:documents <urn:abcl.org/release/1.3.0-dev/contrib/jss#3.0.5" .
dc:revised "09-JUN-2017" ;
asdf:long-description <urn:abcl.org/release/1.5.0/contrib/jss/README.markdown#3.3.0>" .
......@@ -65,19 +65,13 @@
(eval-when (:compile-toplevel :load-toplevel :execute)
(defun read-invoke/javaparser (stream char arg)
(if (eql arg 1)
(if (ignore-errors (jclass "com.github.javaparser.ParseStart")) ;; chosen randomly, TODO memoize
(if (ignore-errors
(jclass "com.github.javaparser.ParseStart")) ;; chosen randomly, TODO memoize
(read-sharp-java-expression stream)
;; Deal with possiblity of not loading jar
(error "Cannot load javaparser code needed for the #1 macro"))
(unread-char char stream)
(let ((name (read stream)))
(if (or (find #\. name) (find #\{ name))
(jss-transform-to-field name)
(let ((object-var (gensym))
(args-var (gensym)))
`(lambda (,object-var &rest ,args-var)
(invoke-restargs ,name ,object-var ,args-var ,(eql arg 0)))))))))
(read-invoke stream char arg)))
(set-dispatch-macro-character #\# #\" 'read-invoke/javaparser))
......@@ -2,7 +2,7 @@
(defsystem jss
:author "Alan Ruttenberg, Mark Evenson"
:long-description "<urn:abcl.org/release/1.5.0/contrib/jss#>"
:version "3.2.4"
:version "3.3.0"
:components ((:module base :pathname "" :serial t
:components ((:file "packages")
(:file "invoke")
(in-package :cl-user)
#+(or) ;;
(in-package :jss)
(defparameter expanded '(let ((jss::this jss::*object-for-this*))
(jcall "getLoaded"
(jcall "load"
......@@ -32,7 +29,6 @@
(in-package :jss-test)
(prove:plan 1)
(proveis jss::source
(prove:is source expanded)
(in-package :cl-user)
(defpackage jss-test
(:use :cl :cl-user :jss :prove))
(prove:plan 6)
(in-package :jss-test)
(plan 6)
(is (read-from-string "#\"{bar}.{foo}\"") '(get-java-field bar foo t))
(is (read-from-string "#\"q.bar.{foo}\"") '(get-java-field (load-time-value (find-java-class "q.bar")) foo t))
(is (read-from-string "#\"{bar}.foo\"") '(get-java-field bar "foo" t))
(is-error (read-from-string "#\".bar.foo\"") 'simple-error)
(read-from-string "#\"{bar}.{foo}\"")
'(get-java-field bar foo t))
(read-from-string "#\"q.bar.{foo}\"")
'(get-java-field (load-time-value (find-java-class "q.bar")) foo t))
(read-from-string "#\"{bar}.foo\"")
'(get-java-field bar "foo" t))
(read-from-string "#\".bar.foo\"")
;;; http://abcl.org/trac/ticket/205
(is (with-constant-signature ((substring "substring")) (substring "01234" 2)) "234")
(with-constant-signature ((substring "substring"))
(substring "01234" 2)) "234")
;;; http://abcl.org/trac/ticket/229 - note: version of test for this ticket was broken in tests.lisp
(is (#"toString" (find "size"
(#"getMethods" (find-java-class "java.util.Collections$UnmodifiableMap"))
(prove:is (#"toString"
(find "size" (#"getMethods" (find-java-class "java.util.Collections$UnmodifiableMap"))
:test 'string-equal :key #"getName"))
(#"toString" (java::jmethod "java.util.Collections$UnmodifiableMap" "size" )))
;; test that optimized jss is much faster than unoptimized
(defun optimized-jss (count)
(let ()
(defun optimized-jss (count)
(loop repeat count do (#"compile" 'regex.Pattern ".*")))
(let ((jss::*inhibit-jss-optimization* t))
(let ((jss::*inhibit-jss-optimization* t))
(defun unoptimized-jss (count)
(loop repeat count do (#"compile" 'regex.Pattern ".*"))))
(defun just-loop (count)
(defun just-loop (count)
(loop repeat count))
(let ((jss::*inhibit-jss-optimization* nil))
(let ((jss::*inhibit-jss-optimization* nil))
(compile 'just-loop)
(compile 'optimized-jss))
(let ((jss::*inhibit-jss-optimization* t))
(let ((jss::*inhibit-jss-optimization* t))
(compile 'unoptimized-jss))
(defmacro timeit (&body body)
(defmacro timeit (&body body)
`(let ((start (#"currentTimeMillis" 'system)))
(- (#"currentTimeMillis" 'system) start)))
(plan 1)
(is-type (let ((just-loop (timeit (just-loop 10000))))
(prove:plan 1)
(prove:is-type (let ((just-loop (timeit (just-loop 10000))))
(+ 0.0
(/ (- (timeit (optimized-jss 10000)) just-loop)
(- (timeit (unoptimized-jss 10000)) just-loop))))
'(float 0 0.1))
'(float 0 0.1)
"Testing JSS compiler optimization…"))
(plan 2)
(prove:plan 2)
(let* ((jss::*inhibit-jss-optimization* nil)
(optimized-jss (macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t))))
(macroexpand (precompiler::precompile-form
'(#"compile" 'regex.Pattern ".*") t))))
(let* ((jss::*inhibit-jss-optimization* t)
(unoptimized-jss (macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t))))
(is (car optimized-jss) 'java:jstatic)
(is (caar unoptimized-jss) 'lambda)))
(macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t))))
(prove:is (car optimized-jss) 'java:jstatic)
(prove:is (caar unoptimized-jss) 'lambda)))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment