Jaja: Scheme in Java

BEWARE: the Jaja project is no longer active. The applet below is no longer runnable on Explorer because of the non support of RMI. I do not plan to update Jaja now since a new project is born named: PS3I.

History of Jaja

This page describes an implementation of Scheme in Java. This experiment first starts (during summer 1996) as a small runtime (written in Java, of course) needed by a compiler from Scheme to Java. This experiment was also my first contact with Java. The compiler was obtained by retargeting another compiler (written in Scheme) from Scheme to C. This compiler is fully described in the LiSP book). This runtime was around 1000 lines and includes nearly all really primitive functions of the R4RS: for instance, car is present but cadr is not since cadr may be implemented with help of car and cdr.

To implement an interpreter is then simple: just compile an interpreter written in Scheme (and add support for the global environment that is, a way to convert symbols to locations of the global variables they represent). I chose instead to implement a naive interpreter directly in Java, since this is more readable than compiled code and is far easier to explain. Unfortunately, this doubles the size of the runtime support library, making it over 3000 lines of Java.

The Jaja interpreter, the compiler and, soon, the bootstrap process (ie compiling the compiler and additional libraries) are used since fall 1996 in several lectures given at University Paris 6 and École Polytechnique. These lectures are centered on embedded languages, how to interpret them, how to compile them, how to make them use the resources of the implementation language.

In Jaja, I used different OO styles in many places to show various ways to implement some features (even inner classes): this is intentional! I also had a bunch of exercises that deal with Jaja and these finer points. These exercises propose variations around Jaja, alternate implementations, additional features, etc.

NEW: This project will not be continued. A new project called PS3I replaces Jaja. Stay tuned!

Portability

The first version of Jaja was written in Java 1.0.2. The current version uses Java 1.1.7.

Jaja may be used as a stand-alone program or as an applet. It seems to work on PC box with:

You may run concurrently two instances of the Jaja applet in the same page and interact with two logically separate Scheme interpreters sharing the same immutable predefined library but not the same global mutable environment.

Here is Jaja downloaded from a jar file:

Sorry, your browser is not Java-powered! But here is a view of what you missed:

The runtime library has been weakly tested not to talk of the interpreter. However the compiler had been heavily tested. The Java source files of Jaja and its (javadoc'ed) documentation are available under the Gnu General Public License, version 2. Do you like it zipped (with sources and documentation) or jarred (with compiled classes only) ? The entire Jaja system with the compiler and tons of unrelated things may be found via online. For any of them, send bugs or remarks to Christian.Queinnec@lip6.fr .

Invoking Jaja

Jaja may be invoked as a regular Scheme interpreter from a shell with:
      	java Jaja.Textual

or as a window-based interpreter, again from a shell (be sure to be in a directory containing the Jaja subdirectory), with:

	java Jaja.FromOS

or as an applet from an html page as shown above in this very page.

You may exit from Jaja by simulating an end of file in textual mode (usually CTRL-D) or by calling the exit unary function. Visit another page to stop an applet!

There is a variety of ways to load this interpreter (as an applet or a textual application, from a jar file, a zip file, a directory of individual class files, with hidden options, etc.) make difficult to test them all. Here are some hints to check if Jaja do not work.

The predefined library

The predefined library contains around 50 primitives so many non essential functions of R4RS are missing. Functions are currently limited to ten arguments. However, dynamic binding is implemented to encode current input/output ports. Dynamic binding may also be used directly for other purposes.

Additional functions such as (help), (oblist) and (exit n) are available. The eval and load functions (you may even give an url to load remote Scheme files) are also supported.

A recent addition is (detach fun args...) which detaches a thread that applies fun on args... and throws away the resulting value.

The interpreter may be used remotely (with RMI). Different listeners may address the same Scheme interpreter.

The interpreted language

The standard Scheme functions that may be defined in Scheme and do not require to be written natively in Java, appear in the boot1.scm file. Just load it to take benefit of map, equal?, etc. Just say:
 
(load "boot1.scm") 

The interpreter does not support macro: no define (use set! instead), no letrec ... But it does support a tower of macroexpansion interpreters with the eval-in-expansion-world toplevel macro which allows you to define your own macroexpansion mechanism!

To use the derived syntaxes of Scheme (named let, define, and etc.), you may use the bootm1.scm file. This file defines a macroexpansion engine (an expand function) that converts standard Scheme into the pure Scheme kernel understood by Jaja. You must load it at the macro-level ie, just say:

(eval-in-expansion-world 
  (begin (load "boot1.scm") 
         (load "bootm1.scm") ) ) 

These two files are packed in the jar/zip distributed files from which they may be loaded. Human, go away! These files are computer-generated to be computer-readable. These files use a uninitialized-let special form that introduces local bindings that are initially uninitialized: they raise an error if read before being initialized. This special form allows to define letrec as a regular macro in Scheme.

The compiled language

The compiler supports traditional Lisp-like macros and thus supports define, letrec ...

Soon the compiler will be available as a single, loadable file.

Miscellaneous

This interpreter is named Jaja, as suggested by Emmanuel Chailloux. Jaja is affectionate slang for "wine" in French.

Other Scheme implementations in Java exist:


Updated by Christian.Queinnec@lip6.fr
$Id: Jaja.html,v 1.46 2000/09/21 18:08:33 queinnec Exp $