Obliq

Obliq is a lexically-scoped, untyped, interpreted language that supports distributed object-oriented computation. Obliq objects have state and are local to a site. Obliq computations can roam over the network, while maintaining network connections. Distributed lexical scoping is the key mechanism for managing distributed computations.
A Language with Distributed Scope — Luca Cardelli

An overview of Obliq

This section summarizes the information found in A Language with Distributed Scope [8].

Obliq is a object oriented distributed programming language. It uses a prototype-based object system where each object is network transmissible. These objects may hold values which point to remote or local information. It's distributed programming abilities are implemented using four core concepts: sites, locations, values, and threads.

Code Sample

The following is a sample of what Obliq looked like. The following implements Peano numbers and is taken from page 7 of [8]:

let zero = 
  { case =>
      proc(pz, ps) pz() end,
    succ =>
      meth(self)
        let o = clone(self);
        o.case := proc(pz, ps) ps(self) end;
      end } ;

let one = zero.succ;

let iszero =
  proc(n)
    (n.case)(proc() true end, proc(p) false end)
  end;

iszero(one);
iszero(two);

Sites and Locations

Sites are adress spaces that hold locations that values can exist at. Each location is tied to a unique site. Sites are not exposed directly in the language, but exist as part of creating locations.

Values

In Obliq, there are four core values types:

Objects, arrays, and closures can all contain values which point to remote resources. Objects can have fields that exist remotely. Arrays can hold values that point off site. Closures can capture values from one site and transport them intenerally to another.

Threads

Threads are instruction executors that may be run concurrenctly. They are capable of running locally and across the network. Threads can suspend themselves at one site and resume excution on another site seemlessly.

Objects in Detail

As mentioned in the quick overview section, Obliq uses prototypical-objects, specifically concatenative or embedded prototypes. Concatenative-prototypes embed all the fields of the prototype into the newly created object. Thus, Obliq has no prototype-chain to follow which is benfitial in a networked enviroment.

If Obliq was delegation based, the link between objects and their prototypes would need to be distrubted. This would increase the complexity of working across the network. Additionally, changes to the parent would have to distributed across the network.

Fields

Obliq objects take the form of { x1 => a1, ..., xn => an }. Objects can hold three types of fields:

  1. Value fields

    x => 3

  2. Method fields

    x => meth(y0, y1, ..., ym) body end

    Methods can be manipulated as values, but unlike the procedures (defined by proc), can only be activeted inside objects. Additionally, methods are given impicit access to the self parameter. Furthermore, procedures can be extracted from fields, but accessing a method will attempt to invoke it.

  3. Alias fields

    x => alias y of obj end

    Alias are used to foward feild access to another object. In the above example, x will foward all access to it towards the field y in obj. This redirection will happen recursively if the alaised field is also an alais.

Since all fields are directly embedded into objects, look up time is always one-step and search a signle object. Look up operations are cached, and do not penalize large objects. Each object has a unique cache.

Operations on Objects

Obliq implements four additional operations on objects outside of creation: selection and invocation, updating and overriding, cloning, and aliasing.

Selection and Invocation

This operation has two forms:

  1. a.x
  2. a.x(b1, ..., bn)

The first form selects the value from the field x while the second form invokes the method y with zero or more arguments. Additionally, Obliq allows for using the first form for method invokation if the method takes zero objects.

If a value field is located in a remote object, then that value of that field is sent over the network. If a method field is invoked in a remote object, then the arguements to that object are sent over the network. Once the computation is completed (or failed), the result (or error) is sent back over the network.

Updating and Overriding

This operation has one form:

  1. a.x := b

If the field x is a value field, then x is updated to the new value. If the field x is a method field, then x is rebound to the new method b. If a is a remote object, then these changes are transmitted over the network. For methods, this includes any values captured inside the closure.

Cloning

This operation has one form:

  1. clone(a1, ..., an)

When clone receives one argument, it return a copy of the given object. When given two or more items, those objects are copied into a singular object. This merge operation can fail if there are conflicting names. A common construct to perform inheritance is clone(a, {...}). Finally, if the cloned objects contain network references, those values my be retreated from across the network.

Aliasing

This operation has one form:

  1. a.x := alias y of obj end

Aliasing provides a way to redirect operations on a field to another object. Aliasing a method overrides it with an indirect method call:

x => meth(s, z) b.y(z) end

Obliq additional provides the following construct to alias all fields of an object to another:

redirect a1 to a2 end

In typical prototype delegiation, the context of self is bound to the initial object. However, alias are bound to the object which the alias points to. For remote objects, this has the advantage of preforming all operations within the object's local site. Thus, reducing network operations.

