[armedbear-cvs] r12994 - trunk/abcl/src/org/armedbear/lisp

Alessio Stalla astalla at common-lisp.net
Tue Nov 2 23:48:39 UTC 2010


Author: astalla
Date: Tue Nov  2 19:48:36 2010
New Revision: 12994

Log:
New high-level Java interop macros: 'chain' for chained method invocations à la Clojure's '..' operator, and 'jmethod-let'.


Modified:
   trunk/abcl/src/org/armedbear/lisp/autoloads.lisp
   trunk/abcl/src/org/armedbear/lisp/java.lisp

Modified: trunk/abcl/src/org/armedbear/lisp/autoloads.lisp
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/autoloads.lisp	(original)
+++ trunk/abcl/src/org/armedbear/lisp/autoloads.lisp	Tue Nov  2 19:48:36 2010
@@ -282,6 +282,10 @@
 (autoload 'jruntime-class-exists-p "runtime-class")
 (export 'ensure-java-class "JAVA")
 (autoload 'ensure-java-class "java")
+(export 'chain "JAVA")
+(autoload-macro 'chain "java")
+(export 'jmethod-let "JAVA")
+(autoload-macro 'jmethod-let "java")
 
 ;; Profiler.
 (in-package "PROFILER")

Modified: trunk/abcl/src/org/armedbear/lisp/java.lisp
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/java.lisp	(original)
+++ trunk/abcl/src/org/armedbear/lisp/java.lisp	Tue Nov  2 19:48:36 2010
@@ -337,6 +337,45 @@
 (defun (setf jproperty-value) (value obj prop)
   (%jset-property-value obj prop value))
 
+;;; higher-level operators
+
+(defmacro chain (target op &rest ops)
+  "Performs chained method invocations. `target' is the receiver object (when the first call is a virtual method call) or a list in the form (:static <jclass>) when the first method call is a static method call. `op' and each of the `ops' are either method designators or lists in the form (<method designator> &rest args), where a method designator is either a string naming a method, or a jmethod object. `chain' will perform the method call specified by `op' on `target'; then, for each of the `ops', `chain' will perform the specified method call using the object returned by the previous method call as the receiver, and will ultimately return the result of the last method call.
+  For example, the form:
+
+  (chain (:static \"java.lang.Runtime\") \"getRuntime\" (\"exec\" \"ls\"))
+
+  is equivalent to the following Java code:
+
+  java.lang.Runtime.getRuntime().exec(\"ls\");"
+  (labels ((canonicalize-op (op) (if (listp op) op (list op)))
+	   (compose-arglist (target op) `(,(car op) ,target ,@(cdr op)))
+	   (make-binding-for (form) `(,(gensym) ,form))
+	   (make-binding (bindings next-op &aux (target (caar bindings)))
+	     (cons (make-binding-for
+		    `(jcall ,@(compose-arglist target
+					       (canonicalize-op next-op))))
+		   bindings)))
+    (let* ((first (if (and (consp target) (eq (first target) :static))
+		      `(jstatic ,@(compose-arglist (cadr target) (canonicalize-op op)))
+		      `(jcall ,@(compose-arglist target (canonicalize-op op)))))
+	   (bindings (nreverse
+		      (reduce #'make-binding ops
+			      :initial-value (list (make-binding-for first))))))
+      `(let* ,bindings
+	 (declare (ignore ,@(mapcar #'car bindings)))))))
+
+(defmacro jmethod-let (bindings &body body)
+  (let ((args (gensym)))
+    `(let ,(mapcar (lambda (binding)
+		     `(,(car binding) (jmethod ,@(cdr binding))))
+		   bindings)
+       (macrolet ,(mapcar (lambda (binding)
+			    `(,(car binding) (&rest ,args)
+			       `(jcall ,,(car binding) ,@,args)))
+			  bindings)
+	 , at body))))
+
 ;;; print-object
 
 (defmethod print-object ((obj java:java-object) stream)




More information about the armedbear-cvs mailing list