HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML

Scriptic is an experimental extension to the Java language. Why is this new language on top on another brand new one? What problems does it solve?

Java is a big step forward in programming, but like many other languages, it falls short in two areas: user interaction and parallelism. This is because it mainly supports the traditional paradigm of sequential actions controlled by deterministic constructs. Scriptic tries to improve on Java by adding explicit support for parallelism and non-deterministic choice.

Example: The Game of Life
Take the game of Life as an example. This is about a board with patterns that evolve according to a certain algorithm. The user can edit the board contents using the mouse, and have patterns evolve in time. We made a simple Life applet in plain Java (www.delftware.com/javaday.html). The usage follows:

  • key c' clears
  • key r' randomizes
  • key performs one evolution
  • the Enter key starts or stops evolutions
  • mouse clicking and dragging toggles cells
Earlier we found a fine color Life applet somewhere on the World Wide Web. It had the same keyboard interface. The author commented on a few problems. A previous version would hang if the space bar was pressed while the program was already in the evolutions mode. When even this simple user interface leads to problems, it is apparent that building user interfaces is error-prone.

Let's see how the user interface of the color applet had been implemented; then we'll look at the Scriptic alternative.

Java Version
As with many Java applets, the Life applet has two threads, parallel running program parts. The main thread starts and stops; the other one in functions start' and stop'. These processes are called opening and closing the applet:

public void start() {(new GenerationThread(this)).start();}
public void stop () {time_to_die=true;}

To stop, the variable time_to_die' is set to true. The other GenerationThread' needs to notice when this happens. Keystrokes are handled in the function keyDown':

