eyeprolog 1.5.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,8 +31,6 @@ Run EyeProlog without installing it globally:
31
31
 
32
32
  ```sh
33
33
  npx --yes eyeprolog
34
- ?- use_module(library(lists)).
35
- true.
36
34
  ?- member(X, [prolog, logic]).
37
35
  X = prolog
38
36
  ; X = logic.
@@ -63,7 +61,9 @@ printf 'human(socrates).\nmortal(X) :- human(X).\n' |
63
61
  Normal mode executes top-level `Conclusion :+ Premise` rules natively when no explicit
64
62
  `-g/--goal` is supplied. `true :+ Goal` prints answers and `false :+ Goal` emits a
65
63
  `fuse/1`; JavaScript `run()` follows the same rule. Strict ISO mode disables this
66
- extension. See [*The Art of EyeProlog*](the-art-of-eyeprolog.md) for the full semantics.
64
+ extension. Bundled `src/lib/` predicates autoload in files, CLI/API goals, and the REPL;
65
+ use `--no-autoload` to require explicit imports, and explicitly import libraries that introduce
66
+ operators before using their syntax. See [*The Art of EyeProlog*](the-art-of-eyeprolog.md) for the full semantics.
67
67
 
68
68
  ## Links
69
69
 
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.2",
6
+ "version": "1.5.3",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
@@ -121,7 +121,7 @@ families; `--iso-strict` is intended to remove their Part 1 interpretation.
121
121
  | 5.5.6 Side effects | Normal mode adds `statistics/0-2`, cleanup/library state, and optional proof/statistics host instrumentation. | The strict registry excludes Prolog-visible statistics/cleanup/library adapters; ordinary Part 1 I/O/database/flag/operator side effects remain. Host proof/statistics collection observes execution through the embedding API rather than adding a strict Prolog goal effect. **covered** — strict registry/execution regression. |
122
122
  | 5.5.7 Control constructs | `tnot/1` and normal-profile execution optimizations | `tnot/1` and the normal-profile explicit `table` declaration are absent. |
123
123
  | 5.5.8 Flags | `occurs_check` | Absent in strict mode. |
124
- | 5.5.9 Built-in predicates | EyeProlog libraries, CLP(Z), statistics, Part 3 `phrase/2-3`, and interop autoloaded predicates | Strict registry contains only the Part 1 + Corrigenda core registry. |
124
+ | 5.5.9 Built-in predicates | EyeProlog libraries, CLP(Z), statistics, Part 3 `phrase/2-3`, and bundled-library autoloaded predicates | Strict registry contains only the Part 1 + Corrigenda core registry. |
125
125
  | 5.5.10 Evaluable functors | Normal mode additionally accepts the EyeProlog evaluable atom `e`; the remaining arithmetic functors accepted by strict mode are the Part 1 + Corrigenda set. | Strict mode rejects `e/0` as non-evaluable and retains the Corrigendum arithmetic additions. **covered** — strict extension-boundary regression plus `src/iso-arithmetic.js`. |
126
126
  | 5.5.11 Reserved atoms | None | None. |
127
127
  | Cor.3 5.5.12 Options | Extra library/host options may exist outside core option lists | Normal mode additionally accepts the EyeProlog `write_term/2-3` options `double_quotes(true|false)` and `spacing(true|false)`. `spacing(false)` emits only lexically required separators; `spacing(true)` adds conventional layout around operators. Strict core excludes these implementation-specific extensions and accepts only the Part 1 plus Corrigendum 3 write-option surface; unknown extension options raise `domain_error(write_option,...)`. |
@@ -4784,6 +4784,33 @@ function documentationSyncCases() {
4784
4784
  assertEqual(result.stderr, '', 'stderr');
4785
4785
  },
4786
4786
  },
4787
+ {
4788
+ name: 'reference docs match explicit tabling and current runtime extensions',
4789
+ run: () => {
4790
+ const readme = fs.readFileSync(path.join(packageRoot, 'README.md'), 'utf8');
4791
+ const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
4792
+ const profile = fs.readFileSync(path.join(packageRoot, 'why-eyeprolog.md'), 'utf8');
4793
+ const combined = `${readme}
4794
+ ${book}
4795
+ ${profile}`;
4796
+ for (const stale of [
4797
+ 'Automatic tabling',
4798
+ 'Automatic hybrid reasoning',
4799
+ 'eligible positive recursive groups are tabled automatically',
4800
+ '--no-auto-table',
4801
+ 'conservative interop autoloading',
4802
+ ]) assertNotIncludes(combined, stale, `stale documentation phrase ${stale}`);
4803
+ assertIncludes(book, 'including recursive calls, use depth-first resolution unless the source', 'ordinary recursion is depth-first');
4804
+ assertIncludes(book, 'explicitly declares `:- table p/n.`', 'tabling is explicit');
4805
+ assertIncludes(book, 'The autoload index covers every', 'generic bundled-library autoload');
4806
+ assertIncludes(book, 'interactive top-level query therefore autoloads its canonical', 'REPL autoload');
4807
+ assertIncludes(book, 'Autoloading therefore supplies', 'autoload syntax boundary');
4808
+ assertIncludes(book, 'Residual constraints are part of the displayed answer even when', 'top-level hidden residuals');
4809
+ assertIncludes(book, 'EyeProlog normal mode also accepts `:+`', 'native forward-rule extension');
4810
+ assertIncludes(profile, 'an unresolved unqualified predicate may autoload its unique provider', 'Why EyeProlog autoload policy');
4811
+ assertIncludes(readme, 'Bundled `src/lib/` predicates autoload in files, CLI/API goals, and the REPL', 'README autoload summary');
4812
+ },
4813
+ },
4787
4814
  {
4788
4815
  name: 'WG17 syntax status matches its executable-coverage manifest',
4789
4816
  run: () => {
@@ -30,7 +30,7 @@ program with EyeProlog means learning to move comfortably between these views.
30
30
 
31
31
  EyeProlog implements a broad ISO Prolog profile with facts, clauses, terms, lists,
32
32
  control, arithmetic, dynamic predicates, operators, streams, and standard
33
- built-ins. Automatic
33
+ built-ins. Explicit
34
34
  tabling, explicit integrity checks, and proof output are implementation
35
35
  capabilities around that standards-based foundation. EyeProlog does not attempt to
36
36
  claim formal certification of every ISO processor edge case.
@@ -175,7 +175,8 @@ Approach each example through the same six moves:
175
175
  This rhythm deliberately joins declarative reading, operational reading, and
176
176
  program construction. Readers new to logic programming can follow Parts I–III
177
177
  in order. Experienced Prolog programmers can begin with Chapters 3, 13, and
178
- 17 to see where EyeProlog's hybrid execution and proof-oriented design differ.
178
+ 17 to see how EyeProlog combines ordinary depth-first Prolog with explicit
179
+ tabling, native forward rules, and inspectable proofs.
179
180
  Chapter 41 gives further routes through the material.
180
181
 
181
182
  ### When a run surprises you
@@ -5685,10 +5686,11 @@ so `edge/2` and `edge/3` are different predicates.
5685
5686
 
5686
5687
  Execution is goal-directed rather than complete bottom-up saturation. Goals in
5687
5688
  a body normally run from left to right; the solver may select a ready
5688
- deterministic built-in early as a pure filter. Ordinary user-defined calls use
5689
- depth-first resolution, while eligible positive recursive groups are tabled
5690
- automatically. `\+/1` is stratified negation as failure, not classical
5691
- negation.
5689
+ deterministic built-in early as a pure filter. Ordinary user-defined calls,
5690
+ including recursive calls, use depth-first resolution unless the source
5691
+ explicitly declares `:- table p/n.`. `\+/1` is negation as failure, not
5692
+ classical negation; the separate `tnot/1` extension provides well-founded
5693
+ semantics for eligible finite Datalog components.
5692
5694
 
5693
5695
  EyeProlog supports cut, operator declarations, dynamic database updates, grouped
5694
5696
  solutions, exceptions, flags, initialization and inclusion directives, and
@@ -5840,21 +5842,27 @@ time. Source facts are not echoed as new conclusions, and duplicate answers
5840
5842
  are suppressed. Answers are not asserted back into the running program.
5841
5843
  Supported output syntax is designed to be readable as Prolog input accepted by EyeProlog.
5842
5844
 
5843
- #### Automatic hybrid reasoning
5845
+ #### Explicit tabling and recursion planning
5844
5846
 
5845
- The program loader detects predicate-dependency cycles, including dependencies
5846
- inside conjunction, `\+/1`, `once/1`, and aggregate goals.
5847
- Positive recursive components—including directly queried recursive
5848
- relations—are tabled to an answer fixed point before answers are replayed.
5849
- Components with a negative dependency retain guarded ordinary resolution,
5850
- because positive least-fixed-point tabling does not define unstratified
5851
- negation. Nonrecursive groups use indexed, depth-first resolution.
5847
+ The program loader analyzes predicate dependencies and recursion so the solver
5848
+ can choose semantics-preserving indexes and fast paths. That analysis does
5849
+ **not** decide whether a predicate is tabled. Ordinary predicates—including
5850
+ recursive ones—use indexed, depth-first Prolog resolution unless their source
5851
+ explicitly declares `:- table p/n.`.
5852
5852
 
5853
- For calls with ground structural input, tabled answers can be reused within a
5854
- solver run. The engine infers common structurally decreasing inputs from
5855
- recursive heads. Fully open calls and calls whose inferred structural input is
5856
- not ground may remain under ordinary resolution rather than forcing a possibly
5857
- infinite relation into a table. This changes control, not declarative meaning.
5853
+ An explicitly tabled positive recursive predicate is coordinated through an
5854
+ answer table: recurring calls consume answers already found, new answers are
5855
+ recorded, and evaluation continues toward a fixed point. For eligible large,
5856
+ finite, function-free Datalog components, EyeProlog may represent that declared
5857
+ table as one shared most-general relation or an indexed least model. For other
5858
+ declared tables the engine may infer structurally bound input positions to
5859
+ improve table reuse. These are implementation choices inside an explicit table
5860
+ declaration; they never opt an undeclared predicate into tabling.
5861
+
5862
+ Ordinary `\+/1` remains ISO-style negation as failure. The separate `tnot/1`
5863
+ extension explicitly requests well-founded evaluation for eligible finite,
5864
+ range-restricted Datalog dependencies. Strict ISO mode exposes neither `table`
5865
+ nor `tnot/1`.
5858
5866
 
5859
5867
  #### Query execution
5860
5868
 
@@ -5872,8 +5880,8 @@ answers. The host:
5872
5880
  7. prints each answer and, only when requested, its `why/2` explanation.
5873
5881
 
5874
5882
  Goal selection affects host execution rather than the program's logical meaning.
5875
- One goal's answers are not asserted for later goals, although internal
5876
- tables may be reused during the solver run. For stable output, queries for
5883
+ One goal's answers are not asserted for later goals, although explicitly
5884
+ declared tables may be reused during the solver run. For stable output, queries for
5877
5885
  known predicates are grouped by the source order in which their predicate
5878
5886
  groups first appear; goals within one group retain their supplied order.
5879
5887
  Queries for predicates with no group follow the known groups.
@@ -7475,7 +7483,7 @@ recursion as one technique.
7475
7483
  | [Deep taxonomy: 10](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-10.pl) | A small generated hierarchy is readable by hand and establishes the benchmark shape. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-10.pl) |
7476
7484
  | [Deep Taxonomy 100](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-100.pl) | A 100-step taxonomy chain that exercises deep recursive closure and side-label derivation. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-100.pl) |
7477
7485
  | [Deep taxonomy: 1,000](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-1000.pl) | The same logical theory tests indexing and recursive closure at a realistic depth. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-1000.pl) |
7478
- | [Deep Taxonomy 10000](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-10000.pl) | A 10,000-step taxonomy chain used as a large-depth tabling and closure stress test. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-10000.pl) |
7486
+ | [Deep Taxonomy 10000](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-10000.pl) | A 10,000-step taxonomy chain used as a large-depth ordinary-recursion and closure stress test. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-10000.pl) |
7479
7487
  | [Deep taxonomy: 100,000](https://github.com/eyereasoner/eyeprolog/blob/main/examples/deep-taxonomy-100000.pl) | A stress case separates semantic simplicity from implementation scale. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/deep-taxonomy-100000.pl) |
7480
7488
  | [Family cousins](https://github.com/eyereasoner/eyeprolog/blob/main/examples/family-cousins.pl) | Several relational joins derive kinship beyond a simple transitive closure. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/family-cousins.pl) |
7481
7489
  | [Graph reachability](https://github.com/eyereasoner/eyeprolog/blob/main/examples/graph-reachability.pl) | A visited list bounds cyclic traversal and makes explicit negative test cases finite. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/graph-reachability.pl) · [proof](https://github.com/eyereasoner/eyeprolog/blob/main/examples/proof/graph-reachability.pl) |
package/why-eyeprolog.md CHANGED
@@ -149,6 +149,14 @@ removes the operator. Because resource exhaustion is not logical failure, normal
149
149
  execution has no hidden depth cutoff; an explicitly requested depth limit raises
150
150
  `resource_error(depth_limit)`.
151
151
 
152
+ Library convenience is explicit at the profile boundary too. Outside strict ISO
153
+ mode, an unresolved unqualified predicate may autoload its unique provider from
154
+ the bundled `src/lib/` modules after program definitions, standard built-ins,
155
+ and explicit imports have had precedence. `--no-autoload` disables this
156
+ convenience, and strict ISO mode disables it unconditionally. Autoloading happens
157
+ after parsing, so libraries that introduce operators still require an explicit
158
+ `use_module/1-2` before that syntax is read.
159
+
152
160
  Definite clause grammars follow the ISO Part 3 difference-list model. Internal
153
161
  fast paths make deep finite sequence processing economical while preserving
154
162
  relational modes. The checked