Overview
This topic discusses the issues and possible solutions to the problems of initializing a
CLforJava instance. This system is large and complex, requiring a carefully designed startup protocol.
Issues
Loading Java Classes
Java is a dynamic language that does not require all of its classes to be resident when an application starts. Usually classes are loaded on their first reference in the executing code. Any static code that is defined in a class is also executed during the loading process. While the Java compiler is good at detecting circular dependencies among classes, the order and timing of class loading is non-deterministic. Classes can be manually loaded under program control by use of the Class.forName method.
The
RosettaPattern defines a pattern of Java code that simultaneously defines a Lisp type, a Java type, and a static field holding a Lisp symbol that names the Lisp type. It is often accompanied by an inner class defining a Factory for instances of that type. Some instances of this pattern contain additional static fields holding well-known values of that type. For example, the Package interface holds static fields holding references to the standard Common Lisp packages: COMMON-LISP, COMMON-LISP-USER, and SYSTEM. These fields give the Java programmer direct access to these packages from any code executing in
CLforJava.
These fields give rise to certain dependencies among the interfaces. For example, the Package interface must be loaded first so that all of the required symbols can be interned in their appropriate packages. Loading the Package interface forces the load of the
PackageImpl? class that implements packages. The order of the static fields is such that the packages are created before any symbols are created. Loading the Package interface constitutes the initial bootstrap action.
Once the
PackageSystem is loaded, the remainder of the Lisp
TypeSystem must be loaded. All Lisp objects must have both a Java and a Lisp type available before their creation. But at this point, the other types can be dynamically loaded. The Symbol type is already loaded at this point.
Initialization Sequence
CommonLisp depends on the correct configuration of symbols and functions for its operation. There are some 968 functions as well as myriad constants and special variables that may be called on immediately when the system is executing. Here is a description of the current
CLforJava initialization.
- Load the lisp.common.type.Package interface. This creates the basic CL PackageSystem and loads the Symbol interface.
- Load the lisp.common.type.SpecialOperator interface. This creates the symbols for the 26 special operators in Common Lisp.
- Load the lisp.common.type.Constants interface. This creates the global constants defined for Common Lisp. It includes the symbols and their values.
- Load the lisp.common.type.Variables interface. This createsates the SpecialVariables? defined for Common Lisp and their initial values.
- Load the lisp.extensions.type.CommonLispFunctions interface. This loads the implementing classes for the Common Lisp functions and creates singleton instances of those classes. Those instances are set as the symbol-function of the appropriate symbol.
The last item in the startup sequence deserves a little explanation. Originally the function symbols were defined in the lisp.common.type.Function interface. This was satisfactory until the Null Lisp function was imlemented. That meant there was a static member field of the interface called Null. Unfortunately there was already the Lisp NULL type was implemented as lisp.common.type.Null, and many functions used the Java name Null.NIL to reference the Lisp NIL symbol. All Lisp functions implement the Function interface. That lead to a name collision between Function.Null and Null. So I moved the function fields to an independent Java package in the lisp.extensions.type package. A todo item is to move both Constants and Variables to the lisp.extensions.type package.
At this point,
CLforJava is initialized.
Implementation
The initialization is encapsulated in a new extension class: lisp.extensions.CLforJava. The class has a no-arg constructor. On return from creating a new instance, the instance is a fully initialized instance of Common Lisp. It can now execute any Lisp or Java code that is loaded. As a convenience, the class has an interactive interface defined in the readEvalPrint method. This implements a standard Lisp Read-Eval-Print loop. It can also return a value by executing the EXIT function which takes an optional return value object.
Discussions
Links to Blog issues
Status:
Release Level:
Open bug count:
Test Suites
Links to JUnit results
--
JerryBoetje - 12 Jul 2003