⏺ Done. The shared builtin vocabulary table (delta-1) is implemented and #7

Merged
navicore merged 4 commits from lsp into main 2026-06-10 05:03:17 +00:00
Owner

verified.
What landed

crates/shared/src/builtins.rs (new) — the zero-dep single source of truth:

  • BUILTINS: the 55-row (name, arity, kind, doc) table from the reconciled
    roster, #[rustfmt::skip] to keep it a readable one-row-per-line table.
  • BuiltinKind (Control/Inline/Det/Atom) to partition validation.
  • BuiltinSpec::completable() — the identifier heuristic (not kind-derived),
    with the documented escape hatch to a complete: bool column.
  • Accessors lookup, doc (hover: all rows), atom_names/functor_names
    (completion: completable only).
  • 5 self-check tests (size/partition, no dupes, every row doc'd, completable
    behavior, accessor filtering).
  • Re-exported from lib.rs.

crates/compiler/src/codegen/lower.rs — #[cfg(test)] mod vocab_invariant:
asserts DET_BUILTINS are Det rows in BUILTINS, and that codegen's full
recognized set (DET_BUILTINS ∪ ARITH_OPS ∪ ORDER_OPS ∪ a small hand-mirrored
STRUCTURAL list) exactly equals the BUILTINS vocabulary.

crates/runtime/src/control.rs — #[cfg(test)] mod vocab_invariant: asserts
det_builtin's arms equal the Det/arity>0 subset of BUILTINS. Referenced only
under #[cfg(test)] — the key to the zero-leak guarantee.

Checkpoints, all met

  1. Roster complete — 55 rows, 52 docs ported verbatim from v1, 3 new (, ; ->);
    partition 25/16/10/4 asserted.
  2. codegen test — passes (det_builtins_are_det_rows_in_shared,
    recognized_names_equal_shared_vocabulary).
  3. runtime test — passes (det_dispatch_equals_shared_det_subset).
  4. Zero leak into programs — built a real hello-world: 0 doc strings in the
    final binary (vs 4 in the intermediate staticlib, dead-stripped at link). The
    binary_size footprint gate still passes.
  5. Invariant bites — deleting sort/2 from DET_BUILTINS turned the codegen test
    red with a clear set diff; restored to green.

Full suite: 272 tests pass, 0 failures, clippy clean, fmt clean.

One thing worth flagging for when you wire the LSP: the comment I left on
control.rs's det_builtin ("mirrors codegen's DET_BUILTINS") is now backed by an
actual test rather than just prose — so the three-way tie (shared ↔ codegen ↔
runtime) is enforced in just ci, not hoped for. The table is ready for the
plg-lsp crate's completion and hover to consume directly.

verified. What landed crates/shared/src/builtins.rs (new) — the zero-dep single source of truth: - BUILTINS: the 55-row (name, arity, kind, doc) table from the reconciled roster, #[rustfmt::skip] to keep it a readable one-row-per-line table. - BuiltinKind (Control/Inline/Det/Atom) to partition validation. - BuiltinSpec::completable() — the identifier heuristic (not kind-derived), with the documented escape hatch to a complete: bool column. - Accessors lookup, doc (hover: all rows), atom_names/functor_names (completion: completable only). - 5 self-check tests (size/partition, no dupes, every row doc'd, completable behavior, accessor filtering). - Re-exported from lib.rs. crates/compiler/src/codegen/lower.rs — #[cfg(test)] mod vocab_invariant: asserts DET_BUILTINS are Det rows in BUILTINS, and that codegen's full recognized set (DET_BUILTINS ∪ ARITH_OPS ∪ ORDER_OPS ∪ a small hand-mirrored STRUCTURAL list) exactly equals the BUILTINS vocabulary. crates/runtime/src/control.rs — #[cfg(test)] mod vocab_invariant: asserts det_builtin's arms equal the Det/arity>0 subset of BUILTINS. Referenced only under #[cfg(test)] — the key to the zero-leak guarantee. Checkpoints, all met 1. Roster complete — 55 rows, 52 docs ported verbatim from v1, 3 new (, ; ->); partition 25/16/10/4 asserted. 2. codegen test — passes (det_builtins_are_det_rows_in_shared, recognized_names_equal_shared_vocabulary). 3. runtime test — passes (det_dispatch_equals_shared_det_subset). 4. Zero leak into programs — built a real hello-world: 0 doc strings in the final binary (vs 4 in the intermediate staticlib, dead-stripped at link). The binary_size footprint gate still passes. 5. Invariant bites — deleting sort/2 from DET_BUILTINS turned the codegen test red with a clear set diff; restored to green. Full suite: 272 tests pass, 0 failures, clippy clean, fmt clean. One thing worth flagging for when you wire the LSP: the comment I left on control.rs's det_builtin ("mirrors codegen's DET_BUILTINS") is now backed by an actual test rather than just prose — so the three-way tie (shared ↔ codegen ↔ runtime) is enforced in just ci, not hoped for. The table is ready for the plg-lsp crate's completion and hover to consume directly.
⏺ Done. The shared builtin vocabulary table (delta-1) is implemented and
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 46s
b09e573b58
verified.
  What landed

  crates/shared/src/builtins.rs (new) — the zero-dep single source of truth:
  - BUILTINS: the 55-row (name, arity, kind, doc) table from the reconciled
  roster, #[rustfmt::skip] to keep it a readable one-row-per-line table.
  - BuiltinKind (Control/Inline/Det/Atom) to partition validation.
  - BuiltinSpec::completable() — the identifier heuristic (not kind-derived),
  with the documented escape hatch to a complete: bool column.
  - Accessors lookup, doc (hover: all rows), atom_names/functor_names
  (completion: completable only).
  - 5 self-check tests (size/partition, no dupes, every row doc'd, completable
  behavior, accessor filtering).
  - Re-exported from lib.rs.

  crates/compiler/src/codegen/lower.rs — #[cfg(test)] mod vocab_invariant:
  asserts DET_BUILTINS are Det rows in BUILTINS, and that codegen's full
  recognized set (DET_BUILTINS ∪ ARITH_OPS ∪ ORDER_OPS ∪ a small hand-mirrored
  STRUCTURAL list) exactly equals the BUILTINS vocabulary.

  crates/runtime/src/control.rs — #[cfg(test)] mod vocab_invariant: asserts
  det_builtin's arms equal the Det/arity>0 subset of BUILTINS. Referenced only
  under #[cfg(test)] — the key to the zero-leak guarantee.

  Checkpoints, all met

  1. Roster complete — 55 rows, 52 docs ported verbatim from v1, 3 new (, ; ->);
  partition 25/16/10/4 asserted.
  2. codegen test — passes (det_builtins_are_det_rows_in_shared,
  recognized_names_equal_shared_vocabulary).
  3. runtime test — passes (det_dispatch_equals_shared_det_subset).
  4. Zero leak into programs — built a real hello-world: 0 doc strings in the
  final binary (vs 4 in the intermediate staticlib, dead-stripped at link). The
  binary_size footprint gate still passes.
  5. Invariant bites — deleting sort/2 from DET_BUILTINS turned the codegen test
  red with a clear set diff; restored to green.

  Full suite: 272 tests pass, 0 failures, clippy clean, fmt clean.

  One thing worth flagging for when you wire the LSP: the comment I left on
  control.rs's det_builtin ("mirrors codegen's DET_BUILTINS") is now backed by an
  actual test rather than just prose — so the three-way tie (shared ↔ codegen ↔
  runtime) is enforced in just ci, not hoped for. The table is ready for the
  plg-lsp crate's completion and hover to consume directly.
