# `ExDatalog.Engine.Binding`
[🔗](https://github.com/thanos/ex_datalog/blob/v0.5.0/lib/ex_datalog/engine/binding.ex#L1)

Binding environment for Datalog rule evaluation.

A binding maps variable names (strings) to ground values. During rule
evaluation, each body atom extends the binding by matching tuple values
against atom terms. Constraints filter or extend bindings further.

## Types of resolution

- **Variable** (`{:var, "X"}`) — looked up in the binding. If absent, the
  variable is unbound and the constraint/atom cannot be evaluated.
- **Constant** (`{:const, {:int, 42}}`, `{:const, {:atom, :alice}}`, etc.) —
  resolved to the native Elixir value.
- **Wildcard** (`:wildcard`) — matches any value without binding.

## Merge semantics

When joining two atoms that share variables, two bindings are merged. For
shared variables the values must agree; otherwise the merge fails and the
candidate tuple is discarded.

# `t`

```elixir
@type t() :: %{required(String.t()) =&gt; term()}
```

# `bind`

```elixir
@spec bind(t(), String.t(), term()) :: t()
```

Binds a variable to a value in the environment.

## Examples

    iex> ExDatalog.Engine.Binding.bind(%{}, "X", :alice)
    %{"X" => :alice}

    iex> ExDatalog.Engine.Binding.bind(%{"X" => :alice}, "Y", :bob)
    %{"X" => :alice, "Y" => :bob}

# `consistent?`

```elixir
@spec consistent?(t(), t()) :: boolean()
```

Checks whether two binding environments are consistent on shared variables.

Returns `true` if every variable present in both bindings has the same value,
`false` otherwise.

## Examples

    iex> ExDatalog.Engine.Binding.consistent?(%{"X" => 1}, %{"X" => 1, "Y" => 2})
    true

    iex> ExDatalog.Engine.Binding.consistent?(%{"X" => 1}, %{"X" => 2})
    false

    iex> ExDatalog.Engine.Binding.consistent?(%{"X" => 1}, %{"Y" => 2})
    true

# `empty`

```elixir
@spec empty() :: t()
```

Creates an empty binding environment.

## Examples

    iex> ExDatalog.Engine.Binding.empty()
    %{}

# `get`

```elixir
@spec get(t(), String.t()) :: {:ok, term()} | :error
```

Looks up a variable in the binding environment.

Returns `{:ok, value}` if bound, `:error` if not.

## Examples

    iex> ExDatalog.Engine.Binding.get(%{"X" => :alice}, "X")
    {:ok, :alice}

    iex> ExDatalog.Engine.Binding.get(%{"X" => :alice}, "Y")
    :error

# `ir_value_to_native`

```elixir
@spec ir_value_to_native(ExDatalog.IR.ir_value()) :: term()
```

Converts an IR value tag to its native Elixir value.

Used internally by `resolve/2` and by the evaluator for fact conversion.

## Examples

    iex> ExDatalog.Engine.Binding.ir_value_to_native({:int, 42})
    42

    iex> ExDatalog.Engine.Binding.ir_value_to_native({:str, "hello"})
    "hello"

    iex> ExDatalog.Engine.Binding.ir_value_to_native({:atom, :alice})
    :alice

# `merge`

```elixir
@spec merge(t(), t()) :: {:ok, t()} | :conflict
```

Merges two binding environments.

For shared variables, the values must be equal (using `==/2`). If any
shared variable disagrees, returns `:conflict`. Otherwise returns
`{:ok, merged_binding}`.

## Examples

    iex> ExDatalog.Engine.Binding.merge(%{"X" => 1}, %{"Y" => 2})
    {:ok, %{"X" => 1, "Y" => 2}}

    iex> ExDatalog.Engine.Binding.merge(%{"X" => 1}, %{"X" => 1, "Y" => 2})
    {:ok, %{"X" => 1, "Y" => 2}}

    iex> ExDatalog.Engine.Binding.merge(%{"X" => 1}, %{"X" => 2})
    :conflict

# `resolve`

```elixir
@spec resolve(t(), ExDatalog.IR.ir_term()) :: {:ok, term()} | :unbound | :wildcard
```

Resolves an IR term to a native Elixir value using a binding environment.

- `{:var, name}` — looks up in binding. Returns `{:ok, value}` if bound,
  `:unbound` if not.
- `{:const, ir_value}` — returns `{:ok, native_value}` unconditionally.
- `:wildcard` — returns `:wildcard` (matches anything, cannot be resolved).

## Examples

    iex> ExDatalog.Engine.Binding.resolve(%{"X" => 42}, {:var, "X"})
    {:ok, 42}

    iex> ExDatalog.Engine.Binding.resolve(%{}, {:var, "X"})
    :unbound

    iex> ExDatalog.Engine.Binding.resolve(%{}, {:const, {:int, 10}})
    {:ok, 10}

    iex> ExDatalog.Engine.Binding.resolve(%{}, {:const, {:atom, :alice}})
    {:ok, :alice}

    iex> ExDatalog.Engine.Binding.resolve(%{}, :wildcard)
    :wildcard

---

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