1 Introduction

The Mozart system implements Oz 3, the latest in the Oz family of multi-paradigm languages based on the concurrent constraint model. Oz 3 is almost completely upward compatible with its predecessor Oz 2. The main additions to Oz 2 are functors (a kind of software component) and futures (for improved dataflow behavior). Oz 2 is itself a successor to the original Oz 1 language, whose implementation was first released publicly in 1995. Except as otherwise noted, all references to Oz in the Mozart documentation are to Oz 3.

Oz 3 and the Mozart system have been developed mainly by the research groups of Gert Smolka at the DFKI (the German Research Center for Artificial Intelligence), Seif Haridi at SICS (the Swedish Institute of Computer Science), and Peter Van Roy at UCL (the Université catholique de Louvain).

Underlying all versions of Oz is a concurrent constraint programming model, extended to support stateful computations, i.e., computations on mutable objects. The theoretical foundation of the concurrent constraint model is given in [Sar94]. The original Oz computation model, Oz 1, supports a fine-grained notion of concurrency where each statement can potentially be executed concurrently. This results in a fine-grained model similar to the actor model. A good exposition of the Oz 1 programming model is given in [Smo95]. Our experience using Oz 1 showed that this kind of model, while theoretically appealing, makes it very hard for the programmer to control the resources of his/her application. It is also very hard to debug programs and the object model becomes unnecessarily awkward.

Oz 2 remedies these problems by using instead a thread-based concurrency model, with explicit creation of threads. A powerful new object system has been designed and traditional exception handling constructs have been added. In addition, the constraint solving and search capabilities have been greatly enhanced.

Oz 3 conservatively extends Oz 2 with two concepts, functors and futures, and also corrects several minor syntactic problems. A functor is a kind of software component. It specifies a module in terms of the other modules it needs. This supports incremental construction of programs from components that may be addressable over the Internet by URLs, see [Duc98]. A future is a logic variable that can be read but not written. This allows safe dataflow synchronization over the Internet.

The Mozart system supports distributed and networked applications. It is possible to connect Oz computations located on different sites, resulting in a single network-transparent computation. Mozart supports automatic transfer of stateless data and code among sites, mobile computation (objects), message passing, shared logic variables and orthogonal mechanisms for fault detection and handling for the network and for sites.

1.1 Summary of Oz features

A very good starting point is to ask why Oz. Well, one rough short answer is that, compared to other existing languages, it is magic! It provides programmers and system developers with a wide range of programming abstractions to enable them to develop complex applications quickly and robustly. Oz merges several directions of programming language designs into a single coherent design. Most of us know the benefits of the various programming paradigms whether object-oriented, functional, or constraint logic programming. When we start writing programs in any existing language, we quickly find ourselves confined by the concepts of the underlying paradigm. Oz solves this problem by a coherent design that combines the programming abstractions of various paradigms in a clean and simple way.

So, before answering the above question, let us see what Oz is. This is again a difficult question to answer in a few sentences. So, here is the first shot. It is a high-level programming language that is designed for modern advanced, concurrent, intelligent, networked, soft real-time, parallel, interactive and pro-active applications. As you see, it is still hard to know what all this jargon means. More concretely:

1.2 The Kernel Language

This section gives a short but precise introduction to the Oz kernel language. The full Oz language can be regarded as syntactic sugar to a small kernel language. The kernel language represents the essential part of the language.

<Statement> ::= <Statement1> <Statement2>
 | X = f(l1:Y1 ... ln:Yn)
 | X = <number>
 | X = <atom>
 | X = <boolean>
 | {NewName X}
 | X = Y
 | local X1 ... Xn in S1 end
 | proc {X Y1 ... YnS1 end
 | {X Y1 ... Yn}
 | {NewCell Y X}
 | Y=@X
 | X:=Y
 | {Exchange X Y Z}
 | if B then S1 else S2 end
 | thread S1 end
 | try S1 catch X then S2 end
 | raise X end

Figure 1.1: The Oz kernel language

The Oz execution model consists of dataflow threads observing a shared store. Threads contain statement sequences Si and communicate through shared references in the store. A thread is dataflow if it only executes its next statement when all the values the statement needs are available. If the statement needs a value that is not yet available, then the thread automatically blocks until it can access that value. As we shall see, data availability in the Oz model is implemented using logic variables. The shared store is not physical memory, rather it is an abstract store which only allows operations that are legal for the entities involved, i.e., there is no direct way to inspect the internal representations of entities. The store contains unbound and bound logic variables, cells (named mutable pointers, i.e., explicit state), and procedures (named lexically scoped closures that are first-class entities). Variables can reference the names of procedures and cells. Cells point to variables. The external reference procedures are variables. When a variable is bound, it disappears, that is, all threads that reference it will automatically reference the binding instead. Variables can be bound to any entity, including other variables. The variable and procedure stores are monotonic, i.e., information can only be added to them, not changed or removed.

Figure 1.1 defines the abstract syntax of a statement S in the kernel language. We briefly define each possible statement. Statement sequences are reduced sequentially inside a thread. Values (records, numbers, etc.) are introduced explicitly and can be equated to variables. All variables are logic variables, declared in an explicit scope defined by the local statement. Procedures are defined at run-time with the proc statement and referred to by a variable. Procedure applications block until their first argument refers to a procedure. State is created explicitly by NewCell, which creates a cell, an updateable pointer into the variable store. Cells are read by @ and updated by := or alternatively by Exchange. Conditionals use the keyword if and block until the condition variable B is true or false in the variable store. Threads are created explicitly with the thread statement. Exception handling is dynamically scoped and uses the try and raise statements.

The full Oz language is defined by transforming all its statements into this kernel language. This will be explained in detail in this document. Oz supports idioms such as objects, classes, reentrant locks, and ports [Smo95][VR97]. The system implements them efficiently while respecting their definitions. As an introduction we will give a brief summary of each idiom's definition. For clarity, at this stage we have made small conceptual simplifications. Full definitions are given later in this document.

1.3 Classes

A class is essentially a record that contains the method table and attribute names. A class is defined through multiple inheritance, and any conflicts are resolved at definition time when building its method table.

1.4 Objects

An object is essentially a special record having a number of components. One component is the object's class. Another component is a one-argument procedure that references a cell, which is hidden by lexical scoping. The cell holds the object's state. Applying an object Obj to message M applies the object's procedure to M. The argument indexes into the method table. A method is a procedure that is given a reference to the state cell. In general it modifies the state of the object.

1.5 Reentrant locks

A reentrant lock is essentially a one-argument procedure {Lck P} used for explicit mutual exclusion, e.g., of method bodies in objects used concurrently. Reentrant locks use cells and logic variables to achieve their behavior. P is a zero-argument procedure defining the critical section. Reentrant means that the same thread is allowed to reenter the lock. Calls to the lock may therefore be nested. The lock is released automatically if the thread in the body terminates or raises an exception that escapes the lock body.

1.6 Ports

A port is an asynchronous channel that supports many-to-one communication. A port P encapsulates a stream S. A stream is a list with unbound tail. The operation {Send P M} adds M to the end of S. Successive sends from the same thread appear in the order they were sent.

Seif Haridi and Nils Franzén
Version 1.4.0 (20080702)