Introducing Jist

Nik Boyd

Copyright 1997,1998,1999 Nikolas S. Boyd. Permission is granted to copy this document provided this copyright statement is retained in all copies.


Jist is a typed version of Smalltalk that runs on the Java virtual machine. This paper describes the origins of Jist, especially the motivations and choices that led to its design.



BACKGROUND

I've been involved with object technology in general, and Smalltalk in particular since 1986. The simplicity and expressiveness of Smalltalk's syntax has always been attractive to me. The maturity of its class libraries and the agility of its tools contributed to my seduction. As a programmer, I love Smalltalk. There, I've said it. But for those who know me, this is really no secret.

Then, there's the new kid on the block: Java. Java has integrated most of the interesting software technologies that were developed over the past few decades.

  • Object-orientation
  • First-class interfaces
  • Strong typing
  • Exception handling
  • Name spaces
  • Multithreading
  • Garbage collection
  • Ubiquitous virtual machinery
  • Web and internet connectivity
  • Event-driven graphical user interfaces
  • Client-server architecture
  • Deliverable behavior and content
  • Security

While some claim that Java is merely (or ought merely be considered) a programming language, it is in fact much more. It clearly has evolved into a platform whose strength and industry momentum grow daily. So, who am I to resist the tidal wave of Java? Of course, I can not, could not, would not, was not the least bit inclined. There is too much of what I love about Smalltalk in Java to have distanced myself from it. I embraced it as fully as Smalltalk. And clearly, Smalltalk has continued to have an influence over those building the core Java class libraries. One look at Swing and JFC was enough to convince me that the folks involved have used Smalltalk as a touchstone for their designs. Bravo! Outstanding!

However, just as clearly, the original designers of Java were strongly influenced by C and C++ when they developed Java's syntax. I can understand the likely motivation: C and C++ garnered the most mindshare during the '80s and early '90s. From a marketing standpoint, this was the obvious choice. And, while Java's syntax is certainly a vast improvement over that of C++, like others of its ilk, Java's syntax imposes certain limitations on your expressiveness.

Java 1.1 finally included reflection, but Java classes are not fully metaprogrammable - the class model does not support metapolymorphism (at least not yet, but we can hope...). Some might argue that these limitations are minor compared to the benefits and features that Java does provide. Granted. However, should we merely accept these limitations?

I could not, not when I suspected that something better might be possible. For many months, I wondered about whether it might be feasible to integrate the best features of Smalltalk and Java. I was originally motivated by the desire to write Smalltalk code and compile it into Java VM code. I spoke with fellow Smalltalkers about these ideas and received much encouragement. I did some experiments with Java's reflection facility [Boyd, 1997]. I spent many nights and weekends puzzling over this question. Finally, by developing and debugging the syntax of a new programming language, I convinced myself that it is feasible. Now, I hope to convince you as well.


Goals for Jist

JIST = Java In Small Talk, providing the essence (gist) of both. Jist supports the following parts of Smalltalk syntax:

Jist supports the following parts of Java:

What's missing:


DESIGN CHOICES

I was very careful in the design choices I made for Jist. I didn't want to destroy those parts of Smalltalk syntax that I feel represent the essential flavor of the language.


Declarative Model

This is an issue that has arisen occasionally in the course of Smalltalk's history. The strongest proponent for a declarative Smalltalk syntax has been Alan Wirfs-Brock (now with Smalltalk Systems). His work has finally achieved fruition [Wirfs-Brock, 1996], but has not as yet found its way into a commercially available Smalltalk product.

Traditionally, Smalltalk systems are built in the context of an object memory image. While the image based development environment contributes significantly to the agility of Smalltalk's integrated suite of tools, it introduces some difficulties for source code, component and system configuration management in large development projects. A declarative, file based programming model makes it much easier to use existing version control and configuration management tools. Also, some of the newer Java development tools have incorporated incremental compilation facilities that make Java programming almost as agile as Smalltalk. So, it is feasible to have rapid development even with a file based model. For these reasons and those discussed in the next section, the Jist programming model follows the more traditional file based one.


Packages

The absence of a name space mechanism is one of the major deficiencies of most commercial Smalltalk environments. The absence of name spaces permits the occurrence of class naming conflicts, especially when integrating large libraries from independent development organizations. In previous work [Boyd, 1996], I've proposed mechanisms for adding name spaces to Smalltalk. However, when I learned Java, I realized that the package model it supports provides a much more elegant solution.

The Java language model has classes and packages. Java classes are logically organized into packages. Classes are embodied physically in the file system as class files. Packages are embodied as directories in the file system. The following diagram depicts these relationships.

Packages can be used to organize classes, but they also serve as name spaces for classes. This helps system designers resolve potential naming conflicts between classes. This model is simple and powerful. It leverages the fact that Java classes are manifested as files contained in the directories of a file system. There is a direct correspondence between the logical design of the system and its physical manifestation as (and the organization of the) class files. For these reasons, I chose to adopt the same model for Jist classes and packages.


Type Annotations

