ReactiveDag.Dsl (reactive_dag v0.16.0)

Copy Markdown View Source

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 Lowering callbacks (classify / legs / leg_id / ref_id / to_cell) — how to walk a node into cells. ref_id is where BY-NAME resolution lives: a ref returns the id of the node it points at (the portal's register faces resolve ref(: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:

  1. 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 on validate_cells/2's hand-built lists — compile/2 has already collapsed duplicates by design.
  2. domain — the host's validate hook.

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

hooks()

@type hooks() :: %{
  :lowering => ReactiveDag.Lowering.callbacks(),
  optional(:validate) => (list() -> :ok | {:error, String.t()})
}

root()

@type root() :: {String.t(), term()}

Functions

compile(roots, hooks)

@spec compile([root()], hooks()) :: {:ok, [term()]} | {:error, String.t()}

validate_cells(cells, domain_validate \\ nil)

@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}.