eyeprolog 1.5.61 → 1.5.63

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.
Files changed (39) hide show
  1. package/README.md +3 -2
  2. package/examples/cross-organization-data-sharing.pl +1 -1
  3. package/examples/data/README.md +1 -1
  4. package/examples/data/symbiotic-knowledge-graph-rules.pl +3 -3
  5. package/examples/deck/introduction-to-eyeprolog.md +1 -1
  6. package/examples/deck/symbiotic-knowledge-graphs.md +6 -6
  7. package/examples/dpv-odrl-purpose-mapping.pl +2 -2
  8. package/examples/explainable-ev-depot-configuration.pl +1 -1
  9. package/examples/odrl-dpv-fpv-trust-flow.pl +2 -2
  10. package/examples/odrl-dpv-healthcare-risk-ranked.pl +2 -2
  11. package/examples/odrl-dpv-risk-ranked.pl +2 -2
  12. package/examples/odrl-policy-advanced.pl +2 -2
  13. package/examples/odrl-policy.pl +2 -2
  14. package/examples/operational-incident-response.pl +1 -1
  15. package/examples/output/symbiotic-knowledge-graph.pl +2 -2
  16. package/examples/rdf12-annotated-claims.pl +2 -2
  17. package/examples/rdf12-annotation.pl +2 -2
  18. package/examples/rdf12-directional-language.pl +2 -2
  19. package/examples/rdf12-nested-triple-term.pl +2 -2
  20. package/examples/rdf12-trig-graph-join.pl +2 -2
  21. package/examples/rdf12-trig-named-graph.pl +2 -2
  22. package/examples/rdf12-trig-triple-term.pl +2 -2
  23. package/examples/rdf12-triple-term.pl +2 -2
  24. package/examples/sbom-vulnerability-response.pl +1 -1
  25. package/examples/scientific-evidence-graph.pl +1 -1
  26. package/examples/symbiotic-knowledge-graph.pl +4 -4
  27. package/package.json +1 -1
  28. package/src/lib/error.pl +35 -27
  29. package/src/lib/random.pl +14 -11
  30. package/src/lib/si.pl +47 -9
  31. package/src/library-autoload-index.js +1 -0
  32. package/src/standard-library.js +1 -1
  33. package/test/regression/cases-api.mjs +2 -2
  34. package/test/regression/cases-documentation-sync.mjs +4 -4
  35. package/test/regression/cases-regression.mjs +78 -0
  36. package/the-art-of-eyeprolog.md +428 -424
  37. package/tools/generate-predicate-reference.mjs +1 -1
  38. package/tools/predicate-reference.json +10 -1
  39. package/why-eyeprolog.md +1 -1
package/README.md CHANGED
@@ -69,14 +69,15 @@ printf 'human(socrates).\nmortal(X) :- human(X).\n' |
69
69
  - [Example decks](examples/deck/README.md) — explainable RDF/Prolog scenarios with reproducible roundtrips
