wiki:JavaScriptingAPI

Version 7 (modified by astalla, 13 years ago) (diff)

--

JSR-223 support in ABCL

ABCL is integrated with the Java Scripting API (JSR-223, package javax.script) which is built-in in Java 6.

This page describes the design decisions behind the ABCL JSR-223 support. It is not a description of what JSR-223 is or a tutorial on how to use it. See http://trac.common-lisp.net/armedbear/browser/trunk/abcl/examples/abcl/jsr-223 for example usage.

Implemented interfaces

JSR-223 defines three main interfaces, of which two (Invocable and Compilable) are optional. ABCL implements all the three interfaces - ScriptEngine and the two optional ones - almost completely. The JSR-223 API is not specific to a single scripting language, however was designed with languages with a more or less Java-like object model in mind: languages such as Javascript, Python, Ruby, which have a concept of "class" or "object" with "fields" and "methods". Lisp is a bit different, so certain adaptations were made, and in one case a method has been left unimplemented since it does not map at all to Lisp.

ScriptEngine

The main interface defined by JSR-223, javax.script.ScriptEngine, is implemented by the class org.armedbear.lisp.scripting.AbclScriptEngine. AbclScriptEngine is intended to be a singleton, even if it has a public constructor - which will probably be made protected in future versions of the engine. You can obtain an instance of AbclScriptEngine using the AbclScriptEngineFactory or by using the service provider mechanism through ScriptEngineManager (refer to the javax.script documentation).

Configuration file

At startup (i.e. when its constructor is invoked, as part of the static initialization phase of AbclScriptEngineFactory) the ABCL script engine attempts to load an "init file" from the classpath (/abcl-script-config.lisp). If present, this file can be used to customize the behaviour of the engine, by setting a number of variables in the ABCL-SCRIPT package. Here is a list of the available variables:

  • *use-throwing-debugger* Controls whether ABCL uses a non-standard debugging hook function to throw a Java exception instead of dropping into the debugger in case of unhandled error conditions.
    • Default value: T
    • Rationale: it is more convenient for Java programmers using Lisp as a scripting language to have it return exceptions to Java instead of handling them in the Lisp world.
    • Known Issues: the non-standard debugger hook has been reported to misbehave in certain circumstances, so consider disabling it if it doesn't work for you.
  • *launch-swank-at-startup* If true, Swank will be launched at startup. See *swank-dir* and *swank-port*.
    • Default value: NIL
  • *swank-dir* The directory where Swank is installed. Must be set if *launch-swank-at-startup* is true.
  • *swank-port* The port where Swank will listen for connections. Must be set if *launch-swank-at-startup* is true.
    • Default value: 4005
  • *compile-using-temp-files* Controls whether the script engine, through the Compilable interface, will use the Lisp file compiler or the runtime compiler. See Compilation below.
    • Default value: T

Evaluation

Code is read and evaluated in the package ABCL-SCRIPT-USER. This packages USEs the COMMON-LISP and ABCL-SCRIPT packages. Future versions of the script engine might make this default package configurable.

Compilation

AbclScriptEngine implements the javax.script.Compilable interface. It supports two modes of compilation: temp-file-based and runtime compilation. Which one is chosen depends on the value of the *compile-using-temp-files* variable. Be aware that the two modes are not equivalent - they correspond respectively to the "file compiler" and the "runtime compiler" specified in the ANSI Common Lisp specification; refer to it for details. The reason both modes are provided is that it is possible that ABCL will run in scenarios where it won't be able to write files, e.g. as an applet or a Java WebStart restricted application (currently ABCL cannot work in such scenarios, but in the future it might). However, since compilation based on temporary files is the Right Thing wrt the ANSI spec, it is the default. Compiled code, returned as a javax.script.CompiledScript, is read, compiled and executed in the ABCL-SCRIPT-USER package, like evaluated code.

Invocation of functions and methods

AbclScriptEngine implements the javax.script.Invocable interface. This interface allows to directly call functions and methods in the script, as well as to get implementations of Java interfaces from the script. This is only partially possible with Lisp since it has functions, but not methods - not in the traditional OO sense, at least, since Lisp methods are not attached to objects but belong to generic functions. Thus, the invokeMethod() is not implemented and throws an UnsupportedOperationException when called. The invokeFunction() method should be used to call both regular and generic functions.

TBD