Files
rose-ash/plans/prolog-on-sx.md
giles 0f67021aa3 plans: briefings + roadmaps for lua, prolog, forth, erlang, haskell
Five new guest-language plans mirroring the js-on-sx / hs-loop pattern, each
with a phased roadmap (Progress log + Blockers), a self-contained agent
briefing for respawning a long-lived loop, and a shared restore-all.sh that
snapshots state across all seven language loops.

Briefings bake in the lessons from today's stall debugging: never call
sx_build (600s watchdog), only touch lib/<lang>/** + own plan file, commit
every feature, update Progress log on each commit, route shared-file
issues to Blockers rather than fixing them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 15:16:45 +00:00

98 lines
4.8 KiB
Markdown

# Prolog-on-SX: mini-Prolog interpreter on delimited continuations
Horn clauses + unification + cut + arithmetic, implemented as an **interpreter** (clauses live as SX data, a SX-implemented solver walks them). Backtracking is powered by the delimited-continuations machinery in `lib/callcc.sx` + `spec/evaluator.sx` Step 5 — this is the reason Prolog fits SX well.
End-state goal: **200+ tests passing** (classic programs + Hirst's ISO conformance subset + Hyperscript integration suite). Long-lived background agent driving the scoreboard up.
## Ground rules
- **Scope:** only touch `lib/prolog/**` and `plans/prolog-on-sx.md`. Do **not** edit `spec/`, `hosts/`, `shared/`, `lib/js/**`, `lib/hyperscript/**`, `lib/lua/**`, `lib/stdlib.sx`, or anything in `lib/` root. Prolog primitives go in `lib/prolog/runtime.sx`.
- **Shared-file issues** go under "Blockers" below with a minimal repro; do not fix from this loop.
- **SX files:** use `sx-tree` MCP tools only.
- **Architecture:** Prolog source → term AST → clause DB. Solver is SX code walking the DB; backtracking via delimited continuations, not a separate trail machine.
- **Commits:** one feature per commit. Keep `## Progress log` updated and tick boxes.
## Architecture sketch
```
Prolog source text
lib/prolog/tokenizer.sx — atoms, vars, numbers, punct, comments
lib/prolog/parser.sx — term AST; phase 1: f(a,b) syntax only, no operator table
lib/prolog/runtime.sx — clause DB, unify!, trail, solver (DFS + delimited-cont backtracking)
│ built-ins: =/2, \=/2, !/0, is/2, call/1, findall/3, …
solutions / side-effects
```
Representation choices (finalise in phase 1, document here):
- **Term:** nested SX list. Compound `(functor arg1 arg2)`. Atom = symbol. Number = number. Variable = `{:var "X" :binding <ref>}` with mutable binding slot.
- **List:** cons-cell compound `(. H T)` or similar. `[1,2,3]` sugar desugared at parse.
- **Clause:** `{:head <term> :body <term>}` where body is the conjunction goal.
- **Clause DB:** dict `"functor/arity" → list of clauses`.
## Roadmap
### Phase 1 — tokenizer + term parser (no operator table)
- [ ] Tokenizer: atoms (lowercase/quoted), variables (uppercase/`_`), numbers, strings, punct `( ) , . [ ] | ! :-`, comments (`%`, `/* */`)
- [ ] Parser: clauses `head :- body.` and facts `head.`; terms `atom | Var | number | compound(args) | [list,sugar]`
- [ ] **Skip for phase 1:** operator table. `X is Y + 1` must be written `is(X, '+'(Y, 1))`; `=` written `=(X, Y)`. Operators land in phase 4.
- [ ] Unit tests in `lib/prolog/tests/parse.sx`
### Phase 2 — unification + trail
- [ ] `make-var`, `walk` (follow binding chain), `prolog-unify!` (terms + trail → bool), `trail-undo-to!`
- [ ] Occurs-check off by default, exposed as flag
- [ ] 30+ unification tests in `lib/prolog/tests/unify.sx`: atoms, vars, compounds, lists, cyclic (no-occurs-check), mutual occurs
### Phase 3 — clause DB + DFS solver + cut + first classic programs
- [ ] Clause DB: `"functor/arity" → list-of-clauses`, loader inserts
- [ ] Solver: DFS with choice points backed by delimited continuations (`lib/callcc.sx`). On goal entry, capture; per matching clause, unify head + recurse body; on failure, undo trail, try next
- [ ] Cut (`!`): cut barrier at current choice-point frame; collapse all up to barrier
- [ ] Built-ins: `=/2`, `\\=/2`, `true/0`, `fail/0`, `!/0`, `,/2`, `;/2`, `->/2` inside `;`, `call/1`, `write/1`, `nl/0`
- [ ] Arithmetic `is/2` with `+ - * / mod abs`
- [ ] Classic programs in `lib/prolog/tests/programs/`:
- [ ] `append.pl` — list append (with backtracking)
- [ ] `reverse.pl` — naive reverse
- [ ] `member.pl` — generate all solutions via backtracking
- [ ] `nqueens.pl` — 8-queens
- [ ] `family.pl` — facts + rules (parent/ancestor)
- [ ] `lib/prolog/conformance.sh` + runner, `scoreboard.json` + `scoreboard.md`
- [ ] Target: all 5 classic programs passing
### Phase 4 — operator table + more built-ins (next run)
- [ ] Operator table parsing (prefix/infix/postfix, precedence, assoc)
- [ ] `assert/1`, `asserta/1`, `assertz/1`, `retract/1`
- [ ] `findall/3`, `bagof/3`, `setof/3`
- [ ] `copy_term/2`, `functor/3`, `arg/3`, `=../2`
- [ ] String/atom predicates
### Phase 5 — Hyperscript integration
- [ ] `prolog-query` primitive callable from SX/Hyperscript
- [ ] Hyperscript DSL: `when allowed(user, :edit) then …`
- [ ] Integration suite
### Phase 6 — ISO conformance
- [ ] Vendor Hirst's conformance tests
- [ ] Drive scoreboard to 200+
### Phase 7 — compiler (later, optional)
- [ ] Compile clauses to SX continuations for speed
- [ ] Keep interpreter as the reference
## Progress log
_Newest first. Agent appends on every commit._
- _(awaiting phase 1)_
## Blockers
_Shared-file issues that need someone else to fix. Minimal repro only._
- _(none yet)_