Aletheia (Aletheia v0.1.1)

Copy Markdown View Source

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

solution()

@type solution() :: Episteme.solution()

Functions

consult(path)

@spec consult(String.t()) :: {:ok, Episteme.Database.t()} | {:error, term()}

Loads a .alp source file into a fresh database.

consult_string(source, db \\ Database.new())

@spec consult_string(String.t(), Episteme.Database.t()) ::
  {:ok, Episteme.Database.t()} | {:error, term()}

Loads Aletheia source text into db (default: a fresh database).

next_solution(stream, vars)

@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.

query(goal, db)

@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}.

query_lazy(goal, db)

@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.

query_once(goal, db)

@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).