What is Sweet?

Sweet, a static weaver and editor tool for Java, is a prototype designed as a tool for object-oriented program development using Java, although the underlying ideas could be adapted to other settings. It's raison d'etre is to help explore the idea of multi-perspective programming as a means to escape the "tyranny of the dominant decomposition."

With the current, batch-oriented implementation of Sweet, a program is written as a sequence of declarations, the text of which may be spread across several files. As the Sweet tool processes each declaration, it builds up a representation of a complete program in an internal data structure referred to as a repository. These declarations should be thought of, not as the code for a particular program, but as instructions that describe how that particular program might be constructed. As such, Sweet provides a primitive form of meta-programming, although it differs from much of the previous work in that area where the focus has been on mechanisms for programming in the small.

The objective of Sweet is to support more flexible decomposition and construction of Java programs than conventional Java compilers. Specifically, with Sweet, programmers have more opportunity to organize, arrange, and group fragments of code in a way that reflects the problem that is being solved or the choice of algorithm that is being used, instead of being constrained to follow the structure of the language that is used to express those ideas.

Sweet is a practically motivated tool, but it enables a novel (and we think quite intuitive) approach to program construction. In the input to Sweet, a programmer blends definitions of points in an abstract program structure---each of which might correspond, for example, to a package, class, or method---with descriptions of the executable content that should be placed within that structure. The difference between writing programs with conventional Java tools or writing programs with Sweet is analogous to the difference between printing an image on a piece of paper or drawing it by hand. To print an image, we must convert it into a collection on pixels and then send data for each one to the printer in a specific order. Typically, neither the decomposition into pixels or the sequencing of pixel data has any direct relation to the objects depicted in the image. Moreover, the pixels corresponding to individual objects in the image will often end up scattered across the output pixel stream, concealing the relationship between them until the whole image has been rendered. By contrast, when we draw a picture by hand, we typically work at a much higher and more natural level, painting complete objects and proceeding in an order that is determined by the image itself and not by the orientation or size of the paper on which it is drawn. Only the most abstract of artists would ever consider drawing an image in the same way that the printer does!

The syntax of Sweet has also been designed to reduce the need for tedious boilerplate, duplication of information and tangling of datatype definitions with the implementations of associated operations. For example, Sweet provides a compact notation for describing class hierarchies, and allows uses of the ``visitor pattern'' to be described directly at the level of source code without encoding. The following vignette illustrates these benefits in miniature:

		  public abstract class List {
public case Nil
public case Cons(private int x, private List xs)
}

public int length()
case List abstract;
case Nil {return 0;}
case Cons {return 1+xs.length();}
The first part of this code defines a hierarchy of three classes, with an abstract base class "List" and implementations "Nil" and "Cons" for empty and non-empty lists, respectively. The second half of the code defines a "length" method on lists, collecting together in one place the appropriate definitions for this operator in each of the classes. In fact Sweet would produce exactly the same output program if the input were presented to it in the conventional Java style as three separate classes, each containing an appropriate definition of "length". In some cases, and for some purposes, this version of the program might be preferred. However, in this simple example, we believe the code shown above is preferable because it highlights more clearly the relationship between the classes; it collects the definitions for a single conceptual unit---the "length" method---into a single location; and it emphasizes the separation between these two different aspects of the program. The most important point here, however, is that Sweet gives programmers the opportunity to choose between these (and other) options, instead of insisting on one particular choice as a conventional Java compiler does.

Given the description above, we can expand on the acronym for Sweet. Sweet is a static tool because its work is performed at compile-time, without requiring any run-time support (and without the corresponding overhead that might result from encodings or support libraries). Sweet is a weaver that allows the code for cross-cutting aspects of a program's source code to be collected together in a single file (or group of files). In the Java output, that same code may be spread across many different classes and automatically integrated with code describing other aspects of the overall program's behavior. Finally, Sweet is an editing tool that allows sequences of editing actions to be captured, replayed, and presented as source text. These editing actions are described at a high-level, acting on program level constructs such as packages, classes, and methods, instead of the low-level, character-oriented descriptions of editing actions that are obtained with textual diffs.