ExDatalog.IR (ExDatalog v0.2.0)

Copy Markdown View Source

Intermediate representation (IR) types for compiled Datalog programs.

The IR is the engine-neutral output of ExDatalog.Compiler.compile/1. It contains the same information as a validated ExDatalog.Program but in a canonical, deterministic form optimized for evaluation:

  • Rules are sorted by (stratum, relation_name, rule_id).
  • Facts are sorted by (relation_name, values).
  • Relations are sorted by name.
  • Each rule carries its assigned stratum field.
  • Every struct has a serialize/1 function that produces a plain map suitable for logging, debugging, or future serialisation.

IR Type Hierarchy

IRProgram
  +-- relations:  [IRRelation]
  +-- facts:      [IRFact]
  +-- rules:      [IRRule]
  +-- strata:     [IRStratum]
  +-- metadata:   map()

IRRelation    name, arity, types
IRFact        relation, values
IRRule        id, head (IRAtom), body ([IRLiteral]), stratum, metadata
IRLiteral     {:positive, IRAtom} | {:negative, IRAtom} | {:constraint, IRConstraint}
IRAtom        relation, terms ([IRTerm])
IRTerm        {:var, name} | {:const, IRValue} | :wildcard
IRConstraint  op, left, right, result
IRStratum     index, rule_ids, relations
IRValue       {:int, integer} | {:str, String.t} | {:atom, atom}
IRType        :integer | :string | :atom | :any

Summary

Functions

The top-level IR program struct.

Converts an AST atom to an IR atom.

Converts an AST constraint to an IR constraint.

Converts an AST term to an IR term.

Resolves an IR term against a binding environment.

Serializes an IR program to a plain map.

Converts a tagged IR value to its native Elixir representation.

Types

ir_constraint()

@type ir_constraint() :: %ExDatalog.IR.Constraint{
  left: ir_term(),
  op: ExDatalog.Constraint.op(),
  result: ir_term() | nil,
  right: ir_term() | nil
}

ir_literal()

@type ir_literal() ::
  {:positive, ExDatalog.IR.Atom.t()}
  | {:negative, ExDatalog.IR.Atom.t()}
  | {:constraint, ir_constraint()}

ir_term()

@type ir_term() :: {:var, String.t()} | {:const, ir_value()} | :wildcard

ir_type()

@type ir_type() :: :integer | :string | :atom | :any

ir_value()

@type ir_value() ::
  {:int, integer()}
  | {:str, String.t()}
  | {:atom, atom()}
  | {:list, [ir_value()]}

t()

@type t() :: %ExDatalog.IR{
  facts: [ExDatalog.IR.Fact.t()],
  metadata: map(),
  relations: [ExDatalog.IR.Relation.t()],
  rules: [ExDatalog.IR.Rule.t()],
  strata: [ExDatalog.IR.Stratum.t()]
}

Functions

%ExDatalog.IR{}

(struct)

The top-level IR program struct.

from_atom(atom)

@spec from_atom(ExDatalog.Atom.t()) :: ExDatalog.IR.Atom.t()

Converts an AST atom to an IR atom.

from_constraint(constraint)

@spec from_constraint(ExDatalog.Constraint.t()) :: ir_constraint()

Converts an AST constraint to an IR constraint.

from_term(arg1)

@spec from_term(ExDatalog.Term.t()) :: ir_term()

Converts an AST term to an IR term.

Examples

iex> ExDatalog.IR.from_term({:var, "X"})
{:var, "X"}

iex> ExDatalog.IR.from_term({:const, 42})
{:const, {:int, 42}}

iex> ExDatalog.IR.from_term({:const, :alice})
{:const, {:atom, :alice}}

iex> ExDatalog.IR.from_term({:const, "hello"})
{:const, {:str, "hello"}}

iex> ExDatalog.IR.from_term(:wildcard)
:wildcard

resolve_operand(arg1, binding)

@spec resolve_operand(ir_term(), map()) :: {:ok, term()} | :unbound

Resolves an IR term against a binding environment.

Returns {:ok, native_value} if the term is a constant or a bound variable, or :unbound if the term is a variable not present in the binding.

serialize(ir)

@spec serialize(t()) :: map()

Serializes an IR program to a plain map.

The output is deterministic: relations, facts, rules, and strata are sorted by their canonical order.

value_to_native(arg)

@spec value_to_native(ir_value()) :: term()

Converts a tagged IR value to its native Elixir representation.

  • {:int, n}n
  • {:str, s}s
  • {:atom, a}a
  • {:list, elements}elements (each element is recursively converted)