# `Rupa.IR`
[🔗](https://github.com/zero-one-group/rupa/blob/v0.1.0/lib/rupa/ir.ex#L1)

The intermediate representation: what the staging pass turns a schema into.

A schema says what you meant. The IR says what the decoder will do, in the order it will do
it, with everything the schema only implied made explicit:

  * refs are resolved — a ref that is not on a cycle is replaced by the definition itself,
    so the decoder never looks anything up; only genuinely recursive refs stay as nodes, and
    those live in a table beside the tree
  * an object's fields become an ordered list, each with the wire key it arrives under, the
    one it leaves under, the key it takes in the decoded map, whether it is required, and
    what it defaults to — so `rename_all:`, `from:`, `to:` and `keys:` are all spent here
  * `into:` stays a bare module name on the object, checked against that module's
    `defstruct` while staging, so a backend builds the struct without asking anything
  * a scalar's constraints become an ordered list of checks
  * `enum` and `literal` become one lookup table from wire value to decoded value
  * a tagged union becomes a table from tag string to branch, with the decoded tag atom
    interned here and never from wire data

Nothing here is a runtime artifact: a `pattern` is still its source string, not a compiled
regex, because the module backend has to embed these nodes in generated code. Compiling the
regex is the backend's job.

Both backends consume this, which is the point: a feature is written once. `Rupa.explain/1`
prints it, so what you read is what runs, whichever backend you are on.

# `program`

```elixir
@type program() :: %{root: t(), defs: %{required(atom()) =&gt; t()}}
```

A staged schema: the root node, plus the definitions that recursion needs.

# `t`

```elixir
@type t() ::
  Rupa.IR.Scalar.t()
  | Rupa.IR.Const.t()
  | Rupa.IR.Object.t()
  | Rupa.IR.Array.t()
  | Rupa.IR.Fixed.t()
  | Rupa.IR.Dict.t()
  | Rupa.IR.Nullable.t()
  | Rupa.IR.Union.t()
  | Rupa.IR.Tagged.t()
  | Rupa.IR.Ref.t()
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
