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

Validation pipeline for ExDatalog programs.

Validates a program in two stages:

- **Phase 1 (structural)**: Checks relation references, arity consistency,
  and term validity. Runs on every `validate/1` call.

- **Phase 2 (semantic)**: Checks variable safety, range restriction,
  wildcard-in-head, constraint binding, and stratified negation. Runs on
  every `validate/1` call after Phase 1 succeeds.

All errors are collected (not short-circuited) so callers see the full
picture. Returns `{:ok, program}` on success or `{:error, [errors]}` on
failure.

## Examples

    iex> alias ExDatalog.{Program, Validator}
    iex> program = Program.new() |> Program.add_relation("edge", [:atom, :atom])
    iex> Validator.validate(program)
    {:ok, %ExDatalog.Program{}}

# `validate`

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

Runs the full validation pipeline (structural + semantic) on a program.

Returns `{:ok, program}` on success, or `{:error, [%Error{}]}` with all
accumulated errors on failure.

The returned program is the **same struct** that was passed in — list order
of `facts` and `rules` is not modified. The builder API prepends for O(1)
per-call cost, so `facts` and `rules` are in reverse insertion order (newest
first). This is normalized internally during compilation.

Calling `validate/1` is idempotent: `program == elem(validate(program), 1)`.

---

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