Escher A language for connecting technologies using pure metaphors

Programs and materialization

Materialization is the process of creating and executing a system of interconnected reflexes, wherein the system is specified by a circuit called a program.

Materialization takes as input an index (of circuit programs and other reflex materializers) and a circuit program to materialize. The result of materialization is the creation and execution of the system of reflexes described by the circuit program, as well as a residual value.

Circuit programming

A program circuit describes a system of interconnected reflexes.

Each circuit gate corresponds to a reflex. The gate value describes the type of reflex that is to be materialized. While the gate name is merely an identifier, unique to the program circuit, used mainly to enable the specification of the reflex-to-reflex links. The relation between gate values and materialized reflexes is explained later.

In a valid program circuit, a gate whose name is the empty string must not be defined. The empty-string gate is reserved for the super gate, which (detailed later) designates an “enclosing” circuit.

The circuit program's links connect pairs of reflex-valve endpoints. Links are allowed either between two gates defined within the circuit, or between a defined gate and the super gate.

Links connected to the super gate are endpoints whose eventual connection to a reflex is deferred to the enclosing circuit.

Circuit programs that have no links to the super gate are called closed circuits, as they describe complete materializable systems on their own.

On the other hand, circuit programs that have links to the super gate can only be materialized as reflexes within higher-level enclosing circuits.

Gate value interpretation

Circuit programs recognize the following types of gate values:

  1. Integer
  2. Float
  3. Complex
  4. String
  5. Circuit (non-directive)
  6. Directive circuit

Noun reflexes

Gate value types 1 to 5 will result in the materialization of a “noun” reflex, whose noun value is the gate value.

A noun reflex is a generic, built-in reflex type, which — after materialization — emits its corresponding gate value to each one of its connected valves. If no valves are connected, the noun reflex leaves the gate value as its residue. Otherwise, it leaves no residue.

Expanding directives

When the gate value is a directive, materialization proceeds as follows:

  1. The runtime looks up the “target” value, which resides in the index at the address specified in the directive.
    • If the directive verb is @, the gate is materialized as a noun gate emitting the target value.
    • If the directive verb is *, the target value is substituted as the gate value, and the materialization process described in this section is repeated now with the target value as the gate value.

Circuit residue

As pointed out in the section on reflexes, every reflex can leave a residue value as a result of being materialized, or the Go value nil, which indicates leaving no residue.

Circuit programs are no different than reflexes (in fact they describe higher-order reflexes themselves) in that they leave a residue value as well.

The residue of materializing a circuit program is the same circuit, wherein each gate value is replaced by the residue of materializing that gate. Gates corresponding to reflexes that leave no residue are not present in the residue circuit.

If no gates leave any residue, the circuit program itself leaves no residue.

Example with an illustration

Consider, for instance, the following index:

{
	Database {
		cache Cache
		shard1 Shard
		shard2 Shard
		link Link

		cache:Web = :Web
		shard1:Cache = cache:Left
		shard2:Cache = cache:Right
		shard1:Backup = link:Left
		shard2:Backup = link:Right
		link: = :Backup
	}
	App {
		web Web
		db1 Database
		db2 Database
		bkp Backup

		db1:Web = web:Left
		db2:Web = web:Right
		db1:Backup = bkp:Left
		db2:Backup = bkp:Right
	}
	Web …
	Cache …
	Shard …
	Link …
}

Here App and Database are program circuits and their symbolic representation is shown below. Whereas assume that Web, Cache, Shard and Link (whose definition is not given in this listing) are reflex materializers.

If we materialize the program circuit App with respect to the index given above (i.e. directive addresses will resolve with respect to that index), we are going to get the following residue:
{
	web WebResidue
	bkp BackupResidue
	db1 {
		shard1 Shard1Residue
		shard2 Shard2Residue
		cache CacheResidue
		link LinkResidue

		cache:Web = :Web
		left:Cache = cache:Left
		right:Cache = cache:Right
		left:Backup = link:Left
		right:Backup = link:Right
		link: = :Backup
	}
	db2 {
		shard1 Shard1Residue
		shard2 Shard2Residue
		cache CacheResidue
		link LinkResidue

		cache:Web = :Web
		shard1:Cache = cache:Left
		shard2:Cache = cache:Right
		shard1:Backup = link:Left
		shard2:Backup = link:Right
		link: = :Backup
	}
	db1:Web = web:Left
	db2:Web = web:Right
	db1:Backup = bkp:Left
	db2:Backup = bkp:Right
}

Where WebResidue, BackupResidue, Shard1Residue, etc. are merely placeholders here for whatever the actual residue values of the respective reflexes are. Visually the program residue could be represented as:

The actual executed system of interconnected reflexes which results from the materialization can be visualized like so:

This illustration does not correspond to a circuit data structure anywhere in the runtime. It is merely an illustration of the executed reflexes and their runtime connections.

Three ways to invoke materialization

One can materialize (i.e. execute) a program circuit given an index from three different places.

Materializing from Go

Package be provides the materialization method:

func MaterializeSystem(program interface{}, index, barrier Circuit) (residue interface{})

Argument program contains the program circuit — of Go type Circuit — that is to be materialized. Incidentally, the value of program can be any value recognized as a gate value in a circuit program as described earlier. Often, one will pass a directive circuit as program.

Argument index holds the materialization index, relative to which directive addresses are interpreted.

The last argument, barrier, is to be set to nil.

The function returns the residue of the materialization process.

Materializing from within Escher

One can recursively materialize circuits programs from within other circuit programs. This is accomplished using the built-in reflex e.Materialize which is described in the materialization faculty section.

Materializing from the command-line

The Escher executable, which is explained in detail in the runtime section, will materialize a directive from the command-line. Given our index (project source root) is "/src/app/", and in one of the "*.escher" files in that directory we have a gate named "Main", we can materialize it from the command-line like this:

escher -src /src/ "*app.Main"