This is another issue that has arisen many times in the course of Smalltalk's history. Several researchers have proposed means for adding type information to Smalltalk. In retrospect, I believe Java has the right approach for type annotations, especially its support for the use of packages and interfaces in the type model. For this reason, the Jist type model duplicates virtually all of Java's. As with Java, Jist requires type annotations on classes, variables, methods, arguments and local variables.

Smalltalk's dynamic typing allows you to prototype code without concern for whether objects yet support the messages they are sent. This facility supports a highly incremental programming style, much valued by Smalltalk programmers. Historically, this has been one of the strongest arguments against static typing and in favor of dynamic typing. However, having both static and dynamic typing available as options will be even better.

Eventually, I intend to support both static and dynamic typing in a Jist development environment that integrates tools in much the same way as Smalltalk. Then, the Jist compiler will support both typing options. When strong typing is enabled, a message sent to an object must be supported by an interface. Unsupported messages are reported as compile errors (as in Java).

When soft typing is enabled, a message supported by an interface is optimized, but unsupported messages are still sent. Messages are sent using the appropriate variant of perform:, which resolves the method binding using the Java reflection facility. This imposes a performance penalty on those kind of message sends, but it retains the equivalent Smalltalk message semantics (e.g., when porting Smalltalk code to Jist). This may also encourage programmers to improve the performance of their code by refining their type information (e.g., during product finalization). Soft typing


Reserved Words

Fully adopting the Java conventions for type annotations requires the introduction of some reserved words. Initially, I was loath to reserve these words because Smalltalk has only a handful of reserved words. However, I realized the following:

For these reasons, Jist supports the use of the following reserved words as type annotation options:

Class Variable Method Argument Local
final final final final final
public
protected
public
protected
private
public
protected
private
static static
abstract abstract
transient
volatile
native
synchronized
throws
class
interface

There are two nouns used to declare entities in both Java and Jist - class and interface. Being nouns, reserving them could interfere with some naming conventions. In fact, the word class is commonly used in Smalltalk to access the metaclass (static) methods. Reserving these words would create undo hardship on Smalltalk programmers. Also, reserving them is unnecessary because of their location within the overall syntax of Jist. For these reasons, Jist uses them to declare classes and interfaces, but Jist does not treat these as reserved words.

Another pair of words are reserved for use with type information - is and as. Jist uses is to indicate the type of a variable or argument. Jist uses as for type casting instead of the parenthetical cast notation used by Java, C++, and C. This follows an established naming convention used in Smalltalk for conversions between types - e.g., asString, asInteger, etc. These kinds of conversions are also supported, but the use of as for casts generalizes this convention to support type compatible downcasting (as featured in Java).

Both these words are seldom (if ever) used alone in any naming conventions. However, using them in type declarations and casts increases the readability of Jist code. For example, cast expressions look like this:

primary as CastType

Variable declarations look like this:

variableName is TypeName := initialValue.

Method signatures look like this:

methodName: argumentName is ArgumentType ^ResultType

Block signatures look like this:

: argumentName is ArgumentType ^ResultType !

These reserved words behave syntactically like binary operators instead of unary or keyword messages. If they were keyword messages, the syntax would require the insertion of parentheses around the expressions, which would complicate the notation.

Also, notice the declarations of the result types used in the last two examples. The return operator is used to indicate the result type of a block or method. This follows from the syntax used to exit a block scope with a result.


Interfaces

Support for object interfaces is one of the most powerful and innovative features of Java. Interfaces provide a language mechanism for defining polymorphism distinct and separate from inheritance. The object community recognized the importance of supporting object interfaces largely as a result of the development of distributed object computing facilities like CORBA and DCOM. Interfaces eliminate the need for multiple inheritance and the associated thorny issues that arise with it. For these reasons, Jist supports the definition and use of interfaces.


Punctuation

The syntax for Smalltalk methods and blocks are very close. The primary difference is that blocks are delimited with square brackets [ ], while methods are not. In order to support the declarative model and normalize the syntax, I've eliminated this difference in Jist. Thus, the declaration of Jist classes, interfaces, and methods are also delimited with square brackets. For developers familiar with Java, this means that everywhere you would use curly braces { } in Java, instead you use square brackets [ ] in Jist.

Java uses ";" as a statement terminator. Smalltalk uses "." as a statement terminator and ";" for message cascades. The Smalltalk syntax more closely approximates the punctuation used in natural language, especially English. Also, message cascades are frequently used in Smalltalk to simplify sending a set of messages to a single object. For these reasons, Jist uses the Smalltalk statement punctuators.


Blocks

Blocks are a very powerful aspect of the Smalltalk language. They are so flexible that they are used to implement all the Smalltalk control structures. This contributes to Smalltalk's syntactic simplicity. There are no special words in Smalltalk reserved for the control structures as there are in other OO languages like Java and C++. I felt it very important to retain this aspect of the syntax in Jist.

Fortunately, the 1.1 version of the Java language now supports inner classes, which can be used to mimic the semantics of Smalltalk blocks. Most of the traditional control structures can be optimized and translated into the equivalent Java control structures. However, where specialized blocks are used, they can be translated into an equivalent Java inner class by the Jist compiler. For a further discussion of this, see the section in [Boyd, 1997] that discusses the implementation of Smalltalk blocks using Java inner classes.