Protected Objects

{ protected, x1 => a1, ..., xn => an }

Protected objects are objects that are guarded from external change. They are free to modify and clone themselves internally, but no outside observer can. Protection is applied to the entire object to prevent cloning.

Serialized Objects

{ serialized, x1 => a1, ..., xn => an }

Serialized objects are a mechanism to prevent race condition with distrubted programs. Code can run cuncurrently in remote context and locally. Thus serialized objects provide a system of controlling access via mutices. Serialized objects allow internal access to run without blocking upon re-entry, but prevents exteran access to re-enter.

Obliq additionally, provides the watch statement:

watch condition until guard end

watch will wait on a condition to be signal by some other code. Additionally, it can only be used inside a serialized object. When the condition is signaled, the guard statement will be executed. If that condition return true, then the current thread locks the mutex of its current context. If that condition returns false, then the thread waits on condition until it is signal again.

Further Reading

These feature cover some of the core concepts within Obliq. Further detail on Obliq can be found in "A Language with Distributed Scope".

Visual Obliq

An overview of Visual Obliq

Visual Obliq was a programming enviroment for using Obliq to build distrubted graphical applications. It's goal was to make building distrubted applications as easy as local single-user applications [8]. It provided a interface building based on Microsoft's Visual Basic [4].

Visual Obliq programs were transmitted over the web using an extenion to HTTP. The interface builder would bundle applications into a single file that was transmissible over a network connection. A gate-way program would handle initiating sessions when a hyperlink to an application was selected. a MIME header would indicate the returned response was a Visual Obliq application. [4]

Migratory Application

Visual Obliq was designed to enable the idea of migratory applications. Migratory application are GUI programs capable of moving from host to host while preservering their state. This idea was constructed to enable applications to handle the demands of mobile and distrubted users.

The Motivation of Migration

The core use case of migratory applications was to allow the user to move from system to system. Send applications from home to work to a colleague's machine. Additionally, it could allow low end-system to move application in and out of the system to a larger pool of distributed resources. [5]

Migrating an Application

When an application is migrated, the interface is saved to a check point. The hierachy of widgets is traversed and state is copied from the UI tookit into the widget. Only user modifiable state needs to be saved. State controlled by the application exclusively is already holding the latest information.

This state must then be rebuilt on the remote system. The widget hierachy is re-constructed within the local toolkit of the remote system. The shape of widgets may change during migration. One such reason is to account for a "portable computer" with smaller screen space. This provides flexiblity while preserver the application interface as much as possible. [5]

Migrating local resources such as file-handers and network connections could be trouble some. These resouces must be handled manually as there is no clear way to handle there resources. For example, two remote systems may not have access to a shared file-system.

Application Security

Visual Obliq's runtime restricted a network application's ability to access the user's hardware. The runtime remove unsafe commands that access the underlying system. There commands are substitued with safe alternative, that require premission to operate.

An image showing an attempt to run the command processNew. Next to that there is a permission file showing what is allowed. Finally, multiple arrows point outwards from the command showing the three possible outcomes: getting blocked, allowed to run, or having to prompt the user.
An example of safe routines in visual obliq

A user-specified configuration file controls the permission of the external program. The op-codes and parameterare varified against this configuration file (.vorestrict) to determin if it is allowed. When a forbidden action is attempted, the program will be terminated and the user will be notified. When an action is neither blocked nor allowed, the user will be prompted for permission to preform it.

A Demonstration of Visual Obliq Applications

Sources

  1. Distributed Applets
      Marc A. Najork and Marc H. Brown. 1997
  2. "Collaborative Active Textbooks: A Web-Based Algorithm Animation System for an Electronic Classroom"
      Marc H. Brown and Marc A. Najork. 1996.
  3. "Visual Obliq: A System for Building Distributed, Multi-User Applications by Direct Manipulation"
     Krishna Bharat and Marc H. Brown. 1995.
  4. "DISTRIBUTED APPLICATIONS IN A HYPERMEDIA SETTING"
      Krishna Bharat and Luca Cardelli. 1995.
  5. "MIGRATORY APPLICATIONS"
      Krishna Bharat and Luca Cardelli. 1995.
  6. "Obliq-3D: A High-Level, Fast-Turnaround 3D Animation System"
      Marc A. Najork and Marc H. Brown. 1995.
  7. "A Language with Distributed Scope"
      Luca Cardelli, 1995
  8. "Building a Distributed Application Using Visual Obliq"
      Krishna Bharat, Marc H. Brown. 1995