Equivalence check.
See Node.opIndex.
Semantic hash. Depends only on channel lengths.
Provides an iterator over this node's in-edges.
Provides an iterator over this node's out-edges.
Frees all resources allocated by this node and sets it to an uninitialized state.
Initializes a join node, must be later disposed.
Non-empty collection of channels, each containing zero or more of this node's parameters (either data or memory edges).
Control flow edge into the join node's body.
This join node's definition (a data slot), used to instantiate and invoke it.
Post-move adjusts in-edge slots' owner pointer.
Join nodes are used to define the (external) interface and (internal) contents of procedures and basic blocks. They interact with the outside world through zero or more parameters. As a join node begins to execute, control flows into its body, where all of its parameters are made available. Therefore, a join node behaves like the entry block of a CFG, but with a collection of SSA phis (one for each parameter); so it can be used as an extended basic block. RULE: Gyre graphs can be cyclic, but only if every cycle goes through a join node. This is similar to having a DFG with SSA phis, in which data-flow can still be considered causal as long as every cycle goes through one or more phi nodes to indicate a "temporal" control-flow dependency.
Since join nodes define blocks/subprocedures, one may want to know where such a definitions begins and ends. A join node's scope begins with all of its parameters and control flow edges. Furthermore, whenever another node is connected to part of a join node's scope, it also becomes part of that scope. In other words: a join node's scope is implicitly defined by the set of nodes which (a) are transitively reachable by control flow in its body or (b) have a transitive dependency on any one of its parameters. This idea comes from Thorin's implicit scopes. RULE: Two scopes cannot intersect unless one is a strict subset of the other.
The only way in which a Gyre subgraph may refer to a join node without becoming part of its scope is through an indirection: the join node's "definition" edge. Through its definition, external code may instantiate and invoke a join node. Since a join node's body may use any of its parameters, it can only begin executing when they were all provided by the calling code. Furthermore, parameters are divided into (one or more) groups, called channels. All parameters within a channel need to be provided at the same time, but each channel can receive its inputs from a different source in the calling code. Thus, join nodes can also be used to merge concurrent control flows, which should not be surprising to those familiar with the join calculus: join nodes correspond to linear join patterns.
Gyre's main mechanism for procedural abstraction, the join node.
Join nodes can be used as procedures, basic blocks or synchronization points.