70
70
  - [Introduction to EyeProlog](https://eyereasoner.github.io/eyeprolog/examples/deck/introduction-to-eyeprolog) — short presentation deck for first-time audiences
71
71
  - [Symbiotic Knowledge Graphs](https://eyereasoner.github.io/eyeprolog/examples/deck/symbiotic-knowledge-graphs) — RDF ↔ Prolog heatwave-response demo for human/AI/KG co-evolution
72
- - [rdf-prolog-roundtrip](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the RDF examples
72
+ - [rdf-prolog-interchange](https://github.com/eyereasoner/rdf-prolog-interchange) — standalone RDF 1.2 ↔ ISO Prolog bridge used by the RDF examples
73
+ - [RDF and Prolog: Two Standards-Based Legs](https://github.com/eyereasoner/rdf-prolog-interchange/blob/main/why-rdf-prolog.md) — why W3C RDF and ISO Prolog form the foundation
73
74
  - [ISO conformance review](test/conformance/ISO-COMPLIANCE.md) — supported Part 1 profile
74
75
  - [Latest Neumerkel conformity](test/conformance/NEUMERKEL-LATEST.md) — tracked result from the current live upstream inventory
75
76
  - [Conformance report](conformance-report.md) — generated executable conformance status, local corpus summary, and known deviations
76
77
  - [OpenRuleBench](openrulebench/README.md) — portable benchmark profile
77
78
  ## RDF, Prolog, and symbiotic knowledge graphs
78
79
 
79
- EyeProlog can sit behind an RDF knowledge graph without inventing a private graph representation. [`rdf-prolog-roundtrip`](https://github.com/eyereasoner/rdf-prolog-roundtrip) converts RDF 1.2 datasets to ordinary `rdf(Subject, Predicate, Object, Graph)` facts, EyeProlog applies portable rules, and ground `rdf/4` results can be converted back to RDF.
80
+ EyeProlog can sit behind an RDF knowledge graph without inventing a private graph representation. [`rdf-prolog-interchange`](https://github.com/eyereasoner/rdf-prolog-interchange) converts RDF 1.2 datasets to ordinary `rdf(Subject, Predicate, Object, Graph)` facts, EyeProlog applies portable rules, and ground `rdf/4` results can be converted back to RDF.
80
81
 
81
82
  The checked [Symbiotic Knowledge Graphs example](examples/symbiotic-knowledge-graph.pl) uses named graphs and RDF 1.2 triple terms to distinguish trusted knowledge, AI-proposed statements, and human review. Its [wide-audience companion](https://eyereasoner.github.io/eyeprolog/examples/deck/symbiotic-knowledge-graphs) explains why this is a useful present-day software model for human/AI/KG co-evolution: RDF supplies shared semantic memory, Prolog supplies explicit deliberation, AI supplies new hypotheses, and people remain participants in meaning and judgment.
82
83
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -4,7 +4,7 @@ This directory contains source and materialized data that support runnable examp
4
4
 
5
5
  ## Symbiotic Knowledge Graphs
6
6
 
7
- The heatwave-response example uses [`rdf-prolog-roundtrip`](https://github.com/eyereasoner/rdf-prolog-roundtrip) as its RDF boundary:
7
+ The heatwave-response example uses [`rdf-prolog-interchange`](https://github.com/eyereasoner/rdf-prolog-interchange) as its RDF boundary:
8
8
 
9
9
  ```text
10
10
  symbiotic-knowledge-graph-input.nq
@@ -1,6 +1,6 @@
1
1
  % Symbiotic knowledge graph rules for EyeProlog.
2
2
  %
3
- % The source rdf/4 facts above are generated by rdf-prolog-roundtrip from
3
+ % The source rdf/4 facts above are generated by rdf-prolog-interchange from
4
4
  % symbiotic-knowledge-graph-input.nq. RDF stays the interchange and storage
5
5
  % model; these rules provide the explicit reasoning and governance layer.
6
6
 
@@ -317,10 +317,10 @@ knowledge_exchange_fact(prolog_to_rdf, materialized_ground_rdf4).
317
317
 
318
318
  pipeline_step(N, Description) :- pipeline_step_fact(N, Description).
319
319
  pipeline_step_fact(1, 'RDF 1.2 N-Quads: named graphs keep source and governance boundaries explicit').
320
- pipeline_step_fact(2, 'rdf-prolog-roundtrip: RDF becomes ordinary rdf/4 Prolog facts without a solver').
320
+ pipeline_step_fact(2, 'rdf-prolog-interchange: RDF becomes ordinary rdf/4 Prolog facts without a solver').
321
321
  pipeline_step_fact(3, 'EyeProlog: ISO Prolog rules validate candidates, apply review policy, and derive actions').
322
322
  pipeline_step_fact(4, 'EyeProlog: result_rdf/4 materializes accepted knowledge and decisions as ground RDF-shaped facts').
323
- pipeline_step_fact(5, 'rdf-prolog-roundtrip: ground rdf/4 facts become RDF again for publication or federation').
323
+ pipeline_step_fact(5, 'rdf-prolog-interchange: ground rdf/4 facts become RDF again for publication or federation').
324
324
 
325
325
  cognitive_parallel(Prolog, Human) :- cognitive_parallel_fact(Prolog, Human).
326
326
  cognitive_parallel_fact(fact, remembered_assertion).
@@ -166,7 +166,7 @@ Boolean constraints are compact when the domain is “on/off”, “selected/not
166
166
 
167
167
  ## RDF and knowledge graphs
168
168
 
169
- EyeProlog pairs naturally with RDF through `rdf-prolog-roundtrip`:
169
+ EyeProlog pairs naturally with RDF through `rdf-prolog-interchange`:
170
170
 
171
171
  ```text
172
172
  RDF dataset
@@ -10,7 +10,7 @@ The demonstration does not claim that EyeProlog is a brain-computer interface. I
10
10
 
11
11
  The architecture uses two small projects with deliberately separate jobs:
12
12
 
13
- - [`rdf-prolog-roundtrip`](https://github.com/eyereasoner/rdf-prolog-roundtrip) moves RDF 1.2 datasets to and from ordinary `rdf/4` Prolog facts. It contains no Prolog solver.
13
+ - [`rdf-prolog-interchange`](https://github.com/eyereasoner/rdf-prolog-interchange) moves RDF 1.2 datasets to and from ordinary `rdf/4` Prolog facts. It contains no Prolog solver.
14
14
  - [EyeProlog](https://github.com/eyereasoner/eyeprolog) reasons over those facts with explicit ISO Prolog rules.
15
15
 
16
16
  That separation is the central design choice. **RDF remains the shared interchange and publication layer; Prolog becomes the transparent reasoning layer.**
@@ -105,7 +105,7 @@ p2 confidencePercent 93
105
105
 
106
106
  The embedded triple is a **statement being talked about**. It is not yet an asserted operational fact.
107
107
 
108
- After `rdf-prolog-roundtrip`, the same structure is an ordinary Prolog term:
108
+ After `rdf-prolog-interchange`, the same structure is an ordinary Prolog term:
109
109
 
110
110
  ```prolog
111
111
  rdf(
@@ -246,10 +246,10 @@ That closeness makes it easier for a person to enter the machine's reasoning loo
246
246
 
247
247
  Without RDF, the Prolog example could be dismissed as a hand-written toy knowledge base.
248
248
 
249
- With `rdf-prolog-roundtrip`, the roles are clearer:
249
+ With `rdf-prolog-interchange`, the roles are clearer:
250
250
 
251
251
  - RDF provides Web identifiers, graph boundaries, literals, RDF 1.2 triple terms, and interoperable publication;
252
- - `rdf-prolog-roundtrip` preserves those structures as ordinary ISO Prolog terms;
252
+ - `rdf-prolog-interchange` preserves those structures as ordinary ISO Prolog terms;
253
253
  - EyeProlog applies explicit rules and explores alternatives;
254
254
  - materialized conclusions return to RDF.
255
255
 
@@ -279,7 +279,7 @@ A direct neural interface would change the input/output channel. It would not re
279
279
 
280
280
  ## Reproduce the roundtrip
281
281
 
282
- Assuming `rdf-prolog-roundtrip` and EyeProlog are available on `PATH`:
282
+ Assuming `rdf-prolog-interchange` and EyeProlog are available on `PATH`:
283
283
 
284
284
  ```sh
285
285
  rdf-to-prolog \
@@ -327,5 +327,5 @@ The deepest reason Prolog fits this vision is not nostalgia or syntax. It is tha
327
327
  ## References
328
328
 
329
329
  - Ruben Taelman, [*Symbiotic Knowledge Graphs: A Vision for Semantic Brain-Computer Interfaces*](https://rubensworks.github.io/article-iswc2026-vision-symbiotic-knowledge-graphs/).
330
- - [`eyereasoner/rdf-prolog-roundtrip`](https://github.com/eyereasoner/rdf-prolog-roundtrip) — standalone RDF 1.2 ↔ ISO Prolog roundtripping toolkit.
330
+ - [`eyereasoner/rdf-prolog-interchange`](https://github.com/eyereasoner/rdf-prolog-interchange) — standalone RDF 1.2 ↔ ISO Prolog roundtripping toolkit.
331
331
  - [`eyereasoner/eyeprolog`](https://github.com/eyereasoner/eyeprolog) — ISO Prolog reasoning and proof engine.
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -29,10 +29,10 @@ knowledge_exchange(machine_to_human, recommendation(after_review, riverside, ope
29
29
  knowledge_exchange(rdf_to_prolog, ordinary_rdf4_facts).
30
30
  knowledge_exchange(prolog_to_rdf, materialized_ground_rdf4).
31
31
  pipeline_step(1, 'RDF 1.2 N-Quads: named graphs keep source and governance boundaries explicit').
32
- pipeline_step(2, 'rdf-prolog-roundtrip: RDF becomes ordinary rdf/4 Prolog facts without a solver').
32
+ pipeline_step(2, 'rdf-prolog-interchange: RDF becomes ordinary rdf/4 Prolog facts without a solver').
33
33
  pipeline_step(3, 'EyeProlog: ISO Prolog rules validate candidates, apply review policy, and derive actions').
34
34
  pipeline_step(4, 'EyeProlog: result_rdf/4 materializes accepted knowledge and decisions as ground RDF-shaped facts').
35
- pipeline_step(5, 'rdf-prolog-roundtrip: ground rdf/4 facts become RDF again for publication or federation').
35
+ pipeline_step(5, 'rdf-prolog-interchange: ground rdf/4 facts become RDF again for publication or federation').
36
36
  cognitive_parallel(fact, remembered_assertion).
37
37
  cognitive_parallel(rule, reusable_generalization).
38
38
  cognitive_parallel(query, explicit_question).
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,7 +1,7 @@
1
- % Adapted from rdf-prolog-roundtrip.
1
+ % Adapted from rdf-prolog-interchange.
2
2
  % This standalone program combines generated RDF input with its ISO Prolog rules.
3
3
 
4
- % Generated by rdf-prolog-roundtrip.
4
+ % Generated by rdf-prolog-interchange.
5
5
 
6
6
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
7
7
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -1,4 +1,4 @@
1
- % Generated by rdf-prolog-roundtrip.
1
+ % Generated by rdf-prolog-interchange.
2
2
 
3
3
  % RDF terms use rdf(Subject, Predicate, Object, Graph).
4
4
 
@@ -63,7 +63,7 @@ rdf(iri('https://example.org/city/review/r3'), iri('https://example.org/vocab/no
63
63
  % Rules
64
64
  % Symbiotic knowledge graph rules for EyeProlog.
65
65
  %
66
- % The source rdf/4 facts above are generated by rdf-prolog-roundtrip from
66
+ % The source rdf/4 facts above are generated by rdf-prolog-interchange from
67
67
  % symbiotic-knowledge-graph-input.nq. RDF stays the interchange and storage
68
68
  % model; these rules provide the explicit reasoning and governance layer.
69
69
 
@@ -380,10 +380,10 @@ knowledge_exchange_fact(prolog_to_rdf, materialized_ground_rdf4).
380
380
 
381
381
  pipeline_step(N, Description) :- pipeline_step_fact(N, Description).
382
382
  pipeline_step_fact(1, 'RDF 1.2 N-Quads: named graphs keep source and governance boundaries explicit').
383
- pipeline_step_fact(2, 'rdf-prolog-roundtrip: RDF becomes ordinary rdf/4 Prolog facts without a solver').
383
+ pipeline_step_fact(2, 'rdf-prolog-interchange: RDF becomes ordinary rdf/4 Prolog facts without a solver').
384
384
  pipeline_step_fact(3, 'EyeProlog: ISO Prolog rules validate candidates, apply review policy, and derive actions').
385
385
  pipeline_step_fact(4, 'EyeProlog: result_rdf/4 materializes accepted knowledge and decisions as ground RDF-shaped facts').
386
- pipeline_step_fact(5, 'rdf-prolog-roundtrip: ground rdf/4 facts become RDF again for publication or federation').
386
+ pipeline_step_fact(5, 'rdf-prolog-interchange: ground rdf/4 facts become RDF again for publication or federation').
387
387
 
388
388
  cognitive_parallel(Prolog, Human) :- cognitive_parallel_fact(Prolog, Human).
389
389
  cognitive_parallel_fact(fact, remembered_assertion).
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.61",
6
+ "version": "1.5.63",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/lib/error.pl CHANGED
@@ -21,34 +21,39 @@
21
21
  % raise site: the raise sites throw with [] and this wrapper prepends its
22
22
  % element, so contexts stay proper lists and compose with any enclosing
23
23
  % call_with_error_context/2 (issue #98).
24
+ % The context is named in exactly one place -- error__must_be_throw/1 -- so no
25
+ % raise site hands one over (issue #98). It is a throw helper rather than a
26
+ % call_with_error_context/2 wrapper because wrapping a Prolog goal in catch/3
27
+ % costs a child Solver on every call, and must_be/2 succeeds almost always.
24
28
  must_be(Type, Term) :-
25
- call_with_error_context(
26
- ( var(Type) -> instantiation_error
27
- ; error__must_be(Type, Term)
28
- ),
29
- predicate-must_be/2).
29
+ ( var(Type) -> error__must_be_throw(instantiation_error)
30
+ ; error__must_be(Type, Term)
31
+ ).
32
+
33
+ error__must_be_throw(Formal) :-
34
+ throw(error(Formal, [predicate-must_be/2])).
30
35
 
31
36
  error__must_be(integer, Term) :- !,
32
- ( var(Term) -> instantiation_error
37
+ ( var(Term) -> error__must_be_throw(instantiation_error)
33
38
  ; integer(Term) -> true
34
- ; type_error(integer, Term)
39
+ ; error__must_be_throw(type_error(integer, Term))
35
40
  ).
36
41
  error__must_be(atom, Term) :- !,
37
- ( var(Term) -> instantiation_error
42
+ ( var(Term) -> error__must_be_throw(instantiation_error)
38
43
  ; atom(Term) -> true
39
- ; type_error(atom, Term)
44
+ ; error__must_be_throw(type_error(atom, Term))
40
45
  ).
41
46
  error__must_be(number, Term) :- !,
42
- ( var(Term) -> instantiation_error
47
+ ( var(Term) -> error__must_be_throw(instantiation_error)
43
48
  ; number(Term) -> true
44
- ; type_error(number, Term)
49
+ ; error__must_be_throw(type_error(number, Term))
45
50
  ).
46
51
  error__must_be(var, Term) :- !,
47
52
  ( var(Term) -> true
48
53
  ; throw(error(uninstantiation_error(Term), []))
49
54
  ).
50
55
  error__must_be(ground, Term) :- !,
51
- ( ground(Term) -> true ; instantiation_error ).
56
+ ( ground(Term) -> true ; error__must_be_throw(instantiation_error) ).
52
57
  error__must_be(acyclic, Term) :- !,
53
58
  ( acyclic_term(Term) -> true ; type_error(acyclic_term, Term) ).
54
59
  error__must_be(list, Term) :- !,
@@ -56,23 +61,23 @@ error__must_be(list, Term) :- !,
56
61
  error__must_be(list(Type), Term) :- !,
57
62
  error__proper_list_of(Term, Type).
58
63
  error__must_be(pair, Term) :- !,
59
- ( var(Term) -> instantiation_error
64
+ ( var(Term) -> error__must_be_throw(instantiation_error)
60
65
  ; Term = _-_ -> true
61
- ; type_error(pair, Term)
66
+ ; error__must_be_throw(type_error(pair, Term))
62
67
  ).
63
68
  error__must_be(not_less_than_zero, Term) :- !,
64
69
  must_be(integer, Term),
65
70
  ( Term >= 0 -> true ; domain_error(not_less_than_zero, Term) ).
66
71
  error__must_be(Type, Term) :-
67
- ( var(Term) -> instantiation_error
68
- ; type_error(Type, Term)
72
+ ( var(Term) -> error__must_be_throw(instantiation_error)
73
+ ; error__must_be_throw(type_error(Type, Term))
69
74
  ).
70
75
 
71
76
  error__proper_list([]) :- !.
72
77
  error__proper_list([_|Tail]) :- !, error__proper_list(Tail).
73
78
  error__proper_list(Term) :-
74
- ( var(Term) -> instantiation_error
75
- ; type_error(list, Term)
79
+ ( var(Term) -> error__must_be_throw(instantiation_error)
80
+ ; error__must_be_throw(type_error(list, Term))
76
81
  ).
77
82
 
78
83
  error__proper_list_of([], _) :- !.
@@ -80,7 +85,7 @@ error__proper_list_of([Head|Tail], Type) :- !,
80
85
  must_be(Type, Head),
81
86
  error__proper_list_of(Tail, Type).
82
87
  error__proper_list_of(Term, _) :-
83
- ( var(Term) -> instantiation_error
88
+ ( var(Term) -> error__must_be_throw(instantiation_error)
84
89
  ; type_error(list, Term)
85
90
  ).
86
91
 
@@ -138,12 +143,15 @@ call_with_error_context(Goal, Pair) :-
138
143
  ( copy_term(Pair, Element),
139
144
  throw(error(Error, [Element|Context])) )).
140
145
 
141
- % The element must be a pair (issue #99). This cannot go through must_be/2:
142
- % must_be/2 declares its own context with call_with_error_context/2, so
143
- % checking with must_be/2 here would recurse. The reported context matches
144
- % what must_be(pair, _) would have produced.
146
+ % The element must be a pair (issue #99). The test is inlined rather than
147
+ % delegated to must_be(pair, _) so that the wrapper stays independent of the
148
+ % rest of this module. The reported context matches what must_be(pair, _)
149
+ % produces.
150
+ % Written as indexed clauses rather than an if-then-else: this runs on every
151
+ % call_with_error_context/2 call, and an if-then-else costs several times what
152
+ % first-argument clause selection does.
153
+ error__require_pair(Pair) :- var(Pair), !,
154
+ throw(error(instantiation_error, [predicate-must_be/2])).
155
+ error__require_pair(_-_) :- !.
145
156
  error__require_pair(Pair) :-
146
- ( var(Pair) -> throw(error(instantiation_error, [predicate-must_be/2]))
147
- ; Pair = _-_ -> true
148
- ; throw(error(type_error(pair, Pair), [predicate-must_be/2]))
149
- ).
157
+ throw(error(type_error(pair, Pair), [predicate-must_be/2])).
package/src/lib/random.pl CHANGED
@@ -10,7 +10,7 @@
10
10
  :- module(random, [maybe/0, maybe/1, maybe/2, random/1, random/3, random_integer/3, set_random/1]).
11
11
 
12
12
  :- use_module(library(iso_ext), [bb_get/2, bb_put/2]).
13
- :- use_module(library(error), [call_with_error_context/2, instantiation_error/0, type_error/2]).
13
+
14
14
 
15
15
  maybe :-
16
16
  random_integer(0, 2, 0).
@@ -31,7 +31,7 @@ random(Value) :-
31
31
  % Context declared once per predicate instead of at each raise site, so the
32
32
  % raise sites throw with [] and contexts stay proper composable lists.
33
33
  random_integer(Lower, Upper, R) :-
34
- call_with_error_context(random__check_integer_range(Lower, Upper), predicate-random_integer/3),
34
+ random__check_integer_range(Lower, Upper),
35
35
  Lower < Upper,
36
36
  random__current_seed(Seed0),
37
37
  random(Seed0, _, Seed),
@@ -39,28 +39,31 @@ random_integer(Lower, Upper, R) :-
39
39
  R is Lower + Seed mod (Upper - Lower).
40
40
 
41
41
  set_random(Seed) :-
42
- call_with_error_context(random__set_seed(Seed), predicate-set_random/1).
42
+ random__set_seed(Seed).
43
+
44
+ random__throw(Formal, Predicate) :-
45
+ throw(error(Formal, [predicate-Predicate])).
43
46
 
44
47
  random__check_integer_range(Lower, Upper) :-
45
- ( var(Lower) -> instantiation_error
46
- ; var(Upper) -> instantiation_error
48
+ ( var(Lower) -> random__throw(instantiation_error, random_integer/3)
49
+ ; var(Upper) -> random__throw(instantiation_error, random_integer/3)
47
50
  ; integer(Lower) -> true
48
- ; type_error(integer, Lower)
51
+ ; random__throw(type_error(integer, Lower), random_integer/3)
49
52
  ),
50
53
  ( integer(Upper) -> true
51
- ; type_error(integer, Upper)
54
+ ; random__throw(type_error(integer, Upper), random_integer/3)
52
55
  ).
53
56
 
54
57
  random__set_seed(Seed) :-
55
- ( var(Seed) -> instantiation_error
58
+ ( var(Seed) -> random__throw(instantiation_error, set_random/1)
56
59
  ; Seed = seed(S) ->
57
- ( var(S) -> instantiation_error
60
+ ( var(S) -> random__throw(instantiation_error, set_random/1)
58
61
  ; integer(S) ->
59
62
  random__random_normalize_seed(S, Normalized),
60
63
  bb_put('$random_seed', Normalized)
61
- ; type_error(integer, S)
64
+ ; random__throw(type_error(integer, S), set_random/1)
62
65
  )
63
- ; type_error(random_state, Seed)
66
+ ; random__throw(type_error(random_state, Seed), set_random/1)
64
67
  ).
65
68
 
66
69
  random__current_seed(Seed) :- bb_get('$random_seed', Seed), !.
package/src/lib/si.pl CHANGED
@@ -8,6 +8,7 @@
8
8
  character_si/1,
9
9
  term_si/1,
10
10
  chars_si/1,
11
+ compare_si/3,
11
12
  dif_si/2,
12
13
  not_si/1,
13
14
  when_si/2
@@ -16,24 +17,24 @@
16
17
  :- meta_predicate(not_si(0)).
17
18
  :- meta_predicate(when_si(+, 0)).
18
19
 
19
- atom_si(A) :- ( var(A) -> throw(error(instantiation_error, atom_si/1)) ; atom(A) ).
20
- integer_si(I) :- ( var(I) -> throw(error(instantiation_error, integer_si/1)) ; integer(I) ).
21
- atomic_si(A) :- ( var(A) -> throw(error(instantiation_error, atomic_si/1)) ; atomic(A) ).
20
+ atom_si(A) :- ( var(A) -> throw(error(instantiation_error, [predicate-atom_si/1])) ; atom(A) ).
21
+ integer_si(I) :- ( var(I) -> throw(error(instantiation_error, [predicate-integer_si/1])) ; integer(I) ).
22
+ atomic_si(A) :- ( var(A) -> throw(error(instantiation_error, [predicate-atomic_si/1])) ; atomic(A) ).
22
23
 
23
24
  list_si(List) :- si__list(List).
24
25
  si__list([]).
25
26
  si__list([_|Tail]) :- !, si__list(Tail).
26
27
  si__list(Term) :-
27
- ( var(Term) -> throw(error(instantiation_error, list_si/1)) ; fail ).
28
+ ( var(Term) -> throw(error(instantiation_error, [predicate-list_si/1])) ; fail ).
28
29
 
29
30
  character_si(C) :-
30
- ( var(C) -> throw(error(instantiation_error, character_si/1))
31
+ ( var(C) -> throw(error(instantiation_error, [predicate-character_si/1]))
31
32
  ; atom(C), atom_length(C, 1)
32
33
  ).
33
34
 
34
35
  term_si(Term) :-
35
36
  ( ground(Term) -> acyclic_term(Term)
36
- ; throw(error(instantiation_error, term_si/1))
37
+ ; throw(error(instantiation_error, [predicate-term_si/1]))
37
38
  ).
38
39
 
39
40
  chars_si(Chars) :-
@@ -44,19 +45,56 @@ si__chars([C|Cs]) :- character_si(C), si__chars(Cs).
44
45
 
45
46
  dif_si(X, Y) :-
46
47
  X \== Y,
47
- ( X \= Y -> true ; throw(error(instantiation_error, dif_si/2)) ).
48
+ ( X \= Y -> true ; throw(error(instantiation_error, [predicate-dif_si/2])) ).
48
49
 
49
50
  not_si(Goal) :- term_si(Goal), \+ Goal.
50
51
 
51
52
  when_si(Condition, Goal) :-
52
53
  ( si__condition(Condition) ->
53
54
  ( call(Condition) -> call(Goal)
54
- ; throw(error(instantiation_error, when_si/2)) )
55
+ ; throw(error(instantiation_error, [predicate-when_si/2])) )
55
56
  ; throw(error(domain_error(when_condition_si, Condition), when_si/2))
56
57
  ).
57
58
 
58
- si__condition(Condition) :- var(Condition), !, throw(error(instantiation_error, when_si/2)).
59
+ si__condition(Condition) :- var(Condition), !, throw(error(instantiation_error, [predicate-when_si/2])).
59
60
  si__condition(ground(_)).
60
61
  si__condition(nonvar(_)).
61
62
  si__condition((A,B)) :- si__condition(A), si__condition(B).
62
63
  si__condition((A;B)) :- si__condition(A), si__condition(B).
64
+
65
+ % compare_si(Order, A, B) holds when compare(Order, A, B) holds for *every*
66
+ % instance of A and B, and raises an instantiation_error otherwise. The point
67
+ % is to raise it as rarely as possible: an unbound variable only matters when
68
+ % it is what decides the ordering. So f(X) @< g(Y) is decided by the functor
69
+ % names, f(X,a) @< f(X,b) by the second arguments, and X == X gives (=), while
70
+ % f(a) vs f(Y) and X vs 1 are genuinely undecided.
71
+ compare_si(Order, A, B) :-
72
+ ( A == B
73
+ -> Order = (=)
74
+ ; si__order_decided(A, B)
75
+ -> compare(Order, A, B)
76
+ ; throw(error(instantiation_error, [predicate-compare_si/3]))
77
+ ).
78
+
79
+ % Both arguments are known to be non-identical here.
80
+ si__order_decided(A, B) :- ( var(A) ; var(B) ), !, fail.
81
+ si__order_decided(A, B) :-
82
+ compound(A), compound(B), !,
83
+ functor(A, NameA, ArityA),
84
+ functor(B, NameB, ArityB),
85
+ ( ArityA =\= ArityB -> true
86
+ ; NameA \== NameB -> true
87
+ ; A =.. [_|ArgsA],
88
+ B =.. [_|ArgsB],
89
+ si__args_decided(ArgsA, ArgsB)
90
+ ).
91
+ % Otherwise both are non-variables and at least one is atomic, so either the
92
+ % type order or the values themselves settle it and no instantiation can
93
+ % change the outcome.
94
+ si__order_decided(_, _).
95
+
96
+ si__args_decided([A|As], [B|Bs]) :-
97
+ ( A == B
98
+ -> si__args_decided(As, Bs)
99
+ ; si__order_decided(A, B)
100
+ ).
@@ -90,6 +90,7 @@ export const eyePrologLibraryAutoload = Object.freeze({
90
90
  "chars_utf8bytes/2": "charsio",
91
91
  "circuit/1": "clpz",
92
92
  "clpz_t/2": "clpz",
93
+ "compare_si/3": "si",
93
94
  "complement/2": "ugraphs",
94
95
  "compose/3": "ugraphs",
95
96
  "cond_t/3": "reif",