⏺ The completion + hover slice is complete and verified end-to-end.
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 1m7s
aba4002be6
What shipped

  completion.rs — three sources, user-shadows-stdlib-shadows-builtin:
  - Built-ins from plg_shared::builtins::{atom_names, functor_names} — these
  already apply completable(), so operators and ! are filtered out automatically
  (the delta-1 payoff: no LSP-side filter needed).
  - Stdlib predicates parsed once from plg_shared::STDLIB_PL (delta-2 payoff).
  - User predicates via buffer::parse_best_effort (mid-edit recovery).

  hover.rs — built-in docs from plg_shared::builtins::doc (the same table
  codegen/runtime validate against), falling back to rendered user clause heads.

  main.rs — added completion_provider/hover_provider capabilities and both
  handlers; dropped the temporary dead_code allows now that buffer and content
  are live.

  Verified over real stdio

  - Completion for mem in a buffer defining member/2: returns member, and ! is
  absent — confirming the completable() filter works through the whole pipeline.
  - Hover on user member → **member** (user-defined) with the rendered head
  member(_0, [...]).
  - Hover on builtin between/findall → the doc text from the shared table.

  One honest correction

  Hovering an operator like =.. returns nothing — word_at_position extracts
  identifier runs only, so the cursor never resolves to a symbol token. This is
  exactly v1's behavior (its operator doc entries were unreachable via hover
  too). I'd initially overstated "hover serves operators"; I corrected both
  comments and added a test only for the identifier-form case that actually
  works. Symbol-token hover would be an additive enhancement, noted in the
  hover.rs header — not part of v1 parity.
lsp
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 1m1s
ab052fc75f
⏺ Done. Undefined-predicate detection is implemented end-to-end, with your exact
All checks were successful
CI - Linux / CI - Linux x86_64 (pull_request) Successful in 1m2s
1c86a814f7
requirements: ISO by default, strictness on demand.

  What landed

  Shared analysis (crates/frontend/src/lint.rs) — lives in plg-frontend so both
  the compiler and the LSP use it without pulling in codegen/runtime:
  - Walks clause bodies, recursing through control constructs (, ; -> \+ once)
  and meta-goal positions (findall's goal, catch's goal+recovery, call/1). Flags
  only direct, statically-resolvable calls; variable goals and call/N (N>1) are
  left to the runtime.
  - Recognizes builtins (via the delta-1 BUILTINS table) and dynamic decls — no
  false positives.
  - Did-you-mean via Levenshtein (xarent → parent).
  - 9 unit tests.

  Compiler (plgc) — --deny-undefined on build/run/check:
  - Default: warning, still compiles → the
  undefined_in_rule_body_raises_when_reached ISO contract is untouched
  (verified).
  - --deny-undefined: error, exit 2, no binary.

  LSP (plgl) — undefined calls surface as WARNING squiggles (yellow), distinct
  from red parse errors, positioned on the call site. Seeds stdlib into the
  interner so member/append calls aren't falsely flagged.

  Docs — ISO_COMPLIANCE.md records the decision (catchable existence_error stays;
  strictness is opt-in above the ISO default); plugin README updated.

  Verified in real nvim

  WARN line=2 col=15-21 src=plgl msg="undefined predicate xarent/1 — did you mean
  parent/1?"
  And plgc:
  - check /tmp/undef.pl → warning: … did you mean parent/1?, exit 0
  - check --deny-undefined → error: …, exit 2
  - build → warns, binary produced; build --deny-undefined → errors, no binary

  371 tests pass, 0 failures, fmt clean, clippy clean.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-prolog!7
No description provided.