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.
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.
Circuit programs recognize the following types of gate values:
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.
When the gate value is a directive, materialization proceeds as follows:
@
, the gate is materialized as a noun gate
emitting the target value.*
, 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.
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.
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.
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.
One can materialize (i.e. execute) a program circuit given an index from three different places.
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.
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.
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"