core.parallel: one slot per lane, with no ordering between the lanes
(ADR-0002 decision 10).
The second config-parameterized type. config carries an ordered
"lanes" list of bare lane names, and each lane name becomes the slot
"lane_" <> name:
config = %{"lanes" => ["capture", "receipt"]}
slots(config)
#=> [{"lane_capture", :any, "capture"}, {"lane_receipt", :any, "receipt"}]A lane stores its bare name and the slot prefixes it, where
StatifierBlocks.Core.Branch's arms store the whole slot name. The
asymmetry is not this type's choice: it is what the ADR-0001 worked
example stores, and the stored bytes win over any tidier scheme.
Lane slots are :any - a declared-but-empty lane is an ordinary
intermediate state, not a finding - and the order of the lanes in
config is presentation order only. Nothing about a parallel block gives
its lanes a sequence; that is the whole point of it, and it is why
palette_entry/0 declares layout: :columns so the lanes render side by
side (ADR-0005 decision 10).
produces is :unknown for the same reason core.branch's is: joining
the lanes' outputs is a type lattice, and ADR-0003 decision 4 refuses to
build one.
Summary
Functions
A compound state wrapping one <parallel> whose regions are the lanes
(ADR-0004 decision 2), each region sequencing its own steps and finishing
at its own <final>.
One :any slot per well-formed lane, in config order.
Functions
A compound state wrapping one <parallel> whose regions are the lanes
(ADR-0004 decision 2), each region sequencing its own steps and finishing
at its own <final>.
<state id="s_PAR" initial="s_PAR__run">
<transition event="done.state.s_PAR__run" target="s_PAR__done"/>
<parallel id="s_PAR__run">
<state id="s_PAR__lane_capture" initial="...">...<final id="s_PAR__done_lane_capture"/></state>
<state id="s_PAR__lane_receipt" ...>
</parallel>
<final id="s_PAR__done"/>
</state>A <parallel> is done when every region is, so the outer state needs one
transition and no join logic of its own.
The two role families are lane_<name> and done_lane_<name>. They
cannot collide with each other whatever a lane is called, because they
differ in their first token rather than their last - a lane named
capture_done mints lane_capture_done and done_lane_capture_done, and neither is
any other lane's id.
A parallel with no lanes emits no <parallel> at all: an empty one is
not valid SCXML, and "run nothing concurrently" is done the moment it
starts, so the block compiles to a state whose initial is its <final>.
One :any slot per well-formed lane, in config order.
Total for any config: a lane name that could not make a usable slot name is skipped rather than raised on, keeping ADR-0002 decision 6's stability rule true mid-edit.