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 defered 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 values in the first group (integer, float, complex, string or a non-directive circuit) 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. Gate 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 left Shard right Shard link Link cache:Web = :Web left:Cache = cache:Left right:Cache = cache:Right left:Backup = link:Left right:Backup = link:Right link: = :Backup } App { web Web left Database right Database backup Backup left:Web = web:Left right:Web = web:Right left:Backup = backup:Left right:Backup = backup: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 left:Cache = cache:Left right:Cache = cache:Right left:Backup = link:Left right:Backup = link:Right link: = :Backup } left:Web = web:Left right:Web = web:Right left:Backup = backup:Left right:Backup = backup:Right }
Where WebResidue
, BackupResidue
, Shard1Residue
, etc. are
merely placeholders here for whatever the actual residue values of the respetive 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: from Go, from another program circuit (i.e. from Escher) and from the POSIX shell.
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 escher.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:
% escher -src /src/app *app.Main