The DSL compile pipeline over the flat Cell IR — the resolve→lower→validate
machinery both host DSLs share, parameterized by app hooks so each keeps its
own domain vocabulary.
A host compiles by handing compile/2 its named roots (each a {id, node}
where node is a nested op-expression in the host's own node structs) plus a
hooks map:
the
Loweringcallbacks (classify / legs / leg_id / ref_id / to_cell) — how to walk a node into cells.ref_idis where BY-NAME resolution lives: a ref returns the id of the node it points at (the portal's register faces resolveref(:people, role: :rows)→"reg:people/rows"). No object inlining, no shared-identity dedup.validate(optional) —(cells -> :ok | {:error, message})for DOMAIN checks the substrate can't know (the portal's guarantee/scenario/addresses id checks). Runs after the structural checks below.
compile/2 lowers every root via Lowering.walk, unions the cells (a shared
node appears once — it's a named root; refs are edges; a walk yielding the
same id twice is DEDUPED, first wins), then validates:
- structural — every input/ref names a real cell; acyclic (delegated to
Graph.build, which raises on a dangle/cycle). The duplicate-id check bites only onvalidate_cells/2's hand-built lists —compile/2has already collapsed duplicates by design. - domain — the host's
validatehook.
Returns {:ok, cells} or {:error, message}; a host transformer turns an
error into a compile-time Spark.Error.DslError.
Summary
Functions
Validate an ALREADY-assembled cell list (for a host that builds cells itself
rather than handing op-expression roots): structural checks (unique ids +
inputs resolve + acyclic) then the optional domain hook. {:ok, cells} |
{:error, message}.
Types
@type hooks() :: %{ :lowering => ReactiveDag.Lowering.callbacks(), optional(:validate) => (list() -> :ok | {:error, String.t()}) }
Functions
@spec validate_cells([term()], (list() -> :ok | {:error, String.t()}) | nil) :: {:ok, [term()]} | {:error, String.t()}
Validate an ALREADY-assembled cell list (for a host that builds cells itself
rather than handing op-expression roots): structural checks (unique ids +
inputs resolve + acyclic) then the optional domain hook. {:ok, cells} |
{:error, message}.