Skip to content
Sébastien Doeraene edited this page Feb 14, 2013 · 1 revision

Reflective layer

Mozart 2 comes with what we called a reflective layer, which enables to extend the system in Oz. It was initially designed to support the implementation of the Distributed Subsystem (DSS) entirely in Oz, but it can be used for other purposes.

This page gives a documentation of the reflective layer.

API

The API of the reflective layer is currently available through the boot module x-oz://boot/Reflection. This module defines the following procedures:

{Reflection.newReflectiveEntity ?Stream ?Entity}

Creates a reflective entity Entity associated with the stream Stream. See below for an explanation of what is a reflective entity.

{Reflection.newReflectiveVariable ?Stream ?Variable}

Creates a reflective variable Variable associated with the stream Stream. See below for an explanation of what is a reflective variable.

{Reflection.bindReflectiveVariable Variable Value}

Effectively binds the reflective variable Variable to the value Value. See below.

{Reflection.getStructuralBehavior X ?Y}

Binds Y to an atom representing the structural behavior of the entity X. The possible values are:

  • value: X is a value. Values are compared by value, and have an atomic structure from unification's point of view. Examples: integers, booleans, atoms.
  • structural: X is a structure. Structures are compared by value, but are not atomic from unification's point of view. Examples: records, tuples, conses.
  • token: X is a determined entity with token behavior. Tokens are compared by reference. Examples: cells, names, objects.
  • variable: X is a variable, or more generally a transient. Most operations wait on transients. Transients are meant to become something else later through binding. Examples: variables, read-only's, failed values.
{Reflection.become X Y}

Make the token- or variable-behaved entity X become Y. Afterwards, X and Y are indistinguishable. They became the same node in memory. The entity previously held by X is discarded, and only Y remains. Any other reference to X in the system is "redirected" to Y.

X must not have value or structural behavior for this operation to succeed (because it plainly does not make sense). Note that Y may have any behavior.

Example:

local X Y in
   X = {NewCell 5}
   Y = {NewName}
   {Show @X}                % 5
   {Show X == Y}            % false
   {Reflection.become X Y}
   {Show X == Y}            % true
   {Show @X}                % type error! X is a name
end

Reflective entities by example

A reflective entity created by Reflection.newReflectiveEntity is an Oz entity that forwards any low level operation (aka, builtin) on it into a message sent on the associated stream. Let us start with an example, that you can replay in the OPI.

declare Reflection S C in
[Reflection] = {Link ['x-oz://boot/Reflection']}
{Reflection.newReflectiveEntity ?S ?C}
{Browse S}

At this point the browser displays _<future>, which indicates that S is a read-only variable. This is exactly the same as if we had created a port instead of a reflective entity.

Now let us apply some builtin operation on the reflective entity, like this:

{Assign C 5} {Browse completed}

We ask the browser to display completed so that we know when the Assign call is completed. You can observe that currently, the browser does not display completed, but it shows that the stream has received one element:

assign(5)#_|_<future>

The primitive Assign operation corresponds to a message assign(X) where X is the rhs of the assignment. The second item in the #-tuple is an acknowledgment to be filled by the reflective entity driver. Let us bind it to unit by hand:

S.1.2 = unit

Observe that this triggers the display of completed. This highlights the fact that Assign was waiting for this ack to be bound before continuing.

The same is true for any primitive operation. It will send a #-tuple with two elements: a message representing the operation and its arguments, and an acknowledgment. The primitive operation waits for this acknowledgment to be bound to unit before continuing (note: it must unit, not another value - see later).

TODO ...