Format of STEP XML documents:
This section details the valid nodes, attributes, and relations for these nodes in a STEP document. The following example may be useful in following this document
STEP Programming Example 1:
Some attributes are meaningful for every kind of STEP node. Specifically:
The id is attribute is a locally unique, opaque identifier string; no
two nodes in a single STEP program should have the same ID. The STEP
root element (stepgraph)has an id attribute that represents the program
ID. Thus, each node has both a program ID and node ID that, when
taken together form a globally unique ID (GUID). IDs are used to
identify particular nodes to SXEs and SSDs as targets for splicing and
grafting and as part of the URIs (addresses) through which nodes
communicate with each other while in-evaluation.
The bindto attribute, when present, gives the URI of a particular SXE
that this node is to be bound to. This can be used when
submitting a program to the SSD to force it to bind certain nodes to
certain Sensorium elements.
A stepgraph is always the root node of a STEP file and it has a
required attribute “id” . It is a convenience that
specifies the ID of the program, with this program ID inherited by all
child nodes. All child nodes (except snobjects) have a globally
unique ID (GIUD) determined by the concatenation of the program ID with
the node ID. The stepgraph node has zero or more non stepgraph
nodes as children. A stepgraph node may only occur as the root
node of the document and should never occur elsewhere.
These represent calls to primitive functions (addition, string
concatenation, image manipulation, etc) to be executed by the SXE on
which this node will be deployed. Each identifies a
function/operation via its single, mandatory opcode attribute, the
arguments to which are the values of (or values produced by) the node's
children. Has zero or more children, depending upon the number of
operands the named function takes. The opcode attribute
specifies a specific Java class file found on the SXE that extends the
FunctionWrapper class and implements a method Call. More
information can be found in the section “implementing your own
opcodes” later in the document.
Understanding trigger nodes:
These specify a repetition for “semi-persistent” and
“persistent” query evaluation. They have at least two
children: the predicate, the body. Three specific forms exist
specifying that the children of this node will be evaluated repeatedly
given the following considerations:
The predicate subtree will be evaluated continually until it evaluates
to true. Once the predicate evaluates to true, the body is
evaluated exactly once and is never evaluated again. The value of
the trigger will become the value derived from the evaluation of the
body. If the body is not yet evaluated, the value of this node is
The predicate subtree will be evaluated continually. Every time
the predicate evaluates to true, the the body is evaluated. The value
of the trigger will become the value derived from the evaluation of the
body or “NIL” before the body has been evaluated.
The predicate subtree will be evaluated continually. Each time
the predicate value changes such that it evaluates to true, the the
body is evaluated. In essence, the body is only evaluated when
the predicate evaluation changes to true from false (i.e., the
“edge” of a clock). The value of the trigger will
become the value derived from the evaluation of the body or
“NIL” before the body has been evaluated.
This node must be a descendant of a trigger and is a “peek”
at the current value the trigger specified by its mandatory attribute
“target” (the value of the attribute is the ID of that
trigger). This allows a programmer to emulate an iterative call
that is “cycle safe”. In execution, the
last_trigger_eval will have either a value of NIL (indicating that the
trigger has not yet evaluated its body or its body's evaluation has
resulted in a NIL) or some other value produced at the predicate.
The use of a last_trigger_eval makes sense in either the predicate or
the body. For example, the predicate may check the
last_trigger_eval to see if its NIL (indicating the first pass) or
perhaps if the computation is complete. The body will naturally
be used to, say, increment the last value.
STEP Programming Example 2:
These nodes regulate access to the values produced by trigger nodes by
making explicit the semantic for how the transient trigger value should
be read temporally. They have exactly one child, a single trigger
node. The mandatory attribute, “opcode” may have one
of the values “block”, “nonblock” or
Specifying a ``non-blocking'' read to a trigger requests the read
immediately return the result of the last completed evaluation of
the trigger's target expression. A non-blocking read will block
if and only if the target expression has never completed an
evaluation. A ``blocking'' read waits until the next (or
currently ongoing) evaluation of the target expression completes,
then produces that value. Finally a ``fresh'' read waits for a
complete re-evaluation of the trigger's predicate and target and
produces that value.
A const node is used to block further descent into a tree after an
initial evaluation. They are used to block re-evaluation of their
children after they have been evaluated exactly once (e.g., a SNAFU a
letonce binding). A const node has exactly one child,
representing the root of the subgraph whose evaluation is limited to
exactly one evaluation. These nodes only make sense as the
descendants of triggers. These nodes are inserted by the SNAFU
compiler in the case of a letonce binding. In practice, this node
reflects the subtle complexity of programming directly in STEP.
They are references to other nodes such that two nodes may share the
same (literally, the same) child node. As STEP graphs are
supposed to be cycle free, misplaced splice nodes are dangerous!
In practice a splice node may be generated as a compilation of a
“let” construct in SNAFU (e.g., let X = ..). They
also may be used by the SSD to describe how a partial STEP graph should
be spliced onto another (for reuse). Splice nodes allow independently
compiled STEP graphs to share common components. Specifically, after a
STEP graph has been deployed to a given SXE, another program may be
admitted by the SSD to that SXE so as it would share part of the
already-deployed STEP graph to re-use those computations as appropriate.
The splice node must have a “target” attribute whose value
must be the id of another node. Splice nodes are only represented
in serialized STEP files; when loaded into memory the edge to the
splice node is instead connected to the targeted node. Since
STEPs should be DAGs (cycle-free) the splice target should not be
farther up the tree if it causes a cycle to occur.
These nodes provide communication between SXEs over a loosely-coupled
network. These nodes are rarely present in the STEP files
produced by compilers; they are injected into STEP DAGs by the SD to
allow it to distribute an expression's evaluation across multiple
SXEs. In execution, these nodes effectively allow the data
transferred over an edge to span physical resources.
A socket has a required attribute “role” that specifies the
node as either a “sender” or “receiver”.
A receiver has no parents, and a sender has no children. A socket
cannot be both a sender and a receiver, because the semantics of its
attributes are dependent upon this distinction. Such operation
can be simulated with a two-node graph connecting one receiver with one
sender; we call this construct a rendezvous or relay node. A
receiver will pass the value from the sender further up the
graph. A sender node will take the value from child and send this
value across the network.
The protocol attribute determines which protocol model this socket uses
to communicate. Currently supported models are GET (HTTP/1.1
pull) and POST (HTTP/1.1 push). We also envision UDP, serial
port, and sensor-net-oriented protocols being added. The peeruri
attribute binds the communications to a particular (logical or
physical) address (traditionally this is the URI of the node of
interest) and the peerid attribute specifies the id of the node on the
peer's side, used for internal sanity-checking.
|<socket id="8081:in" protocol="POST" role="receiver"
|<socket id="8080:out" protocol="POST" role="sender" peerid="8081:in"
The value node wraps some constant value in the STEP program. It
associates an ID with some strongly typed snObject. It contains a
The snobject is a node without an id. The snobject has a type
attribute specifying the type of the data. Valid types at present
snbench/object (super class)
The values are stored “loose” within the tag, in the case
of string or binary values they are wrapped in CDATA such that binary
values and XML tokens can be stored without loss of data. Valid
values depend on the type of the data. For example, a boolean may
hold either the string “true” or “false”, an
integer may represent any valid whole number, and an image is the CDATA
representation of a PNG formatted image (admittedly, we don't
anticipate a programmer specifying images as constants).
Below are two examples of value/snobject pairs that convey constant
values in some STEP program. The first is the integer value 1,
the second conveys the string “320x240”:
Third STEP Programming Example:
Creation Date: 1/10/06
Last Change: 1/12/06