# Aletheia v0.1.1 - Table of Contents

> An embedded Prolog dialect for Elixir: classic Prolog syntax (`:-`, `,`/`;`, `=`, a mutable op/3 table) via a reader on Ichor, fronting Episteme -- the resolution engine and clause database (unification, SLD-resolution, backtracking, a real clause-scoped cut) behind it.

## Pages

- [Aletheia](readme.md)
- [Case study: auditing structured application logs](case_study.md)
- [Changelog](changelog.md)
- [LICENSE](license.md)

- Guides
  - [Tutorial: embedding Aletheia in an Elixir application](tutorial-1.md)
  - [Examples: embedding Aletheia](examples.md)
  - [Cheatsheet: embedding Aletheia](cheatsheet.md)

- Language
  - [Tutorial: the Aletheia language](tutorial-2.md)
  - [Reference: the Aletheia language](aletheia-language-reference.md)
  - [Examples: the Aletheia language](aletheia_examples.md)
  - [Cheatsheet: the Aletheia language](aletheia_cheatsheet.md)

## Modules

- [Aletheia.Reader.ControlSyntax](Aletheia.Reader.ControlSyntax.md): 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.

- Top-level API
  - [Aletheia](Aletheia.md): 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.

- Reader
  - [Aletheia.Reader](Aletheia.Reader.md): 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
  - [Aletheia.Reader.Actions](Aletheia.Reader.Actions.md): 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.
  - [Aletheia.Reader.Pratt](Aletheia.Reader.Pratt.md): 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.

- REPL
  - [Aletheia.Repl](Aletheia.Repl.md): 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.