public boolean keyDown(Event e, int key) {
switch (key) {
case c' : doClear (); break;
case r' : doRandomize(); break;
case \n': generating=!generating; break;
case : if(!generating)
doGeneration(); break;
return true;

On e' the boolean variable generating' flips from true to false or the other way round. Again this is something that the other thread should notice:

class GenerationThread extends Thread {
public void run() {
if(app.generating) app.doGeneration();

In other words, as long as the time to die has not come, inspect the variable generating' to see whether a new evolution has to be generated and shown on the screen.

The communication between the two threads by means of boolean variables is rather cumbersome, and prone to errors like the one the author encountered. In general, if you look at the source code of an interactive Java program, it is not directly clear what parts are executed inside handleEvent' functions (including keyDown'), and what parts are in different threads. Communication between threads using wait() and notify() functions may even be harder.

The Life applet is still small; bigger ones would need more such boolean variables or wait/notify calls, leading to more potential problems. This is where Scriptic may help with better support for user input and parallelism.

Scriptic Version
Scriptic offers a new refinement construct: the script, well comparable to functions. A script to clear the screen after a c' keystroke is:

clear = key(c'!); {doClear()}

key(c'!) means that the c' key has been pressed. The subsequent action {doClear()} is a Java code fragment enclosed in braces; it takes care of clearing the cells.

Likewise the script randomize:

randomize = key(r'!); {doRandomize ()}

Unlike functions in a single thread, more than one of such scripts may be active at the same time, or waiting for an event such as a key stroke. doClear' and doRandomize' are two possible change actions on the board; others are toggling the cells, single stepping using the space bar, and multiple stepping, using the e' key. These possible changes are enabled inside an eternal loop in the script changes'

changes = while(true);
( clear || randomize || toggling
|| singleStep || multiSteps )
singleStep = key( !); {doGeneration()}

The ||' operator denotes or-parallelism: the operands run in parallel, but as soon as one completes successfully then the others are terminated. Here it ensures that a clear' or randomize' action would terminate multiSteps' if these were active.

Another use of the ||' operator is in the main script which is named live'. It is launched in its own thread from the applet's start' function. Life's live' script is an or-parallel composition of the eternal changes' script and exit'. exit' waits for the user to press x' to terminate the program in case the Life program is run as a frame rather than an applet:

exit = if (!(frame instanceof Applet)) key(x'!)
live = changes || exit

The multiSteps' script waits for the \n' key. Then it starts a code fragment with an eternal loop that does the generations.

multiSteps = key(\n'!); ({*while(true)
/ key(\n'!) )

The generation code fragment is inside asterisks, which means that it runs in a private thread that does not block the rest of the program. The threaded fragment may be stopped or broken, says the slash, by another \n' keystroke. The script key' also contains a special kind of code fragment, telling it is executed by handleEvent' in case of KEY_PRESS events; a bit simplified version is:

key (int k) = {.Event.KEY_PRESS: k=event.key}

An alternative for the earlier clear' script: suppose it needs as well to be controlled by a screen button and a menu item, apart from the c' button. Then the following would do:

clear = ( key(c' !)

+ clearButton.action
+ clearMenuItem.action); {doClear()}

The plus means exclusive choice. The implementations of the action' scripts automatically enable or disables the button and the menu item; a very handy feature which took us only six lines of Java code.

Finally a few words about iterations in Scriptic. You can use while' and for' constructs, but not just for sequential iterations; you may as well build parallel and alternative iterations. Scriptic has also a very special iteration symbol: ..' (ellipsis). This specifies an optional exit point in a loop. This kind of looping is also known from parser generators such as Yacc. It allows you to write very concise syntax descriptions, e.g.,

identList = (identifier; ..; comma); endOfInput

This could well parse a comma-separated identifier list, such as "A,B,C". Rather than a boolean expression, the context determines whether the loop ends: the availability of a comma versus the end of input.

Scriptic has been implemented for research purposes using a preprocessor and a virtual machine. The first version of the preprocessor made a rough translation of Scriptic into Java. It holds about 90 Kb source code in thirty-six Java classes. I hooked (hacked) these into Sun's Java compiler (javac). This was possible because Sun made the source code for the compiler available for other parties. This way the preprocessor only took a few weeks of work.

Then, in two months, Ari Schot created a totally new version of the preprocessor, which does a far better job; it contains also half a Java compiler, and has 800 Kb Java code in 140 classes.

The virtual machine has about 320 Kb of Java source in eighty classes and interfaces. It takes care of activating scripts, executing Java code fragments, thread management etc. Its main data structure is an activation graph, rather than a call stack. The virtual machine system is far more complicated than the preprocessor; it is comparable to both an interpreter and an operating system.

Java proved to be an excellent vehicle for implementing Scriptic. From existing C++ and Smalltalk knowledge, it is easy to learn. It is far less complicated than C++. Java makes it harder to make errors, especially with memory management. The threading support is only rudimentary but powerful. (For most applications I would recommend Scriptic, of course). The implementor's productivity may have been from two to five times as high as it may have been with C++, but this is a subjective conjecture.

The virtual machine was mainly implemented in the early Java days (winterof 1995/96); only command-line utilities such as Sun's compiler and debugger were available. The command-line compiler was invoked on Windows 95 from the Programmer's File Editor. I did not use the debugger because I disliked its user interface, and it happened not to be necessary. Errors like null-references and illegal type casts resulted in clear run-time exceptions and were then easily spotted. As a whole, this simple and free development environment seemed to work about as nicely as Microsoft Visual C++ 1.5. Now with dedicated Java development environments around, things have even improved.

The virtual machine runs pretty fast, since it does lots of list processing rather than array access. The Life example runs in the Scriptic version as fast as in a plain Java version. On the downside of this efficiency, the typical speed gain from Symantec's Jit compiler is only a factor 2.

Much to our surprise, Scriptic works pretty well with the Abstract Windowing Toolkit. We expected a collision, since both systems seem to grab control. This makes us feel that the basic design of the AWT is good; the existing problems with the AWT are mainly a matter of implementation and solvable.

Scriptic is available free for evaluation from www.delftware.com; the developer's kit includes a "Life trail" guide showing how to include buttons and menu items that are "automatically" enabled and disabled. The preprocessor now also supports an experiment with user-defined operators, which are types of overloaded operators without most problems known from C++. We plan to turn this preprocessor into a full-blow compiler which may also support the dimensioned numbers proposal (see Java Developer's Journal, issue 1).

Scriptic has also extended a sequence of other languages in the past: Pascal, Modula-2, C and C++. The combination with Java fits best, because of Java's simple syntax and thread support. The C++ version has successfully been applied to simulations of discrete systems, most notably in Computer Integrated Manufacturing.

Scriptic is based on the theory Process Algebra, developed in the eighties in The Netherlands. In short, Process Algebra studies processes as the kind of mathematical objects like numbers and booleans. It treats sequential and alternative operations as a kind of multiplication and addition, the main difference being that sequential composition is not commutative. Other forms of process composition such as parallelism can be expressed in terms of sequence and choice. This way Process Algebra can precisely define the meaning of parallel programs; it shows how to computate' the behavior of parallel programs. That is what the Scriptic Virtual Machine does.

About the Author
Andre van Delft studied Mathematics and Business Administration in Holland. Then he joined the Department of Computer Science at Leiden University for four years. From 1989 on he has worked in Delftware Technology as consultant and software developer. His topics of interest are software engineering, reliability and parallel programming.


All Rights Reserved
Copyright ©  2003 SYS-CON Media, Inc.
  E-mail: info@sys-con.com

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.