Local Block Variables and Non-local Returns

Smalltalk block local variables can be mapped directly to variables (data members) of inner class instances. For example:

public exampleMethod: methodArgument is ArgumentType ^ResultType
[
methodArgument isNil ifFalse:
[ : ^ResultType !
SomeType aLocal := SomeClass new.
ResultType result := aLocal unaryMessage.
^result
].
]

The Jist preprocessor translates this block into the following Java code:

public ResultType exampleMethod( final ArgumentType methodArgument )
{
ResultType result = nil;
try
{
( new ZeroArgumentVoidBlock()
{
public void value()
{
( methodArgument.isNil() ).ifFalse(
new ZeroArgumentVoidBlock()
{
SomeType aLocal;
ResultType result;

public void value()
{
aLocal = new SomeType();
result = aLocal.unaryMessage();
NonLocalReturn.throwWith( result );
}
} );
}
} ).value();
}
catch( NonLocalReturn farReturn )
{
result = (ResultType) farReturn.result;
}
return( result );
}

Binary Operators

Binary operators are another part of Smalltalk that I would hate to lose. Unfortunately, Java does not support operator overloading (unlike C++). I find this limitation in Java very strange. I can only surmise that it would have introduced some complication in the Java grammar or the language developers simply didn't have time to include it. Smalltalk allows method names to be arbitrary combinations of the supported binary operators. For these reasons, Jist also supports arbitrary combinations of the following binary operators.

@ & | ~ - + * \ / < > = ,

Keyword Messages

To my mind, the support for keyword messages is one of the most compelling parts of Smalltalk. Keyword messages give you the ability to model natural language statements much more closely than you can with the kind of functionally oriented syntax found in most programming languages. Call me biased, but I find

sender transmit: message to: receiver via: medium

much easier to read and understand than a method call with a simple list of parameters. The ability to use arbitrary combinations of verbs and prepositions as keywords gives us the ability to map natural language sentences to readable code. The method signatures of Java really have no analogous way to model natural language. One possible mapping might look something like this:

sender.transmit_to_via_( message, receiver, medium ).

In fact, this kind of mapping provides one possible way of achieving interoperability between Jist and Java.

On the other hand, Smalltalk has no support for simple parameter lists. In order to allow calls to Java methods with simple parameter lists, Jist supports anonymous keywords - i.e., keyword messages that support parameter lists using ":" as a parameter separator. For example,

sender transmit: message : receiver : medium

would correspond to the Java equivalent

sender.transmit( message, receiver, medium ).

However, further exploration of interoperability between Jist and Java is beyond the scope of this paper. Please refer to [Boyd, 1997] for more detailed discussions and suggestive approaches to interoperability.

The ability to model natural language with keywords provides an unique kind of traceability back to design and requirements. I've never seen anything like this kind of natural expressiveness in any other commercially available programming language. For this reason, support for keyword messages is an essential part of Jist.


Variable Initializations

From the designers viewpoint, there is a significant advantage to variable initialization during object construction. All new instances can have an established, well known state immediately after they've been instantiated. This gives the designer a well defined starting point from which to understand the evolution of the object state. Turning variable declarations into statements also allows the elimination of the use of vertical bars "|" for delimiting local variables in blocks.

Both C++ and Java provide language conventions for object initialization - i.e., constructors. However, Java also supports direct variable initialization in a class definition outside of a constructor. This facility eliminates the need for most default constructors and initialization methods. For this reason, Jist also supports direct variable initialization, both for class data members and local method and block variables.


Gory Details

Here are links to:


Future Work

Clearly, there is still much to do. I foresee the following tasks:

I'd like to add two more features to the language, but they require virtual machine support.


CONCLUSION

Because I love Smalltalk, I would hate to see it vanish or relegated to the computing scrap heap. Jist provides a way for Smalltalk to evolve symbiotically and synergistically with Java. If we can hook it up to the Java engine, perhaps it will continue to have a future in the commercial programming language market.


Bibliography

[Beaton, 1994] Wayne Beaton. Name Space in Smalltalk/V for Win32 in The Smalltalk Report 4(1). SIGS Publications, September 1994.

[Boyd, 1997] Nik Boyd. Toward Smalltalk and Java Language Integration. http://home.labridge.com/~nikboyd/papers/sttojava/

[Boyd, 1996] Nik Boyd. Class Naming and Privacy in Smalltalk in The Smalltalk Report 6(3). SIGS Publications, November 1996.

[Wirfs-Brock, 1996] Alan Wirfs-Brock. Declarative Model for Smalltalk Programs, a talk given at the OOPSLA Conference, October 1996.

[Wirfs-Brock, 1988] Alan Wirfs-Brock, Brian Wilkerson. An Overview of Modular Smalltalk in OOPSLA Conference Proceedings. ACM, September 1988.

Trademarks
Java is a trademark of Sun Microsystems, Inc.