# `ExDatalog.Compiler`
[🔗](https://github.com/thanos/ex_datalog/blob/v0.5.0/lib/ex_datalog/compiler.ex#L1)

Compiles a validated `ExDatalog.Program` into an `ExDatalog.IR` program.

The compiler transforms the high-level AST (rules, atoms, terms, constraints)
into a deterministic, engine-neutral intermediate representation suitable
for evaluation by any backend that implements `ExDatalog.Engine`.

## Compilation steps

1. **Validate** — calls `ExDatalog.Validator.validate/1` to ensure the
  program is structurally and semantically correct.

2. **Assign strata** — uses `ExDatalog.Compiler.Stratifier` to determine
  which stratum each rule belongs to.

3. **Canonicalize** — sorts relations, facts, and rules into deterministic
  order. Rule IDs are assigned monotonically in canonical order.

4. **Convert** — transforms AST types (`Term`, `Atom`, `Constraint`) into
  IR types (`IRTerm`, `IRAtom`, `IRConstraint`), replacing `{:const, value}`
  with tagged IR values (`{:const, {:int, n}}`, `{:const, {:atom, a}}`, etc.).

The output is a `%ExDatalog.IR{}` struct that is deterministic for a given
input program: compiling the same program twice produces identical IR.

After compilation, the IR is validated against structural invariants:
unique rule IDs, stratum bounds, rule-in-stratum consistency, and
relation reference integrity. Violations raise an error — these indicate
a bug in the compiler, not an invalid program (programs are validated
before compilation).

## Examples

    iex> alias ExDatalog.{Program, Rule, Atom, Term, Compiler}
    iex> program =
    ...>   Program.new()
    ...>   |> Program.add_relation("parent", [:atom, :atom])
    ...>   |> Program.add_relation("ancestor", [:atom, :atom])
    ...>   |> Program.add_fact("parent", [:alice, :bob])
    ...>   |> Program.add_rule(
    ...>     Rule.new(
    ...>       Atom.new("ancestor", [Term.var("X"), Term.var("Y")]),
    ...>       [{:positive, Atom.new("parent", [Term.var("X"), Term.var("Y")])}]
    ...>     )
    ...>   )
    iex> {:ok, ir} = Compiler.compile(program)
    iex> length(ir.rules) == 1 and length(ir.relations) == 2
    true

# `compile`

```elixir
@spec compile(ExDatalog.Program.t()) ::
  {:ok, ExDatalog.IR.t()} | {:error, [ExDatalog.Validator.Error.t()]}
```

Compiles a program into its IR representation.

Returns `{:ok, %ExDatalog.IR{}}` on success, or `{:error, errors}` if
validation fails.

---

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