Changeset 12994


Ignore:
Timestamp:
11/02/10 23:48:36 (11 years ago)
Author:
astalla
Message:

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

Location:
trunk/abcl/src/org/armedbear/lisp
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/abcl/src/org/armedbear/lisp/autoloads.lisp

    r12992 r12994  
    283283(export 'ensure-java-class "JAVA")
    284284(autoload 'ensure-java-class "java")
     285(export 'chain "JAVA")
     286(autoload-macro 'chain "java")
     287(export 'jmethod-let "JAVA")
     288(autoload-macro 'jmethod-let "java")
    285289
    286290;; Profiler.
  • trunk/abcl/src/org/armedbear/lisp/java.lisp

    r12831 r12994  
    338338  (%jset-property-value obj prop value))
    339339
     340;;; higher-level operators
     341
     342(defmacro chain (target op &rest ops)
     343  "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.
     344  For example, the form:
     345
     346  (chain (:static \"java.lang.Runtime\") \"getRuntime\" (\"exec\" \"ls\"))
     347
     348  is equivalent to the following Java code:
     349
     350  java.lang.Runtime.getRuntime().exec(\"ls\");"
     351  (labels ((canonicalize-op (op) (if (listp op) op (list op)))
     352     (compose-arglist (target op) `(,(car op) ,target ,@(cdr op)))
     353     (make-binding-for (form) `(,(gensym) ,form))
     354     (make-binding (bindings next-op &aux (target (caar bindings)))
     355       (cons (make-binding-for
     356        `(jcall ,@(compose-arglist target
     357                 (canonicalize-op next-op))))
     358       bindings)))
     359    (let* ((first (if (and (consp target) (eq (first target) :static))
     360          `(jstatic ,@(compose-arglist (cadr target) (canonicalize-op op)))
     361          `(jcall ,@(compose-arglist target (canonicalize-op op)))))
     362     (bindings (nreverse
     363          (reduce #'make-binding ops
     364            :initial-value (list (make-binding-for first))))))
     365      `(let* ,bindings
     366   (declare (ignore ,@(mapcar #'car bindings)))))))
     367
     368(defmacro jmethod-let (bindings &body body)
     369  (let ((args (gensym)))
     370    `(let ,(mapcar (lambda (binding)
     371         `(,(car binding) (jmethod ,@(cdr binding))))
     372       bindings)
     373       (macrolet ,(mapcar (lambda (binding)
     374          `(,(car binding) (&rest ,args)
     375             `(jcall ,,(car binding) ,@,args)))
     376        bindings)
     377   ,@body))))
     378
    340379;;; print-object
    341380
Note: See TracChangeset for help on using the changeset viewer.