Top-level API: consult/1/consult_string/2 load source into an
Episteme.Database, query/2 solves a goal (source text or an
already-parsed term) against one. Parses text via Aletheia.Reader
and delegates the actual solving to Episteme, the standalone
engine/database package this reader is a front-end for -- everything
past parsing (terms, unification, SLD-resolution, cut, builtins) lives
there, not here. Uncaught Prolog exceptions (a real throw/1 no
catch/3 in the program itself caught) surface as {:error, term}
here, at the outermost boundary, rather than as a raw Elixir throw
escaping to the caller.
Every goal parsed from source text (a rule body, or a query/2-style
goal) is also rewritten from Aletheia.Reader's own ISO-punctuation
term shape (,/2, ;/2, !, =/2, ...) into the
plain-English control-construct/comparison names Episteme.Engine
dispatches on (and/2, or/2, cut, unify/2, ...) -- see
Aletheia.Reader.ControlSyntax. An already-parsed term passed
directly to query/2/query_lazy/2 is assumed to already be in
Episteme's own term shape and is passed through untouched.
Summary
Functions
Loads a .alp source file into a fresh database.
Loads Aletheia source text into db (default: a fresh database).
Pulls one solution from a query_lazy/2 stream -- see Episteme.next_solution/2.
Solves goal (source text or an already-parsed term) against db,
returning every solution's variable bindings as %{name => term}
maps (Episteme.Term.to_text/1-ready values, already fully resolved).
A real Prolog throw/1 that escapes uncaught surfaces as {:error, term}.
Like query/2, but doesn't force every solution eagerly -- returns the
raw lazy solution stream plus the goal's own named variables, both
meant to be passed straight to next_solution/2. For a REPL (or any
caller that only wants the first few solutions of a possibly-infinite
search) instead of query/2's own "pull the whole list" behavior.
Like query/2, but returns only the first solution (or :none).
Types
@type solution() :: Episteme.solution()
Functions
@spec consult(String.t()) :: {:ok, Episteme.Database.t()} | {:error, term()}
Loads a .alp source file into a fresh database.
@spec consult_string(String.t(), Episteme.Database.t()) :: {:ok, Episteme.Database.t()} | {:error, term()}
Loads Aletheia source text into db (default: a fresh database).
@spec next_solution(Ichor.Backtrack.Tree.t(), MapSet.t(Episteme.Term.Var.t())) :: {:solution, solution(), Ichor.Backtrack.Tree.t()} | :none | {:error, term()}
Pulls one solution from a query_lazy/2 stream -- see Episteme.next_solution/2.
@spec query(String.t() | term(), Episteme.Database.t()) :: {:ok, [solution()]} | {:error, term()}
Solves goal (source text or an already-parsed term) against db,
returning every solution's variable bindings as %{name => term}
maps (Episteme.Term.to_text/1-ready values, already fully resolved).
A real Prolog throw/1 that escapes uncaught surfaces as {:error, term}.
@spec query_lazy(String.t() | term(), Episteme.Database.t()) :: {:ok, {Ichor.Backtrack.Tree.t(), MapSet.t(Episteme.Term.Var.t())}} | {:error, term()}
Like query/2, but doesn't force every solution eagerly -- returns the
raw lazy solution stream plus the goal's own named variables, both
meant to be passed straight to next_solution/2. For a REPL (or any
caller that only wants the first few solutions of a possibly-infinite
search) instead of query/2's own "pull the whole list" behavior.
@spec query_once(String.t() | term(), Episteme.Database.t()) :: {:ok, solution()} | :none | {:error, term()}
Like query/2, but returns only the first solution (or :none).