Modules
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.
Parses Aletheia source into a sequence of clause forms -- {:fact, term}, {:rule, head, body}, or {:directive, goal} -- via
Aletheia.Reader.Grammar's run_sequence/2, a plain checked-in module
generated ahead of time from lib/aletheia/reader/grammar.aether by
Turns lib/aletheia/reader/grammar.aether's raw capture tree into
Episteme.Term-shaped data -- mirrors ichor's own
test/support/prolog_actions.ex worked example closely, adapted to
build real Episteme.Term.Var/Compound structs (and native lists,
via the ./2 encoding Episteme.Term.deconstruct/1 implements)
instead of that fixture's plain tuples.
Translates a parsed goal from Aletheia.Reader's own ISO-punctuation
term shape (,/2, ;/2, ->/2, !, =/2, ...) into the
plain-English control-construct/comparison names Episteme.Engine
dispatches on (and/2, or/2, if_then/2, cut, unify/2, ...) --
see episteme's own CHANGELOG.md under its 0.1.0 release: as of
its first Hex publish, Episteme no longer accepts ISO punctuation
directly, since it has no reader of its own for that punctuation to
be conventional syntax against. Bridging that gap is squarely this
reader's job, not the engine's.
The @native(...) callback lib/aletheia/reader/grammar.aether's
term/arg_term rules delegate to -- precedence-climbing over
context.operators (an Ichor.Toolkit.Pratt table), mirroring
ichor's own test/support/prolog_grammar.ex worked example, with one
addition: parse_arg_term/4 raises the floor to @arg_min_prec,
ISO's real "an argument is a term of priority =< 999" rule
(Ichor.Toolkit.Pratt.parse/4's own min_prec parameter), so , --
a genuine operator here, unlike that fixture's grammar-structural
comma -- never gets swallowed into a single argument or list element.
Minimal consult + interactive query loop: ?- prompts for a goal,
prints each solution's bindings, and (matching real Prolog UX) offers
; for the next solution or any other input to stop.