Obliq
Luca Cardelli's lexically scoped scripting language for distributed objects, built at DEC SRC on Modula-3 Network Objects, in which procedures can travel across the network and keep their original bindings
Created by Luca Cardelli at Digital Equipment Corporation Systems Research Center (DEC SRC)
Obliq is a small interpreted language for distributed object-oriented programming. Luca Cardelli created it at Digital Equipment Corporation’s Systems Research Center (DEC SRC) in Palo Alto, and it was available inside SRC from June 1993. Its central idea fits in one sentence: lexical scoping still applies when code crosses the network. When an Obliq procedure is sent to another machine and run there, its free variables still refer to the variables they referred to where the procedure was written, even when those variables live on a different computer. Cardelli’s paper on the language, A Language with Distributed Scope, won ACM SIGPLAN’s Most Influential POPL Paper Award ten years after it was presented.
History and Origins
Built on Network Objects
In the early 1990s, DEC SRC was one of the main centres of Modula-3 development. Among its projects was Network Objects, a distributed-object system by Andrew Birrell, Greg Nelson, Susan Owicki and Edward Wobber. It let a Modula-3 program call methods on objects in another address space, with stub generation and distributed garbage collection handled for it.
Obliq is a scripting language built directly on that system. Cardelli’s paper credits the Network Objects project with “the infrastructure without which Obliq would not have been conceived.” Every Obliq object is a Modula-3 network object, and so is every updatable Obliq variable. As a result, any object or variable can be reached from another machine without extra work. The paper’s verdict: “a distributed language like Obliq is easy to implement on top of a library like Modula-3 Network Objects.”
Publication
According to the full paper, Obliq was available at SRC from June 1993. The first public description was SRC Research Report 122, Obliq: A Language with Distributed Scope, dated 3 June 1994. A short version was presented at the ACM Symposium on Principles of Programming Languages (POPL) in January 1995, and the full paper appeared in USENIX’s journal Computing Systems (volume 8, number 1, Winter 1995). The implementation and documentation were published on SRC’s web site and in the SRC Modula-3 distribution.
The language was designed alongside Martín Abadi and Cardelli’s work on the semantics and type theory of objects, published in 1996 as A Theory of Objects. The paper is careful to note that the formal work did not cover distributed scoping or distributed semantics.
Design Philosophy
Distributed lexical scoping
The paper names the question Obliq set out to answer: when a procedure is sent across the network, “what happens to the free identifiers of network-transmitted procedures?” Obliq’s answer is that “such identifiers are bound to their original locations, as prescribed by lexical scoping, even when these locations belong to different network sites.”
As a result, the meaning of a program depends on where its identifiers were bound, not on where it happens to run. A procedure sent to a compute server can still update a counter on the client machine, because the counter it names is the client’s counter. If the server has a variable with the same name, that variable is untouched.
Objects stay put; computations roam
Obliq objects are fixed to the site that created them. Obliq does not move objects. Instead, it gives programmers two primitives from which migration can be built:
- Cloning, which can be done remotely, so that an object can be copied to another site.
- Aliasing, which redirects operations on one object to another.
Migration is then “clone it over there, then alias the original to the clone.” Procedures move freely, and a procedure with no free identifiers is, in the paper’s words, “a completely self-contained computing agent.”
Prototypes without delegation
Obliq has no classes. An object is built directly or cloned from another object. Unlike Self, Obliq does not use delegation. Cardelli called its model embedding-based: all of an object’s methods and fields are stored in the object itself. The paper gives a distributed reason for this choice. When an embedded object is cloned across the network, its methods go with it and it can work on its own at the destination. A delegation-based object would need its parent objects moved along with it.
Key Features
Objects and the four operations
An Obliq object is a collection of named fields, and a field holds a value, a method or an alias. There are four basic operations:
| Operation | Syntax | Meaning |
|---|---|---|
| Selection / invocation | a.x, a.x(b) | read a field or call a method |
| Update / override | a.x := b | replace a field or method |
| Cloning | clone(a) | make a shallow copy |
| Aliasing | a.x := alias y of b end, redirect a to b end | send operations to another object |
Methods name their self parameter explicitly, as their first argument:
let counter = {
n => 0,
inc => meth(self) self.n := self.n + 1; self end
};
counter.inc();
Protection and serialization
Two attributes control access to an object:
- A
protectedobject rejects external updates, clones and aliases, but allows them when the object does them to itself throughself. This stops a client from, for example, overriding a network server’s methods. - A
serializedobject has an implicit mutex. External operations take the lock, but operations an object performs on itself throughselfdo not, so a method can call its sibling methods without deadlocking. Conditional synchronization over that implicit mutex is also provided.
{ protected, serialized,
... }
Procedures, control flow and threads
Outside its object model, Obliq is a conventional higher-order imperative language. let declares constants, var declares updatable variables, let rec defines recursive procedures, and procedures are first-class closures. Control structures include if/elsif/else, case, loop/exit, for and foreach, try ... except and try ... finally. Concurrency support includes fork/join, mutexes and conditions. This factorial example is from the paper:
let rec recFact =
proc(n)
if n is 0 then 1
else n * recFact(n - 1)
end;
end;
Values are typed at run time, but variables have no declared types. Cardelli described the language as untyped. Comments use Modula-3’s (* ... *) delimiters, and library procedures are called with a library_name prefix, as in net_export.
Network primitives and execution engines
The net library exports objects to a name server and imports them by name. Because compute servers are so common, Obliq also has a built-in execution engine, which accepts procedure closures from the network and runs them at its own site. This compute server example is adapted from the paper:
(* Server site *)
var replay = proc() end;
net_export("ComputeServer", namer,
{ rexec => meth(s, p) replay := p; p() end });
(* Client site *)
let computeServer = net_import("ComputeServer", namer);
var x = 0;
computeServer.rexec(proc() x := x + 1 end);
(* x is now 1 on the client: the closure ran on the server,
but its free x is still bound to the client's variable *)
The paper’s migration example combines these features. A serialized, protected object calls a method on itself that sends clone(self) to a remote engine, then runs redirect self to remoteObj end. Serialization makes the two steps atomic. Because both operations count as self-inflicted, migration works even on a protected object.
Embedding
Obliq could run as a standalone interactive interpreter or be linked into Modula-3 programs as a library, so that those programs could be scripted and could work with each other remotely through Obliq. The SRC implementation gave scripts access to many Modula-3 libraries, including SRC’s user-interface toolkit.
Evolution
Obliq has no numbered releases. It was developed and used at SRC from 1993 to about 1996. Most of its later history is the systems built on top of it:
- Visual Obliq (Krishna Bharat and Marc H. Brown, UIST ‘94; SRC Research Report 130a, October 1995) was a GUI builder for multi-user distributed applications. Its project page says Bharat did most of the work while interning at SRC in the summers of 1993 and 1994.
- Obliq-3D (Marc Najork and Marc H. Brown, IEEE Transactions on Visualization and Computer Graphics, 1995) used Obliq to script 3D animation.
- Migratory Applications (Bharat and Cardelli, UIST ‘95) moved running GUI applications between machines.
- Oblets and Collaborative Active Textbooks (Brown and Najork, 1996–1997) put Obliq applets into web pages for collaborative algorithm animation.
The source tree, including the interpreter, its 3D and animation libraries, Visual Obliq and its CGI variant, is still carried in the m3-obliq directory of the community-maintained Critical Mass Modula-3 (cm3) repository on GitHub. The last real change to that directory was general build maintenance in 2021, and this page does not claim that the code still builds or runs.
Current Relevance
Obliq is a historical research language. It was never a commercial product, and its known uses were in research, chiefly at DEC SRC and among its collaborators. DEC SRC went to Compaq with the rest of Digital in 1998, and its original Obliq web pages are long gone. No Docker image or modern package exists.
Its ideas have lasted better than its implementation. Distributed lexical scoping and network-transparent closures appear again in the distribution model of Oz/Mozart, whose designers credit Cardelli’s Obliq work in their HOPL IV history. Obliq’s migration scheme also gave formal-methods researchers a concrete problem. Øjeblik, a calculus extracted from Obliq, was used to show that migration under the aliasing model of Obliq’s implementation can be unsafe in some contexts, and to propose a model and type system that make it safe.
Why It Matters
Obliq took a principle from the lambda calculus, that a name means what it meant where it was written, and showed that it still works in a distributed system. That one rule settled questions that ad hoc remote-execution systems had left open: which variables a mobile procedure can see, what happens to its free variables, and how an agent keeps its connections when it moves. The design was small, with four object operations, two object attributes and an execution engine, yet it was enough to build compute servers, replicated user interfaces and migrating applications. SIGPLAN recognized its influence in 2005. Obliq is still widely cited as an early example of a language in which code can move across the network while keeping lexical scope.
Timeline
Notable Uses & Legacy
Visual Obliq (Georgia Tech / DEC SRC)
Krishna Bharat and Marc H. Brown's GUI builder for distributed, multi-user applications. Each widget's callbacks are written in Obliq, and a central server sends every client both its code (as an Obliq closure) and its user interface
Obliq-3D
Marc Najork and Marc H. Brown's 3D animation system at DEC SRC, which uses Obliq as its scripting language for building and animating scenes
Algorithm animation at DEC SRC
Obliq scripted algorithm animations in Brown's SRC animation work. Brown and Najork later built Collaborative Active Textbooks, a web-based algorithm-animation system for an electronic classroom, from Obliq applets
Migratory Applications
Bharat and Cardelli's UIST '95 system, in which a single migration command moves a running user-interface application to another machine with its state intact, using Obliq's cloning and network-transparent closures
Programming-language semantics research
Obliq's migration-by-cloning-and-aliasing became a test case for mobile-object calculi, including Øjeblik and the pi-calculus encodings by Nestmann, Merro and colleagues