Skip to content

Commit

Permalink
Further fixes for JSS
Browse files Browse the repository at this point in the history
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,
e.g.

    (#"{java.lang.System}.{fileSeparator}")

and the new Java DSL

    (asdf:make :javaparser)
    (#"'#1"new ByteBuddy()
      .subclass(Object.class,t)
      .method(ElementMatchers.named("toString"))
      .intercept(FixedValue.value("Hello World!"))
      .make()
      .load(getClass().getClassLoader())
      .getLoaded()"
  • Loading branch information
mevenson@1c010e3e-69d0-11dd-93a8-456734b0d56f committed Jun 9, 2017
1 parent 64203af commit 80f8222
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 65 deletions.
34 changes: 28 additions & 6 deletions contrib/jss/README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -96,10 +96,32 @@ 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

(#"{java.lang.System}.{fileSeparator}")

### 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()
.subclass(Object.class,t)
.method(ElementMatchers.named("toString"))
.intercept(FixedValue.value("Hello World!"))
.make()
.load(getClass().getClassLoader())
.getLoaded()"

Compatibility
-------------

Expand Down Expand Up @@ -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>" .


14 changes: 4 additions & 10 deletions contrib/jss/javaparser.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
(progn
(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 changes: 1 addition & 1 deletion contrib/jss/jss.asd
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
6 changes: 1 addition & 5 deletions contrib/jss/t/javaparser.lisp
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
(in-package :cl-user)

#+(or) ;;
(in-package :jss)

(defparameter expanded '(let ((jss::this jss::*object-for-this*))
(jcall "getLoaded"
(jcall "load"
Expand Down Expand Up @@ -32,7 +29,6 @@
(in-package :jss-test)

(prove:plan 1)
(proveis jss::source
jss::expanded)
(prove:is source expanded)

(prove:finalize)
92 changes: 49 additions & 43 deletions contrib/jss/t/jss-tests.lisp
Original file line number Diff line number Diff line change
@@ -1,61 +1,67 @@
(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)
(prove:is
(read-from-string "#\"{bar}.{foo}\"")
'(get-java-field bar foo t))
(prove:is
(read-from-string "#\"q.bar.{foo}\"")
'(get-java-field (load-time-value (find-java-class "q.bar")) foo t))
(prove:is
(read-from-string "#\"{bar}.foo\"")
'(get-java-field bar "foo" t))
(prove:is-error
(read-from-string "#\".bar.foo\"")
'simple-error)
;;; http://abcl.org/trac/ticket/205
(is (with-constant-signature ((substring "substring")) (substring "01234" 2)) "234")
(prove:is
(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"))
:test 'string-equal :key #"getName"))
(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)
(loop repeat count do (#"compile" 'regex.Pattern ".*")))

(let ((jss::*inhibit-jss-optimization* t))
(defun unoptimized-jss (count)
(loop repeat count do (#"compile" 'regex.Pattern ".*"))))

(defun just-loop (count)
(loop repeat count))

(let ((jss::*inhibit-jss-optimization* nil))
(compile 'just-loop)
(compile 'optimized-jss))
(let ((jss::*inhibit-jss-optimization* t))
(compile 'unoptimized-jss))

(defmacro timeit (&body body)
`(let ((start (#"currentTimeMillis" 'system)))
,@body
(- (#"currentTimeMillis" 'system) start)))
(let ()
(defun optimized-jss (count)
(loop repeat count do (#"compile" 'regex.Pattern ".*")))
(let ((jss::*inhibit-jss-optimization* t))
(defun unoptimized-jss (count)
(loop repeat count do (#"compile" 'regex.Pattern ".*"))))
(defun just-loop (count)
(loop repeat count))
(let ((jss::*inhibit-jss-optimization* nil))
(compile 'just-loop)
(compile 'optimized-jss))
(let ((jss::*inhibit-jss-optimization* t))
(compile 'unoptimized-jss))

(defmacro timeit (&body body)
`(let ((start (#"currentTimeMillis" 'system)))
,@body
(- (#"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))))
(optimized-jss
(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)))
(unoptimized-jss
(macroexpand (precompiler::precompile-form '(#"compile" 'regex.Pattern ".*") t))))
(prove:is (car optimized-jss) 'java:jstatic)
(prove:is (caar unoptimized-jss) 'lambda)))

(finalize)
(prove:finalize)

0 comments on commit 80f8222

Please sign in to comment.