eyeprolog 1.0.0 → 1.0.2
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 +6 -0
- package/examples/book/README.md +45 -19
- package/examples/book/chapter-01/02-child.pl +1 -3
- package/examples/book/chapter-02/01-same_shape.pl +2 -0
- package/examples/book/chapter-04/01-ancestor.pl +3 -0
- package/examples/book/chapter-10/01-color.pl +14 -0
- package/examples/book/chapter-21/01-parent.pl +7 -0
- package/examples/book/chapter-22/04-sentence.pl +19 -0
- package/examples/book/chapter-24/01-worker.pl +17 -0
- package/examples/book/chapter-25/04-permit.pl +9 -0
- package/examples/book/chapter-26/02-triple.pl +9 -2
- package/examples/book/chapter-26/03-triple-2.pl +2 -0
- package/examples/book/chapter-28/04-integer_rectangle.pl +5 -0
- package/examples/book/chapter-29/01-counterexample_to_odd_square.pl +7 -0
- package/examples/book/chapter-31/01-edge.pl +6 -0
- package/examples/book/chapter-31/02-program.pl +6 -0
- package/examples/book/chapter-31/03-double.pl +13 -0
- package/examples/book/chapter-32/03-candidate_debug.pl +7 -0
- package/examples/book/chapter-32/04-reference_square.pl +12 -0
- package/examples/book/chapter-39/01-answer.pl +5 -0
- package/examples/book/chapter-39/02-answer-2.pl +6 -0
- package/examples/book/chapter-39/03-answer-3.pl +10 -0
- package/examples/book/chapter-39/04-cost.pl +10 -0
- package/examples/book/chapter-39/05-message.pl +16 -0
- package/package.json +1 -1
- package/test/run-regression.mjs +5 -0
- package/the-art-of-eyeprolog.md +139 -33
- /package/examples/book/chapter-02/{01-measurement.pl → 02-measurement.pl} +0 -0
- /package/examples/book/chapter-02/{02-label.pl → 03-label.pl} +0 -0
- /package/examples/book/chapter-04/{01-path.pl → 02-path.pl} +0 -0
- /package/examples/book/chapter-10/{01-plan.pl → 02-plan.pl} +0 -0
- /package/examples/book/chapter-21/{01-grandparent.pl → 02-grandparent.pl} +0 -0
- /package/examples/book/chapter-21/{02-loop_edge.pl → 03-loop_edge.pl} +0 -0
- /package/examples/book/chapter-21/{03-eligible.pl → 04-eligible.pl} +0 -0
- /package/examples/book/chapter-21/{04-grows.pl → 05-grows.pl} +0 -0
- /package/examples/book/chapter-22/{04-evaluate.pl → 05-evaluate.pl} +0 -0
- /package/examples/book/chapter-22/{05-lookup.pl → 06-lookup.pl} +0 -0
- /package/examples/book/chapter-22/{06-simplify.pl → 07-simplify.pl} +0 -0
- /package/examples/book/chapter-24/{01-simple_path.pl → 02-simple_path.pl} +0 -0
- /package/examples/book/chapter-24/{02-reachable.pl → 03-reachable.pl} +0 -0
- /package/examples/book/chapter-24/{03-best_plan.pl → 04-best_plan.pl} +0 -0
- /package/examples/book/chapter-25/{04-incompatible_status.pl → 05-incompatible_status.pl} +0 -0
- /package/examples/book/chapter-26/{03-edge.pl → 04-edge.pl} +0 -0
- /package/examples/book/chapter-28/{04-preserves_combine.pl → 05-preserves_combine.pl} +0 -0
- /package/examples/book/chapter-29/{01-noncommuting_pair.pl → 02-noncommuting_pair.pl} +0 -0
package/README.md
CHANGED
|
@@ -5,6 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
EyeProlog turns portable ISO Prolog programs into answers and inspectable proofs.
|
|
7
7
|
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://eyereasoner.github.io/eyeprolog/the-art-of-eyeprolog">
|
|
10
|
+
<img src="book-assets/title-page.svg" alt="Read The Art of EyeProlog" width="180">
|
|
11
|
+
</a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
8
14
|
**[Book — *The Art of EyeProlog*](https://eyereasoner.github.io/eyeprolog/the-art-of-eyeprolog)** ·
|
|
9
15
|
**[Why EyeProlog?](https://eyereasoner.github.io/eyeprolog/why-eyeprolog)** ·
|
|
10
16
|
**[Playground](https://eyereasoner.github.io/eyeprolog/playground)**
|
package/examples/book/README.md
CHANGED
|
@@ -18,8 +18,9 @@ npm run generate
|
|
|
18
18
|
|
|
19
19
|
## Chapter 2: Terms, variables, and substitution
|
|
20
20
|
|
|
21
|
-
- [01-
|
|
22
|
-
- [02-
|
|
21
|
+
- [01-same_shape.pl](chapter-02/01-same_shape.pl) — Unification
|
|
22
|
+
- [02-measurement.pl](chapter-02/02-measurement.pl)
|
|
23
|
+
- [03-label.pl](chapter-02/03-label.pl)
|
|
23
24
|
|
|
24
25
|
## Chapter 3: Rules and their two readings
|
|
25
26
|
|
|
@@ -37,7 +38,8 @@ npm run generate
|
|
|
37
38
|
|
|
38
39
|
## Chapter 4: Recursion: describing reachability
|
|
39
40
|
|
|
40
|
-
- [01-
|
|
41
|
+
- [01-ancestor.pl](chapter-04/01-ancestor.pl)
|
|
42
|
+
- [02-path.pl](chapter-04/02-path.pl) — Constructing the recursive argument
|
|
41
43
|
|
|
42
44
|
## Chapter 5: Lists as relations
|
|
43
45
|
|
|
@@ -70,7 +72,8 @@ npm run generate
|
|
|
70
72
|
|
|
71
73
|
## Chapter 10: From puzzles to models
|
|
72
74
|
|
|
73
|
-
- [01-
|
|
75
|
+
- [01-color.pl](chapter-10/01-color.pl)
|
|
76
|
+
- [02-plan.pl](chapter-10/02-plan.pl)
|
|
74
77
|
|
|
75
78
|
## Chapter 11: Queries, answers, and proofs
|
|
76
79
|
|
|
@@ -113,19 +116,21 @@ npm run generate
|
|
|
113
116
|
|
|
114
117
|
## Chapter 21: Reading the computation
|
|
115
118
|
|
|
116
|
-
- [01-
|
|
117
|
-
- [02-
|
|
118
|
-
- [03-
|
|
119
|
-
- [04-
|
|
119
|
+
- [01-parent.pl](chapter-21/01-parent.pl)
|
|
120
|
+
- [02-grandparent.pl](chapter-21/02-grandparent.pl) — Substitutions accumulate
|
|
121
|
+
- [03-loop_edge.pl](chapter-21/03-loop_edge.pl)
|
|
122
|
+
- [04-eligible.pl](chapter-21/04-eligible.pl) — Failure rewinds choices, not facts
|
|
123
|
+
- [05-grows.pl](chapter-21/05-grows.pl) — Variants, cycles, and tables
|
|
120
124
|
|
|
121
125
|
## Chapter 22: Trees, languages, and symbolic evaluation
|
|
122
126
|
|
|
123
127
|
- [01-tree.pl](chapter-22/01-tree.pl)
|
|
124
128
|
- [02-tree_member.pl](chapter-22/02-tree_member.pl)
|
|
125
129
|
- [03-mirror.pl](chapter-22/03-mirror.pl) — Transforming a tree
|
|
126
|
-
- [04-
|
|
127
|
-
- [05-
|
|
128
|
-
- [06-
|
|
130
|
+
- [04-sentence.pl](chapter-22/04-sentence.pl) — A grammar without special syntax
|
|
131
|
+
- [05-evaluate.pl](chapter-22/05-evaluate.pl) — Interpreting an expression
|
|
132
|
+
- [06-lookup.pl](chapter-22/06-lookup.pl)
|
|
133
|
+
- [07-simplify.pl](chapter-22/07-simplify.pl) — Rewriting symbolic expressions
|
|
129
134
|
|
|
130
135
|
## Chapter 23: Transforming programs
|
|
131
136
|
|
|
@@ -140,22 +145,25 @@ npm run generate
|
|
|
140
145
|
|
|
141
146
|
## Chapter 24: Designing finite search
|
|
142
147
|
|
|
143
|
-
- [01-
|
|
144
|
-
- [02-
|
|
145
|
-
- [03-
|
|
148
|
+
- [01-worker.pl](chapter-24/01-worker.pl) — Generate, constrain, describe
|
|
149
|
+
- [02-simple_path.pl](chapter-24/02-simple_path.pl) — Search over states
|
|
150
|
+
- [03-reachable.pl](chapter-24/03-reachable.pl) — Existence, one witness, and all witnesses
|
|
151
|
+
- [04-best_plan.pl](chapter-24/04-best_plan.pl) — Optimization is search plus an order
|
|
146
152
|
|
|
147
153
|
## Chapter 25: Case study: an auditable decision service
|
|
148
154
|
|
|
149
155
|
- [01-person.pl](chapter-25/01-person.pl) — Source and concept layers
|
|
150
156
|
- [02-active_badge.pl](chapter-25/02-active_badge.pl)
|
|
151
157
|
- [03-in_good_standing.pl](chapter-25/03-in_good_standing.pl) — Closed-world choice
|
|
152
|
-
- [04-
|
|
158
|
+
- [04-permit.pl](chapter-25/04-permit.pl) — Decision, reasons, and proof
|
|
159
|
+
- [05-incompatible_status.pl](chapter-25/05-incompatible_status.pl) — Integrity before decisions
|
|
153
160
|
|
|
154
161
|
## Chapter 26: A proof can be a computation
|
|
155
162
|
|
|
156
163
|
- [01-mortal.pl](chapter-26/01-mortal.pl)
|
|
157
|
-
- [02-triple.pl](chapter-26/02-triple.pl) —
|
|
158
|
-
- [03-
|
|
164
|
+
- [02-triple.pl](chapter-26/02-triple.pl) — Answers are existential witnesses
|
|
165
|
+
- [03-triple-2.pl](chapter-26/03-triple-2.pl) — Proof objects and proof checking
|
|
166
|
+
- [04-edge.pl](chapter-26/04-edge.pl) — The least model as mathematical closure
|
|
159
167
|
|
|
160
168
|
## Chapter 27: Recursion is induction in motion
|
|
161
169
|
|
|
@@ -168,16 +176,26 @@ npm run generate
|
|
|
168
176
|
- [01-program.pl](chapter-28/01-program.pl) — Unification is structural equation solving
|
|
169
177
|
- [02-triangle.pl](chapter-28/02-triangle.pl) — Symmetry reduces search
|
|
170
178
|
- [03-rectangle.pl](chapter-28/03-rectangle.pl) — Relations reveal inverse problems
|
|
171
|
-
- [04-
|
|
179
|
+
- [04-integer_rectangle.pl](chapter-28/04-integer_rectangle.pl)
|
|
180
|
+
- [05-preserves_combine.pl](chapter-28/05-preserves_combine.pl) — Composition, homomorphism, and reusable laws
|
|
172
181
|
|
|
173
182
|
## Chapter 29: Search as experimental mathematics
|
|
174
183
|
|
|
175
|
-
- [01-
|
|
184
|
+
- [01-counterexample_to_odd_square.pl](chapter-29/01-counterexample_to_odd_square.pl) — Examples suggest; proofs compel
|
|
185
|
+
- [02-noncommuting_pair.pl](chapter-29/02-noncommuting_pair.pl) — One counterexample has asymmetric power
|
|
186
|
+
|
|
187
|
+
## Chapter 31: Testing a theory
|
|
188
|
+
|
|
189
|
+
- [01-edge.pl](chapter-31/01-edge.pl) — Positive and negative observers
|
|
190
|
+
- [02-program.pl](chapter-31/02-program.pl)
|
|
191
|
+
- [03-double.pl](chapter-31/03-double.pl) — Properties over finite domains
|
|
176
192
|
|
|
177
193
|
## Chapter 32: Debugging by meaning, search, and proof
|
|
178
194
|
|
|
179
195
|
- [01-eligible.pl](chapter-32/01-eligible.pl) — Follow bindings from left to right
|
|
180
196
|
- [02-eligible-2.pl](chapter-32/02-eligible-2.pl)
|
|
197
|
+
- [03-candidate_debug.pl](chapter-32/03-candidate_debug.pl) — Create diagnostic relations
|
|
198
|
+
- [04-reference_square.pl](chapter-32/04-reference_square.pl) — Compare specification and implementation
|
|
181
199
|
|
|
182
200
|
## Chapter 33: A pattern catalog for reasoning
|
|
183
201
|
|
|
@@ -215,3 +233,11 @@ npm run generate
|
|
|
215
233
|
## Chapter 38: Language and ISO profile
|
|
216
234
|
|
|
217
235
|
- [01-city.pl](chapter-38/01-city.pl)
|
|
236
|
+
|
|
237
|
+
## Chapter 39: Built-in predicates by programming role
|
|
238
|
+
|
|
239
|
+
- [01-answer.pl](chapter-39/01-answer.pl) — The EyeProlog library
|
|
240
|
+
- [02-answer-2.pl](chapter-39/02-answer-2.pl)
|
|
241
|
+
- [03-answer-3.pl](chapter-39/03-answer-3.pl)
|
|
242
|
+
- [04-cost.pl](chapter-39/04-cost.pl)
|
|
243
|
+
- [05-message.pl](chapter-39/05-message.pl)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 22 — A grammar without special syntax.
|
|
2
|
+
sentence(Input, Rest) :-
|
|
3
|
+
noun_phrase(Input, AfterNoun),
|
|
4
|
+
verb_phrase(AfterNoun, Rest).
|
|
5
|
+
|
|
6
|
+
noun_phrase([the | Input], Rest) :- noun(Input, Rest).
|
|
7
|
+
noun_phrase([a | Input], Rest) :- noun(Input, Rest).
|
|
8
|
+
|
|
9
|
+
noun([robot | Rest], Rest).
|
|
10
|
+
noun([scientist | Rest], Rest).
|
|
11
|
+
|
|
12
|
+
verb_phrase(Input, Rest) :-
|
|
13
|
+
verb(Input, AfterVerb),
|
|
14
|
+
noun_phrase(AfterVerb, Rest).
|
|
15
|
+
|
|
16
|
+
verb([helps | Rest], Rest).
|
|
17
|
+
verb([observes | Rest], Rest).
|
|
18
|
+
|
|
19
|
+
complete_sentence(Words) :- sentence(Words, []).
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 24 — Generate, constrain, describe.
|
|
2
|
+
worker(ada).
|
|
3
|
+
worker(byron).
|
|
4
|
+
worker(clara).
|
|
5
|
+
|
|
6
|
+
task(inspect).
|
|
7
|
+
task(repair).
|
|
8
|
+
|
|
9
|
+
qualified(ada, inspect).
|
|
10
|
+
qualified(byron, repair).
|
|
11
|
+
qualified(clara, inspect).
|
|
12
|
+
qualified(clara, repair).
|
|
13
|
+
|
|
14
|
+
assignment(Worker, Task) :-
|
|
15
|
+
worker(Worker),
|
|
16
|
+
task(Task),
|
|
17
|
+
qualified(Worker, Task).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 25 — Decision, reasons, and proof.
|
|
2
|
+
permit(Person, Zone) :-
|
|
3
|
+
active_badge(Person, Badge),
|
|
4
|
+
cleared_for(Badge, Zone),
|
|
5
|
+
prepared_for(Person, Zone),
|
|
6
|
+
in_good_standing(Person).
|
|
7
|
+
|
|
8
|
+
reason(Person, Zone, badge_and_training_verified) :-
|
|
9
|
+
permit(Person, Zone).
|
|
@@ -1,2 +1,9 @@
|
|
|
1
|
-
% From The Art of EyeProlog, Chapter 26 —
|
|
2
|
-
triple(
|
|
1
|
+
% From The Art of EyeProlog, Chapter 26 — Answers are existential witnesses.
|
|
2
|
+
triple(A, B, C) :-
|
|
3
|
+
between(1, 20, A),
|
|
4
|
+
between(A, 20, B),
|
|
5
|
+
between(B, 20, C),
|
|
6
|
+
(AA is A * A),
|
|
7
|
+
(BB is B * B),
|
|
8
|
+
(Sum is AA + BB),
|
|
9
|
+
(Sum is C * C).
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 31 — Properties over finite domains.
|
|
2
|
+
double(N, D) :- (D is N + N).
|
|
3
|
+
|
|
4
|
+
double_is_even(N) :-
|
|
5
|
+
double(N, D),
|
|
6
|
+
(0 is D mod 2).
|
|
7
|
+
|
|
8
|
+
bounded_double_law :-
|
|
9
|
+
\+ bounded_double_counterexample.
|
|
10
|
+
|
|
11
|
+
bounded_double_counterexample :-
|
|
12
|
+
between(-100, 100, N),
|
|
13
|
+
\+ double_is_even(N).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 32 — Compare specification and implementation.
|
|
2
|
+
reference_square(N, S) :-
|
|
3
|
+
between(0, 20, N),
|
|
4
|
+
(S is N * N).
|
|
5
|
+
|
|
6
|
+
optimized_square(N, S) :-
|
|
7
|
+
between(0, 20, N),
|
|
8
|
+
(S is N * N).
|
|
9
|
+
|
|
10
|
+
disagreement(N, S) :-
|
|
11
|
+
reference_square(N, S),
|
|
12
|
+
\+ optimized_square(N, S).
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 39 — The EyeProlog library.
|
|
2
|
+
answer(square, S) :- (S is 12 * 12).
|
|
3
|
+
answer(day_count, N) :- between(3, 5, N).
|
|
4
|
+
answer(age, D) :- difference('2026-07-28', '2020-05-20', D).
|
|
5
|
+
answer(random_pair, [A,B]) :- random(42, A, S), random(S, B, _).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 39.
|
|
2
|
+
answer(words, Words) :-
|
|
3
|
+
trim(' Logic Made Visible ', Clean),
|
|
4
|
+
lowercase(Clean, Lower),
|
|
5
|
+
split(Lower, ' ', Words).
|
|
6
|
+
|
|
7
|
+
answer(captures, Context) :-
|
|
8
|
+
matches('Ada Lovelace',
|
|
9
|
+
'^(?<first>[A-Za-z]+) (?<last>[A-Za-z]+)$',
|
|
10
|
+
Context).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 39.
|
|
2
|
+
cost(a, 8).
|
|
3
|
+
cost(b, 3).
|
|
4
|
+
cost(c, 3).
|
|
5
|
+
|
|
6
|
+
answer(count, N) :- countall(cost(_, _), N).
|
|
7
|
+
answer(best(Name), Cost) :-
|
|
8
|
+
aggregate_min(CandidateCost, CandidateName,
|
|
9
|
+
cost(CandidateName, CandidateCost),
|
|
10
|
+
Cost, Name).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
% From The Art of EyeProlog, Chapter 39.
|
|
2
|
+
message(event_17,
|
|
3
|
+
(severity(high), source(sensor_3), reading(temp, 91))).
|
|
4
|
+
|
|
5
|
+
context_member((Left, _right), Member) :- context_member(Left, Member).
|
|
6
|
+
context_member((_left, Right), Member) :- context_member(Right, Member).
|
|
7
|
+
context_member(Member, Member) :- Member \= (_left, _right).
|
|
8
|
+
|
|
9
|
+
context_parts(Context, Name, Args) :-
|
|
10
|
+
context_member(Context, Member),
|
|
11
|
+
(Member =.. [Name | Args]),
|
|
12
|
+
atom(Name).
|
|
13
|
+
|
|
14
|
+
answer(field(Name, Args)) :-
|
|
15
|
+
message(event_17, Context),
|
|
16
|
+
context_parts(Context, Name, Args).
|
package/package.json
CHANGED
package/test/run-regression.mjs
CHANGED
|
@@ -1960,6 +1960,11 @@ function documentationSourceStyleIssues() {
|
|
|
1960
1960
|
if (/\bv\d+\.\d+(?:\.\d+)?\b/i.test(text)) {
|
|
1961
1961
|
issues.push('the-art-of-eyeprolog.md: describe the current system instead of release chronology');
|
|
1962
1962
|
}
|
|
1963
|
+
for (const block of text.matchAll(/^```eyeprolog\s*\n([\s\S]*?)^```\s*$/gm)) {
|
|
1964
|
+
if (/^\s*(?:eyeprolog|node|npm)\b/m.test(block[1])) {
|
|
1965
|
+
issues.push('the-art-of-eyeprolog.md: keep host commands outside eyeprolog code fences');
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1963
1968
|
return issues;
|
|
1964
1969
|
}
|
|
1965
1970
|
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
<img src="book-assets/title-page.svg" alt="Front page for The Art of EyeProlog, presenting ISO Prolog rules and inspectable proofs." width="720">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
imec.** This book is licensed under [Creative Commons Attribution 4.0
|
|
5
|
+
This book is licensed under [Creative Commons Attribution 4.0
|
|
7
6
|
International](https://creativecommons.org/licenses/by/4.0/). You may copy,
|
|
8
7
|
share, and adapt it for any purpose, including commercially; please give
|
|
9
8
|
appropriate credit, link to the licence, and indicate changes.
|
|
@@ -60,11 +59,10 @@ Robert Kowalski's phrase “algorithm = logic + control” names this separation
|
|
|
60
59
|
EyeProlog's focused surface makes it unusually easy to see in running examples.
|
|
61
60
|
|
|
62
61
|
Complete EyeProlog code displays from the book are also available as files under
|
|
63
|
-
[`examples/book/`](https://github.com/eyereasoner/eyeprolog/tree/main/examples/book/), grouped by chapter. From a source checkout
|
|
64
|
-
|
|
62
|
+
[`examples/book/`](https://github.com/eyereasoner/eyeprolog/tree/main/examples/book/), grouped by chapter. From a source checkout
|
|
63
|
+
with Node.js 18 or newer, run the CLI directly:
|
|
65
64
|
|
|
66
65
|
```sh
|
|
67
|
-
npm install
|
|
68
66
|
node bin/eyeprolog.js examples/socrates.pl
|
|
69
67
|
```
|
|
70
68
|
|
|
@@ -357,16 +355,20 @@ parent(clara, diego).
|
|
|
357
355
|
Each line is a **fact**. `parent/2` is a relation: the name is `parent` and the
|
|
358
356
|
arity is two. Arity matters. `parent/2` and `parent/3` are different predicates.
|
|
359
357
|
|
|
360
|
-
A **query
|
|
358
|
+
A host-supplied **query** selects the relation whose ground answers EyeProlog
|
|
359
|
+
prints:
|
|
361
360
|
|
|
362
361
|
```eyeprolog
|
|
363
362
|
child(Child, Parent) :- parent(Parent, Child).
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
```sh
|
|
364
366
|
eyeprolog --goal 'child(X, Y)' program.pl
|
|
365
367
|
```
|
|
366
368
|
|
|
367
369
|
The answers are:
|
|
368
370
|
|
|
369
|
-
```
|
|
371
|
+
```text
|
|
370
372
|
child(byron, ada).
|
|
371
373
|
child(clara, byron).
|
|
372
374
|
child(diego, clara).
|
|
@@ -479,7 +481,9 @@ EyeProlog exposes unification as `=/2`:
|
|
|
479
481
|
|
|
480
482
|
```eyeprolog
|
|
481
483
|
same_shape(Pair) :- (Pair = pair(X, X)).
|
|
484
|
+
```
|
|
482
485
|
|
|
486
|
+
```sh
|
|
483
487
|
eyeprolog --goal 'same_shape(pair(red, red))' program.pl
|
|
484
488
|
eyeprolog --goal 'same_shape(pair(red, blue))' program.pl
|
|
485
489
|
```
|
|
@@ -797,6 +801,9 @@ parent, or a parent of an ancestor:
|
|
|
797
801
|
```eyeprolog
|
|
798
802
|
ancestor(X, Y) :- parent(X, Y).
|
|
799
803
|
ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
```sh
|
|
800
807
|
eyeprolog --goal 'ancestor(X, Y)' program.pl
|
|
801
808
|
```
|
|
802
809
|
|
|
@@ -1222,6 +1229,9 @@ coloring(A, B, C) :-
|
|
|
1222
1229
|
(A \= C).
|
|
1223
1230
|
|
|
1224
1231
|
answer(colors(A, B, C)) :- coloring(A, B, C).
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
```sh
|
|
1225
1235
|
eyeprolog --goal 'answer(X)' program.pl
|
|
1226
1236
|
```
|
|
1227
1237
|
|
|
@@ -1531,7 +1541,7 @@ A maintainable theory separates:
|
|
|
1531
1541
|
- source facts: measurements, records, and asserted relationships;
|
|
1532
1542
|
- helpers: normalization, classifications, and reachability;
|
|
1533
1543
|
- decisions: `status/2`, `action/2`, `risk/2`, and `reason/2`;
|
|
1534
|
-
- integrity
|
|
1544
|
+
- integrity relations: predicates that return diagnostic invalid-state witnesses;
|
|
1535
1545
|
- outputs: focused host-supplied goals.
|
|
1536
1546
|
|
|
1537
1547
|
<figure>
|
|
@@ -1589,6 +1599,62 @@ A boundary should make four decisions visible:
|
|
|
1589
1599
|
- which predicates the imported clauses may define; and
|
|
1590
1600
|
- which resource limits apply to the resulting query.
|
|
1591
1601
|
|
|
1602
|
+
### A boundary in four steps
|
|
1603
|
+
|
|
1604
|
+
Suppose a host receives one JSON temperature record. The host, not the logic
|
|
1605
|
+
program, owns the JSON syntax and the decision to trust that record. A narrow
|
|
1606
|
+
adapter can validate the record, map its values into a deliberately small
|
|
1607
|
+
Prolog vocabulary, construct the theory, and ask one bounded question:
|
|
1608
|
+
|
|
1609
|
+
```js
|
|
1610
|
+
import { run } from 'eyeprolog';
|
|
1611
|
+
|
|
1612
|
+
const inputText = '{"sensor":"sensor_1","celsius":91}';
|
|
1613
|
+
const allowedSensors = new Set(['sensor_1', 'sensor_2']);
|
|
1614
|
+
|
|
1615
|
+
function reasoningSource(record) {
|
|
1616
|
+
if (!record || typeof record !== 'object') throw new TypeError('record');
|
|
1617
|
+
if (!allowedSensors.has(record.sensor)) throw new TypeError('sensor');
|
|
1618
|
+
if (!Number.isFinite(record.celsius)) throw new TypeError('celsius');
|
|
1619
|
+
if (record.celsius < -100 || record.celsius > 200) {
|
|
1620
|
+
throw new RangeError('celsius');
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
return `
|
|
1624
|
+
reading(${record.sensor}, ${record.celsius}).
|
|
1625
|
+
thermal_alert(Sensor) :-
|
|
1626
|
+
reading(Sensor, Celsius),
|
|
1627
|
+
(Celsius >= 80).
|
|
1628
|
+
`;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
const record = JSON.parse(inputText);
|
|
1632
|
+
const result = run(reasoningSource(record), {
|
|
1633
|
+
goal: `thermal_alert(${record.sensor})`,
|
|
1634
|
+
proof: true,
|
|
1635
|
+
maxDepth: 10_000,
|
|
1636
|
+
solutionLimit: 10
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
console.log(result.stdout);
|
|
1640
|
+
```
|
|
1641
|
+
|
|
1642
|
+
The allow-list makes interpolation safe here: the external sensor identifier
|
|
1643
|
+
can become only one of two known Prolog atoms, and the temperature must be a
|
|
1644
|
+
finite number in an accepted range. General text must be encoded with a
|
|
1645
|
+
well-tested term constructor or serializer rather than inserted into source.
|
|
1646
|
+
The generated program defines only `reading/2` and the fixed domain rule; the
|
|
1647
|
+
host supplies the goal and ceilings explicitly.
|
|
1648
|
+
|
|
1649
|
+
This small example exposes four different claims:
|
|
1650
|
+
|
|
1651
|
+
| Stage | Claim and owner |
|
|
1652
|
+
| --- | --- |
|
|
1653
|
+
| Parse | the bytes are valid JSON — host parser |
|
|
1654
|
+
| Validate | the record has an accepted sensor and temperature — adapter |
|
|
1655
|
+
| Convert | the accepted values denote these exact Prolog terms — adapter |
|
|
1656
|
+
| Derive | the supplied reading satisfies `thermal_alert/1` — EyeProlog proof |
|
|
1657
|
+
|
|
1592
1658
|
The proof procedure can explain how supplied clauses support an answer. It
|
|
1593
1659
|
cannot prove that a file, database, sensor, or remote service was trustworthy.
|
|
1594
1660
|
That responsibility stays with the host application.
|
|
@@ -1602,12 +1668,11 @@ resource limit that prevents an untrusted input from consuming unbounded work.
|
|
|
1602
1668
|
The JavaScript API exposes a convenience runner and lower-level types:
|
|
1603
1669
|
|
|
1604
1670
|
```js
|
|
1605
|
-
import { run, Program, Solver } from 'eyeprolog';
|
|
1671
|
+
import { run, Program, Solver, parseGoalText } from 'eyeprolog';
|
|
1606
1672
|
|
|
1607
1673
|
const result = run(`
|
|
1608
|
-
eyeprolog --goal 'answer(X)' program.pl
|
|
1609
1674
|
answer(ok) :- ok = ok.
|
|
1610
|
-
|
|
1675
|
+
`, { goal: 'answer(X)' });
|
|
1611
1676
|
console.log(result.stdout);
|
|
1612
1677
|
console.log(result.stats);
|
|
1613
1678
|
```
|
|
@@ -1627,7 +1692,6 @@ For applications that inspect or prepare a theory before running it, use
|
|
|
1627
1692
|
|
|
1628
1693
|
```js
|
|
1629
1694
|
const source = `
|
|
1630
|
-
eyeprolog --goal 'path(a, X)' program.pl
|
|
1631
1695
|
edge(a, b).
|
|
1632
1696
|
edge(b, c).
|
|
1633
1697
|
path(X, Y) :- edge(X, Y).
|
|
@@ -1635,9 +1699,10 @@ path(X, Z) :- edge(X, Y), path(Y, Z).
|
|
|
1635
1699
|
`;
|
|
1636
1700
|
|
|
1637
1701
|
const program = Program.parse(source, { analyzeNegation: true });
|
|
1702
|
+
const goal = parseGoalText('path(a, X)');
|
|
1638
1703
|
const path = program.findGroup('path', 2);
|
|
1639
1704
|
|
|
1640
|
-
console.log(
|
|
1705
|
+
console.log(goal);
|
|
1641
1706
|
console.log(program.stratifiedNegation);
|
|
1642
1707
|
console.log(path?.recursive, path?.tabled, path?.tableInputPositions);
|
|
1643
1708
|
|
|
@@ -1700,9 +1765,8 @@ registry.add(
|
|
|
1700
1765
|
);
|
|
1701
1766
|
|
|
1702
1767
|
const result = run(`
|
|
1703
|
-
eyeprolog --goal 'answer(X)' program.pl
|
|
1704
1768
|
answer(X) :- host_status(service, X).
|
|
1705
|
-
`, { registry });
|
|
1769
|
+
`, { registry, goal: 'answer(X)' });
|
|
1706
1770
|
```
|
|
1707
1771
|
|
|
1708
1772
|
Only mark a built-in deterministic when it can produce at most one environment
|
|
@@ -2088,8 +2152,8 @@ constructs `s(s(s(...)))` without bound.
|
|
|
2088
2152
|
|
|
2089
2153
|
### Negation and aggregation require bounded subsearch
|
|
2090
2154
|
|
|
2091
|
-
`\+ Goal
|
|
2092
|
-
|
|
2155
|
+
`\+ Goal` and aggregates ask the engine to settle a nested search. Their
|
|
2156
|
+
meaning is usable only when that search can finish. Before
|
|
2093
2157
|
writing:
|
|
2094
2158
|
|
|
2095
2159
|
```eyeprolog
|
|
@@ -2282,7 +2346,9 @@ parent(clara, diego).
|
|
|
2282
2346
|
|
|
2283
2347
|
ancestor(X, Y) :- parent(X, Y).
|
|
2284
2348
|
ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z).
|
|
2349
|
+
```
|
|
2285
2350
|
|
|
2351
|
+
```sh
|
|
2286
2352
|
eyeprolog --goal 'ancestor(ada, Who)' program.pl
|
|
2287
2353
|
```
|
|
2288
2354
|
|
|
@@ -2488,7 +2554,9 @@ verb([helps | Rest], Rest).
|
|
|
2488
2554
|
verb([observes | Rest], Rest).
|
|
2489
2555
|
|
|
2490
2556
|
complete_sentence(Words) :- sentence(Words, []).
|
|
2557
|
+
```
|
|
2491
2558
|
|
|
2559
|
+
```sh
|
|
2492
2560
|
eyeprolog --goal 'complete_sentence([the, robot, helps, a, scientist])' program.pl
|
|
2493
2561
|
```
|
|
2494
2562
|
|
|
@@ -2521,7 +2589,7 @@ evaluate(multiply(Left, Right), Value) :-
|
|
|
2521
2589
|
(Value is L * R).
|
|
2522
2590
|
```
|
|
2523
2591
|
|
|
2524
|
-
```
|
|
2592
|
+
```sh
|
|
2525
2593
|
eyeprolog --goal 'evaluate(
|
|
2526
2594
|
add(number(2), multiply(number(3), number(4))),
|
|
2527
2595
|
Value
|
|
@@ -2777,7 +2845,9 @@ assignment(Worker, Task) :-
|
|
|
2777
2845
|
worker(Worker),
|
|
2778
2846
|
task(Task),
|
|
2779
2847
|
qualified(Worker, Task).
|
|
2848
|
+
```
|
|
2780
2849
|
|
|
2850
|
+
```sh
|
|
2781
2851
|
eyeprolog --goal 'assignment(Worker, Task)' program.pl
|
|
2782
2852
|
```
|
|
2783
2853
|
|
|
@@ -2960,7 +3030,9 @@ permit(Person, Zone) :-
|
|
|
2960
3030
|
|
|
2961
3031
|
reason(Person, Zone, badge_and_training_verified) :-
|
|
2962
3032
|
permit(Person, Zone).
|
|
3033
|
+
```
|
|
2963
3034
|
|
|
3035
|
+
```sh
|
|
2964
3036
|
eyeprolog --goal 'permit(Person, Zone)' program.pl
|
|
2965
3037
|
eyeprolog --goal 'reason(Person, Zone, Reason)' program.pl
|
|
2966
3038
|
```
|
|
@@ -3097,9 +3169,9 @@ inherits the twentieth century's harder questions. What counts as a formal
|
|
|
3097
3169
|
proof? What is an effective procedure? Which truths follow from a finite set
|
|
3098
3170
|
of axioms? Which questions cannot be decided by any uniform mechanical method?
|
|
3099
3171
|
|
|
3100
|
-
EyeProlog
|
|
3101
|
-
for all mathematics, a computer algebra system, or an interactive
|
|
3102
|
-
prover. Its definite clauses cover only a disciplined fragment of logic.
|
|
3172
|
+
EyeProlog inherits a small, practical fragment of that tradition. It is not a
|
|
3173
|
+
foundation for all mathematics, a computer algebra system, or an interactive
|
|
3174
|
+
theorem prover. Its definite clauses cover only a disciplined fragment of logic.
|
|
3103
3175
|
Precisely because the fragment is small, however, one can see the ancient
|
|
3104
3176
|
mathematical acts inside the running machine:
|
|
3105
3177
|
|
|
@@ -3196,7 +3268,9 @@ triple(A, B, C) :-
|
|
|
3196
3268
|
(BB is B * B),
|
|
3197
3269
|
(Sum is AA + BB),
|
|
3198
3270
|
(Sum is C * C).
|
|
3271
|
+
```
|
|
3199
3272
|
|
|
3273
|
+
```sh
|
|
3200
3274
|
eyeprolog --goal 'triple(A, B, C)' program.pl
|
|
3201
3275
|
```
|
|
3202
3276
|
|
|
@@ -3503,7 +3577,9 @@ integer_rectangle(Area, W, H) :-
|
|
|
3503
3577
|
between(1, Area, W),
|
|
3504
3578
|
between(W, Area, H),
|
|
3505
3579
|
(Area is W * H).
|
|
3580
|
+
```
|
|
3506
3581
|
|
|
3582
|
+
```sh
|
|
3507
3583
|
eyeprolog --goal 'integer_rectangle(24, W, H)' program.pl
|
|
3508
3584
|
```
|
|
3509
3585
|
|
|
@@ -3534,9 +3610,10 @@ preserves_combine(X, Y) :-
|
|
|
3534
3610
|
(IXY = CombinedImages).
|
|
3535
3611
|
```
|
|
3536
3612
|
|
|
3537
|
-
Over a finite carrier,
|
|
3538
|
-
|
|
3539
|
-
|
|
3613
|
+
Over a finite carrier, define a relation for a violating pair and use ISO
|
|
3614
|
+
`\+/1` to ask whether that counterexample relation has any answer. Over an
|
|
3615
|
+
infinite carrier, finite testing is evidence, not proof. The algebraic law must
|
|
3616
|
+
instead follow from definitions or a stronger proof system.
|
|
3540
3617
|
|
|
3541
3618
|
The examples `d3-group.pl`, `matrix-noncommutativity.pl`,
|
|
3542
3619
|
`group-inverse-uniqueness.pl`, and
|
|
@@ -3609,7 +3686,9 @@ counterexample_to_odd_square(N) :-
|
|
|
3609
3686
|
(Square is N * N),
|
|
3610
3687
|
(Remainder is Square mod 2),
|
|
3611
3688
|
(Remainder \= 1).
|
|
3689
|
+
```
|
|
3612
3690
|
|
|
3691
|
+
```sh
|
|
3613
3692
|
eyeprolog --goal 'counterexample_to_odd_square(N)' program.pl
|
|
3614
3693
|
```
|
|
3615
3694
|
|
|
@@ -3974,7 +4053,9 @@ edge(b, c).
|
|
|
3974
4053
|
|
|
3975
4054
|
path(X, Y) :- edge(X, Y).
|
|
3976
4055
|
path(X, Z) :- edge(X, Y), path(Y, Z).
|
|
4056
|
+
```
|
|
3977
4057
|
|
|
4058
|
+
```sh
|
|
3978
4059
|
eyeprolog --goal 'path(a, b)' program.pl
|
|
3979
4060
|
eyeprolog --goal 'path(a, c)' program.pl
|
|
3980
4061
|
```
|
|
@@ -3987,7 +4068,9 @@ unexpected_path :-
|
|
|
3987
4068
|
|
|
3988
4069
|
expected_absence :-
|
|
3989
4070
|
\+ unexpected_path.
|
|
4071
|
+
```
|
|
3990
4072
|
|
|
4073
|
+
```sh
|
|
3991
4074
|
eyeprolog --goal 'expected_absence' program.pl
|
|
3992
4075
|
```
|
|
3993
4076
|
|
|
@@ -4003,7 +4086,7 @@ golden answer file is an executable specification of the expected answer set.
|
|
|
4003
4086
|
|
|
4004
4087
|
Suppose `append/3` is intended both to concatenate and to split:
|
|
4005
4088
|
|
|
4006
|
-
```
|
|
4089
|
+
```sh
|
|
4007
4090
|
eyeprolog --goal 'append([a, b], [c], Whole)' program.pl
|
|
4008
4091
|
eyeprolog --goal 'append(Prefix, Suffix, [a, b])' program.pl
|
|
4009
4092
|
```
|
|
@@ -4042,7 +4125,9 @@ bounded_double_law :-
|
|
|
4042
4125
|
bounded_double_counterexample :-
|
|
4043
4126
|
between(-100, 100, N),
|
|
4044
4127
|
\+ double_is_even(N).
|
|
4128
|
+
```
|
|
4045
4129
|
|
|
4130
|
+
```sh
|
|
4046
4131
|
eyeprolog --goal 'bounded_double_law' program.pl
|
|
4047
4132
|
```
|
|
4048
4133
|
|
|
@@ -4157,7 +4242,7 @@ Use four views in a fixed order:
|
|
|
4157
4242
|
Do not begin with an open query that prints hundreds of answers. Name one
|
|
4158
4243
|
conclusion that is missing or surprising:
|
|
4159
4244
|
|
|
4160
|
-
```
|
|
4245
|
+
```sh
|
|
4161
4246
|
eyeprolog --goal 'eligible(alex)' program.pl
|
|
4162
4247
|
```
|
|
4163
4248
|
|
|
@@ -4252,7 +4337,9 @@ candidate_debug(Person, Age) :-
|
|
|
4252
4337
|
adult_debug(Person, Age) :-
|
|
4253
4338
|
candidate_debug(Person, Age),
|
|
4254
4339
|
(Age >= 18).
|
|
4340
|
+
```
|
|
4255
4341
|
|
|
4342
|
+
```sh
|
|
4256
4343
|
eyeprolog --goal 'candidate_debug(Person, Age)' program.pl
|
|
4257
4344
|
eyeprolog --goal 'adult_debug(Person, Age)' program.pl
|
|
4258
4345
|
```
|
|
@@ -4279,7 +4366,9 @@ optimized_square(N, S) :-
|
|
|
4279
4366
|
disagreement(N, S) :-
|
|
4280
4367
|
reference_square(N, S),
|
|
4281
4368
|
\+ optimized_square(N, S).
|
|
4369
|
+
```
|
|
4282
4370
|
|
|
4371
|
+
```sh
|
|
4283
4372
|
eyeprolog --goal 'disagreement(N, S)' program.pl
|
|
4284
4373
|
```
|
|
4285
4374
|
|
|
@@ -5048,7 +5137,7 @@ Supported output syntax is designed to be readable as Prolog input accepted by E
|
|
|
5048
5137
|
#### Automatic hybrid reasoning
|
|
5049
5138
|
|
|
5050
5139
|
The program loader detects predicate-dependency cycles, including dependencies
|
|
5051
|
-
inside conjunction, `\+/1`, `once/1`,
|
|
5140
|
+
inside conjunction, `\+/1`, `once/1`, and aggregate goals.
|
|
5052
5141
|
Positive recursive components—including directly queried recursive
|
|
5053
5142
|
relations—are tabled to an answer fixed point before answers are replayed.
|
|
5054
5143
|
Components with a negative dependency retain guarded ordinary resolution,
|
|
@@ -5451,7 +5540,12 @@ JavaScript uses the same registry by default:
|
|
|
5451
5540
|
```js
|
|
5452
5541
|
import { run } from 'eyeprolog';
|
|
5453
5542
|
|
|
5454
|
-
const
|
|
5543
|
+
const source = `
|
|
5544
|
+
answer(Whole) :- append([red, green], [blue], Whole).
|
|
5545
|
+
`;
|
|
5546
|
+
|
|
5547
|
+
const result = run(source, { goal: 'answer(X)' });
|
|
5548
|
+
console.log(result.stdout);
|
|
5455
5549
|
```
|
|
5456
5550
|
|
|
5457
5551
|
The mode notation below is descriptive:
|
|
@@ -5480,6 +5574,9 @@ answer(square, S) :- (S is 12 * 12).
|
|
|
5480
5574
|
answer(day_count, N) :- between(3, 5, N).
|
|
5481
5575
|
answer(age, D) :- difference('2026-07-28', '2020-05-20', D).
|
|
5482
5576
|
answer(random_pair, [A,B]) :- random(42, A, S), random(S, B, _).
|
|
5577
|
+
```
|
|
5578
|
+
|
|
5579
|
+
```sh
|
|
5483
5580
|
eyeprolog --goal 'answer(Kind, Value)' program.pl
|
|
5484
5581
|
```
|
|
5485
5582
|
|
|
@@ -5530,7 +5627,9 @@ answer(split, pair(Prefix, Suffix)) :-
|
|
|
5530
5627
|
|
|
5531
5628
|
answer(second, Item) :-
|
|
5532
5629
|
nth0(1, [a, b, c], Item).
|
|
5630
|
+
```
|
|
5533
5631
|
|
|
5632
|
+
```sh
|
|
5534
5633
|
eyeprolog --goal 'answer(Kind, Value)' program.pl
|
|
5535
5634
|
```
|
|
5536
5635
|
|
|
@@ -5572,7 +5671,9 @@ answer(captures, Context) :-
|
|
|
5572
5671
|
matches('Ada Lovelace',
|
|
5573
5672
|
'^(?<first>[A-Za-z]+) (?<last>[A-Za-z]+)$',
|
|
5574
5673
|
Context).
|
|
5674
|
+
```
|
|
5575
5675
|
|
|
5676
|
+
```sh
|
|
5576
5677
|
eyeprolog --goal 'answer(Kind, Value)' program.pl
|
|
5577
5678
|
```
|
|
5578
5679
|
|
|
@@ -5608,7 +5709,9 @@ answer(best(Name), Cost) :-
|
|
|
5608
5709
|
aggregate_min(CandidateCost, CandidateName,
|
|
5609
5710
|
cost(CandidateName, CandidateCost),
|
|
5610
5711
|
Cost, Name).
|
|
5712
|
+
```
|
|
5611
5713
|
|
|
5714
|
+
```sh
|
|
5612
5715
|
eyeprolog --goal 'answer(Kind, Value)' program.pl
|
|
5613
5716
|
```
|
|
5614
5717
|
|
|
@@ -5633,7 +5736,9 @@ context_parts(Context, Name, Args) :-
|
|
|
5633
5736
|
answer(field(Name, Args)) :-
|
|
5634
5737
|
message(event_17, Context),
|
|
5635
5738
|
context_parts(Context, Name, Args).
|
|
5739
|
+
```
|
|
5636
5740
|
|
|
5741
|
+
```sh
|
|
5637
5742
|
eyeprolog --goal 'answer(X)' program.pl
|
|
5638
5743
|
```
|
|
5639
5744
|
|
|
@@ -6230,8 +6335,8 @@ sentence, mode, finite domain, answer, proof, and revision.
|
|
|
6230
6335
|
This book is the single reference for the EyeProlog implementation. Chapters 38–40
|
|
6231
6336
|
describe its supported ISO Prolog syntax, directives, execution model,
|
|
6232
6337
|
built-in predicates, and command-line interface. The earlier chapters explain the reasoner, automatic tabling,
|
|
6233
|
-
proof terms, warnings, answer formatting, embedding, and
|
|
6234
|
-
|
|
6338
|
+
proof terms, warnings, answer formatting, embedding, and explicit host data
|
|
6339
|
+
boundaries.
|
|
6235
6340
|
|
|
6236
6341
|
The executable corpus under `test/conformance/` tests the JavaScript
|
|
6237
6342
|
implementation. Positive programs and exact output cover arithmetic, text relations,
|
|
@@ -6247,7 +6352,8 @@ The complete suite must pass before release. The file-based conformance corpus
|
|
|
6247
6352
|
contains 710 cases, including 304 focused ISO
|
|
6248
6353
|
cases derived from the success, failure, mode, and error behavior in
|
|
6249
6354
|
ISO/IEC 13211-1 clauses 7 and 8. Separate exact-output suites check 188 normal
|
|
6250
|
-
examples
|
|
6355
|
+
examples and 60 proof examples; all extracted book programs are parsed and
|
|
6356
|
+
their declared goals are executed. The seven-case
|
|
6251
6357
|
playground contract suite imports the production worker, sends real reasoning
|
|
6252
6358
|
requests through its message protocol, and crawls the served module graph for
|
|
6253
6359
|
missing assets, bad MIME types, and static Node-only imports. The generated
|
|
@@ -6696,7 +6802,7 @@ deadlines.
|
|
|
6696
6802
|
| Laboratories 3–4 | Chapters 6–10 and 13 | 4–8 hours each |
|
|
6697
6803
|
| Laboratories 5–7 | Chapters 19 and 26–29 | 4–8 hours each |
|
|
6698
6804
|
| Laboratories 8–10 | Chapters 14, 25, and 31–33 | 6–12 hours each |
|
|
6699
|
-
| Laboratory 11 |
|
|
6805
|
+
| Laboratory 11 | Chapters 15–16 | 4–8 hours |
|
|
6700
6806
|
| Laboratory 12 | Chapters 16, 25, and 31–33 | multi-session capstone |
|
|
6701
6807
|
|
|
6702
6808
|
### Laboratory 1. A family theory
|
|
@@ -6990,7 +7096,7 @@ list bound, the prefix/suffix splits are:
|
|
|
6990
7096
|
`[a | Tail]` is not yet known to be proper because `Tail` might never resolve
|
|
6991
7097
|
to a finite chain ending in `[]`.
|
|
6992
7098
|
|
|
6993
|
-
**Chapter 6.** `is/2`,
|
|
7099
|
+
**Chapter 6.** `is/2`, numeric comparisons, and the recursive
|
|
6994
7100
|
arithmetic steps require their documented numeric inputs. In
|
|
6995
7101
|
`between(1, 10, N)`, an unbound `N` is generated from a finite interval; a
|
|
6996
7102
|
bound `N` is checked for membership in that interval.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|