eyelang 1.7.9 → 1.7.11
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/docs/guide.md +11 -3
- package/docs/language-reference.md +4 -4
- package/examples/animal.eye +1 -1
- package/examples/dairy-energy-balance.eye +3 -3
- package/examples/dijkstra-risk-path.eye +1 -1
- package/examples/ev-range-worlds.eye +10 -10
- package/examples/fft8-numeric.eye +1 -1
- package/examples/field-nitrogen-balance.eye +7 -7
- package/examples/fundamental-theorem-arithmetic.eye +2 -2
- package/examples/gps.eye +8 -8
- package/examples/illegitimate-reasoning.eye +7 -7
- package/examples/map-four-color-search.eye +65 -0
- package/examples/matrix-noncommutativity.eye +43 -0
- package/examples/monkey-bananas.eye +4 -4
- package/examples/output/map-four-color-search.eye +1 -0
- package/examples/output/matrix-noncommutativity.eye +3 -0
- package/examples/output/peano-calculus.eye +3 -0
- package/examples/output/prime-range.eye +3 -0
- package/examples/output/route-planning.eye +4 -0
- package/examples/output/shoelace-polygon-area.eye +1 -0
- package/examples/output/symbolic-derivative.eye +4 -0
- package/examples/output/workplace-compliance.eye +4 -0
- package/examples/peano-calculus.eye +40 -0
- package/examples/prime-range.eye +45 -0
- package/examples/route-planning.eye +33 -0
- package/examples/shoelace-polygon-area.eye +22 -0
- package/examples/symbolic-derivative.eye +39 -0
- package/examples/wolf-goat-cabbage.eye +2 -2
- package/examples/workplace-compliance.eye +41 -0
- package/examples/zebra.eye +21 -21
- package/package.json +1 -1
- package/playground.html +15 -4
- package/src/parser.js +8 -8
- package/src/term.js +1 -1
- package/test/conformance/cases/arithmetic/extra_division_by_zero_fails.eye +1 -1
- package/test/conformance/cases/atoms/103_angle_iri_atoms.eye +2 -2
- package/test/conformance/cases/builtins/extra_difference_end_before_start_fails.eye +1 -1
- package/test/conformance/cases/builtins/extra_difference_invalid_date_fails.eye +1 -1
- package/test/conformance/cases/context/extra_holds_ignores_string_parts.eye +1 -1
- package/test/conformance/cases/lists/020_nested_list_terms.eye +1 -1
- package/test/conformance/cases/lists/extra_length_improper_fails.eye +1 -1
- package/test/conformance/cases/rules/022_rule_head_structure.eye +2 -2
- package/test/conformance/cases/terms/extra_arg_atom_fails.eye +1 -1
- package/test/conformance/cases/terms/extra_arg_zero_fails.eye +1 -1
- package/test/conformance/cases/terms/extra_compound_name_arguments_bad_args_fails.eye +1 -1
- package/test/conformance/cases/variables/007_anonymous_variables.eye +1 -1
- package/test/conformance/cases/variables/026_question_underscore_named_variable_reuse.eye +1 -1
- package/test/conformance/cases/variables/anonymous_in_two_goals.eye +2 -2
- package/test/conformance/cases/variables/extra_anonymous_not_reused.eye +1 -1
- package/test/conformance/cases/variables/question_anonymous_not_reused.eye +3 -3
- package/test/conformance/expected-errors/syntax/bad_question_digit_variable.txt +1 -1
- package/test/conformance/expected-errors/variables/question_digit_rejected.txt +1 -1
- package/test/run-regression.mjs +2 -2
package/docs/guide.md
CHANGED
|
@@ -360,9 +360,9 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
360
360
|
| [`derived-backward-rule.eye`](../examples/derived-backward-rule.eye) | Derives an inverse-property backward rule from rule data. | [`output/derived-backward-rule.eye`](../examples/output/derived-backward-rule.eye) |
|
|
361
361
|
| [`derived-rule.eye`](../examples/derived-rule.eye) | Derives conclusions from rule data. | [`output/derived-rule.eye`](../examples/output/derived-rule.eye) |
|
|
362
362
|
| [`diamond-property.eye`](../examples/diamond-property.eye) | Checks the diamond property of a relation. | [`output/diamond-property.eye`](../examples/output/diamond-property.eye) |
|
|
363
|
-
| [`dijkstra.eye`](../examples/dijkstra.eye) | Enumerates weighted simple paths. | [`output/dijkstra.eye`](../examples/output/dijkstra.eye) |
|
|
364
363
|
| [`dijkstra-findall-sort.eye`](../examples/dijkstra-findall-sort.eye) | Finds shortest paths using collected candidates. | [`output/dijkstra-findall-sort.eye`](../examples/output/dijkstra-findall-sort.eye) |
|
|
365
364
|
| [`dijkstra-risk-path.eye`](../examples/dijkstra-risk-path.eye) | Ranks routes by cost and trust. | [`output/dijkstra-risk-path.eye`](../examples/output/dijkstra-risk-path.eye) |
|
|
365
|
+
| [`dijkstra.eye`](../examples/dijkstra.eye) | Enumerates weighted simple paths. | [`output/dijkstra.eye`](../examples/output/dijkstra.eye) |
|
|
366
366
|
| [`dining-philosophers.eye`](../examples/dining-philosophers.eye) | Simulates Chandy-Misra fork exchanges. | [`output/dining-philosophers.eye`](../examples/output/dining-philosophers.eye) |
|
|
367
367
|
| [`dog.eye`](../examples/dog.eye) | Counts dogs and derives when a license is required. | [`output/dog.eye`](../examples/output/dog.eye) |
|
|
368
368
|
| [`dpv-odrl-purpose-mapping.eye`](../examples/dpv-odrl-purpose-mapping.eye) | Maps a DPV process into an ODRL permission view. | [`output/dpv-odrl-purpose-mapping.eye`](../examples/output/dpv-odrl-purpose-mapping.eye) |
|
|
@@ -389,8 +389,8 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
389
389
|
| [`gdpr-compliance.eye`](../examples/gdpr-compliance.eye) | Checks GDPR-style processing compliance. | [`output/gdpr-compliance.eye`](../examples/output/gdpr-compliance.eye) |
|
|
390
390
|
| [`good-cobbler.eye`](../examples/good-cobbler.eye) | Demonstrates term-level structure with a good-cobbler statement. | [`output/good-cobbler.eye`](../examples/output/good-cobbler.eye) |
|
|
391
391
|
| [`gps.eye`](../examples/gps.eye) | Finds and verifies route paths. | [`output/gps.eye`](../examples/output/gps.eye) |
|
|
392
|
-
| [`graph.eye`](../examples/graph.eye) | Derives transitive paths over French-city road links while showing the productive recursive rule order. | [`output/graph.eye`](../examples/output/graph.eye) |
|
|
393
392
|
| [`graph-reachability.eye`](../examples/graph-reachability.eye) | Derives reachable nodes in a graph. | [`output/graph-reachability.eye`](../examples/output/graph-reachability.eye) |
|
|
393
|
+
| [`graph.eye`](../examples/graph.eye) | Derives transitive paths over French-city road links while showing the productive recursive rule order. | [`output/graph.eye`](../examples/output/graph.eye) |
|
|
394
394
|
| [`gray-code-counter.eye`](../examples/gray-code-counter.eye) | Generates Gray-code counter states. | [`output/gray-code-counter.eye`](../examples/output/gray-code-counter.eye) |
|
|
395
395
|
| [`greatest-lower-bound-uniqueness.eye`](../examples/greatest-lower-bound-uniqueness.eye) | Shows uniqueness of greatest lower bounds in a finite order instance. | [`output/greatest-lower-bound-uniqueness.eye`](../examples/output/greatest-lower-bound-uniqueness.eye) |
|
|
396
396
|
| [`group-inverse-uniqueness.eye`](../examples/group-inverse-uniqueness.eye) | Shows uniqueness of inverses in a finite group instance. | [`output/group-inverse-uniqueness.eye`](../examples/output/group-inverse-uniqueness.eye) |
|
|
@@ -398,6 +398,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
398
398
|
| [`hamming-code.eye`](../examples/hamming-code.eye) | Corrects a single-bit Hamming word. | [`output/hamming-code.eye`](../examples/output/hamming-code.eye) |
|
|
399
399
|
| [`hanoi.eye`](../examples/hanoi.eye) | Derives the Towers of Hanoi moves. | [`output/hanoi.eye`](../examples/output/hanoi.eye) |
|
|
400
400
|
| [`heat-loss.eye`](../examples/heat-loss.eye) | Computes conductive heat loss. | [`output/heat-loss.eye`](../examples/output/heat-loss.eye) |
|
|
401
|
+
| [`herbrand-witnesses.eye`](../examples/herbrand-witnesses.eye) | Represents existential-style consequences as stable Herbrand witness terms. | [`output/herbrand-witnesses.eye`](../examples/output/herbrand-witnesses.eye) |
|
|
401
402
|
| [`heron-theorem.eye`](../examples/heron-theorem.eye) | Computes triangle area by Heron's theorem. | [`output/heron-theorem.eye`](../examples/output/heron-theorem.eye) |
|
|
402
403
|
| [`ideal-gas-law.eye`](../examples/ideal-gas-law.eye) | Applies the ideal gas law. | [`output/ideal-gas-law.eye`](../examples/output/ideal-gas-law.eye) |
|
|
403
404
|
| [`illegitimate-reasoning.eye`](../examples/illegitimate-reasoning.eye) | Detects suspect reasoning patterns. | [`output/illegitimate-reasoning.eye`](../examples/output/illegitimate-reasoning.eye) |
|
|
@@ -413,7 +414,9 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
413
414
|
| [`list-collection.eye`](../examples/list-collection.eye) | Demonstrates list and collection built-ins. | [`output/list-collection.eye`](../examples/output/list-collection.eye) |
|
|
414
415
|
| [`lldm.eye`](../examples/lldm.eye) | Calculates leg-length discrepancy measurements. | [`output/lldm.eye`](../examples/output/lldm.eye) |
|
|
415
416
|
| [`manufacturing-quality-control.eye`](../examples/manufacturing-quality-control.eye) | Evaluates process capability and quality. | [`output/manufacturing-quality-control.eye`](../examples/output/manufacturing-quality-control.eye) |
|
|
417
|
+
| [`map-four-color-search.eye`](../examples/map-four-color-search.eye) | Searches for a valid four-colouring of the EU neighbour graph. | [`output/map-four-color-search.eye`](../examples/output/map-four-color-search.eye) |
|
|
416
418
|
| [`matrix-chain-order.eye`](../examples/matrix-chain-order.eye) | Finds an optimal matrix-chain multiplication order. | [`output/matrix-chain-order.eye`](../examples/output/matrix-chain-order.eye) |
|
|
419
|
+
| [`matrix-noncommutativity.eye`](../examples/matrix-noncommutativity.eye) | Multiplies 2x2 matrices and shows non-commutativity. | [`output/matrix-noncommutativity.eye`](../examples/output/matrix-noncommutativity.eye) |
|
|
417
420
|
| [`microgrid-dispatch.eye`](../examples/microgrid-dispatch.eye) | Plans microgrid dispatch and reserve. | [`output/microgrid-dispatch.eye`](../examples/output/microgrid-dispatch.eye) |
|
|
418
421
|
| [`missionaries-cannibals.eye`](../examples/missionaries-cannibals.eye) | Solves the missionaries-and-cannibals river crossing puzzle. | [`output/missionaries-cannibals.eye`](../examples/output/missionaries-cannibals.eye) |
|
|
419
422
|
| [`modal-logic-kripke.eye`](../examples/modal-logic-kripke.eye) | Emulates modal box and diamond operators over a finite Kripke frame. | [`output/modal-logic-kripke.eye`](../examples/output/modal-logic-kripke.eye) |
|
|
@@ -430,21 +433,24 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
430
433
|
| [`orbital-transfer-design.eye`](../examples/orbital-transfer-design.eye) | Designs a Hohmann orbital transfer. | [`output/orbital-transfer-design.eye`](../examples/output/orbital-transfer-design.eye) |
|
|
431
434
|
| [`path-discovery.eye`](../examples/path-discovery.eye) | Discovers bounded air-route paths. | [`output/path-discovery.eye`](../examples/output/path-discovery.eye) |
|
|
432
435
|
| [`peano-arithmetic.eye`](../examples/peano-arithmetic.eye) | Computes Peano addition, multiplication, and factorial. | [`output/peano-arithmetic.eye`](../examples/output/peano-arithmetic.eye) |
|
|
436
|
+
| [`peano-calculus.eye`](../examples/peano-calculus.eye) | Computes Peano addition, multiplication, and factorial. | [`output/peano-calculus.eye`](../examples/output/peano-calculus.eye) |
|
|
433
437
|
| [`peasant.eye`](../examples/peasant.eye) | Performs peasant multiplication and exponentiation. | [`output/peasant.eye`](../examples/output/peasant.eye) |
|
|
434
438
|
| [`pell-equation.eye`](../examples/pell-equation.eye) | Generates Pell-equation solutions by recurrence. | [`output/pell-equation.eye`](../examples/output/pell-equation.eye) |
|
|
435
439
|
| [`pendulum-period.eye`](../examples/pendulum-period.eye) | Computes simple pendulum periods. | [`output/pendulum-period.eye`](../examples/output/pendulum-period.eye) |
|
|
436
440
|
| [`polynomial.eye`](../examples/polynomial.eye) | Finds complex integer polynomial roots. | [`output/polynomial.eye`](../examples/output/polynomial.eye) |
|
|
441
|
+
| [`prime-range.eye`](../examples/prime-range.eye) | Finds primes in a finite range and computes a totient value. | [`output/prime-range.eye`](../examples/output/prime-range.eye) |
|
|
437
442
|
| [`proof-contrapositive.eye`](../examples/proof-contrapositive.eye) | Models proof by contrapositive. | [`output/proof-contrapositive.eye`](../examples/output/proof-contrapositive.eye) |
|
|
438
443
|
| [`quadratic-formula.eye`](../examples/quadratic-formula.eye) | Solves sample quadratic equations. | [`output/quadratic-formula.eye`](../examples/output/quadratic-formula.eye) |
|
|
439
444
|
| [`radioactive-decay.eye`](../examples/radioactive-decay.eye) | Computes radioactive decay over time. | [`output/radioactive-decay.eye`](../examples/output/radioactive-decay.eye) |
|
|
440
445
|
| [`reusable-builtins.eye`](../examples/reusable-builtins.eye) | Tours reusable numeric, list, and string builtins. | [`output/reusable-builtins.eye`](../examples/output/reusable-builtins.eye) |
|
|
441
446
|
| [`riemann-hypothesis.eye`](../examples/riemann-hypothesis.eye) | Checks a finite catalogue of non-trivial zeta zeros against the Riemann-hypothesis condition. | [`output/riemann-hypothesis.eye`](../examples/output/riemann-hypothesis.eye) |
|
|
447
|
+
| [`route-planning.eye`](../examples/route-planning.eye) | Finds routes and records them as explicit route terms. | [`output/route-planning.eye`](../examples/output/route-planning.eye) |
|
|
442
448
|
| [`security-incident-correlation.eye`](../examples/security-incident-correlation.eye) | Correlates security incidents across signals. | [`output/security-incident-correlation.eye`](../examples/output/security-incident-correlation.eye) |
|
|
443
449
|
| [`send-more-money.eye`](../examples/send-more-money.eye) | Solves the SEND + MORE = MONEY cryptarithm. | [`output/send-more-money.eye`](../examples/output/send-more-money.eye) |
|
|
444
450
|
| [`service-impact.eye`](../examples/service-impact.eye) | Analyzes service impact over cyclic dependencies. | [`output/service-impact.eye`](../examples/output/service-impact.eye) |
|
|
451
|
+
| [`shoelace-polygon-area.eye`](../examples/shoelace-polygon-area.eye) | Computes polygon area with a recursive shoelace calculation. | [`output/shoelace-polygon-area.eye`](../examples/output/shoelace-polygon-area.eye) |
|
|
445
452
|
| [`sieve.eye`](../examples/sieve.eye) | Enumerates primes with a sieve-style program. | [`output/sieve.eye`](../examples/output/sieve.eye) |
|
|
446
453
|
| [`skolem-functions.eye`](../examples/skolem-functions.eye) | Generates deterministic functional terms. | [`output/skolem-functions.eye`](../examples/output/skolem-functions.eye) |
|
|
447
|
-
| [`herbrand-witnesses.eye`](../examples/herbrand-witnesses.eye) | Represents existential-style consequences as stable Herbrand witness terms. | [`output/herbrand-witnesses.eye`](../examples/output/herbrand-witnesses.eye) |
|
|
448
454
|
| [`socket-age.eye`](../examples/socket-age.eye) | Shows socket-declared age reasoning inputs and plugs. | [`output/socket-age.eye`](../examples/output/socket-age.eye) |
|
|
449
455
|
| [`socket-family.eye`](../examples/socket-family.eye) | Shows socket-declared family-source inputs and ancestry rules. | [`output/socket-family.eye`](../examples/output/socket-family.eye) |
|
|
450
456
|
| [`socrates.eye`](../examples/socrates.eye) | Derives that Socrates is mortal. | [`output/socrates.eye`](../examples/output/socrates.eye) |
|
|
@@ -453,6 +459,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
453
459
|
| [`stirling-bell-numbers.eye`](../examples/stirling-bell-numbers.eye) | Computes Stirling numbers and Bell numbers. | [`output/stirling-bell-numbers.eye`](../examples/output/stirling-bell-numbers.eye) |
|
|
454
460
|
| [`sudoku-4x4.eye`](../examples/sudoku-4x4.eye) | Solves a compact 4x4 Sudoku by finite constraint search. | [`output/sudoku-4x4.eye`](../examples/output/sudoku-4x4.eye) |
|
|
455
461
|
| [`superdense-coding.eye`](../examples/superdense-coding.eye) | Models superdense-coding bit transmission. | [`output/superdense-coding.eye`](../examples/output/superdense-coding.eye) |
|
|
462
|
+
| [`symbolic-derivative.eye`](../examples/symbolic-derivative.eye) | Symbolically differentiates explicit expression terms, including products and logs. | [`output/symbolic-derivative.eye`](../examples/output/symbolic-derivative.eye) |
|
|
456
463
|
| [`term-tools.eye`](../examples/term-tools.eye) | Inspects, builds, renders, and validates terms with reusable term/control builtins. | [`output/term-tools.eye`](../examples/output/term-tools.eye) |
|
|
457
464
|
| [`totient-summatory.eye`](../examples/totient-summatory.eye) | Computes Euler totients and their summatory function. | [`output/totient-summatory.eye`](../examples/output/totient-summatory.eye) |
|
|
458
465
|
| [`trust-flow-provenance-threshold.eye`](../examples/trust-flow-provenance-threshold.eye) | Classifies message trust from provenance confidence scores. | [`output/trust-flow-provenance-threshold.eye`](../examples/output/trust-flow-provenance-threshold.eye) |
|
|
@@ -463,6 +470,7 @@ Use `holds/2` when you want to match the member term directly, for example `name
|
|
|
463
470
|
| [`weighted-interval-scheduling.eye`](../examples/weighted-interval-scheduling.eye) | Selects the best non-overlapping weighted intervals with tabled dynamic programming. | [`output/weighted-interval-scheduling.eye`](../examples/output/weighted-interval-scheduling.eye) |
|
|
464
471
|
| [`witch.eye`](../examples/witch.eye) | Derives the classic “burn the witch” rule chain. | [`output/witch.eye`](../examples/output/witch.eye) |
|
|
465
472
|
| [`wolf-goat-cabbage.eye`](../examples/wolf-goat-cabbage.eye) | Solves the wolf-goat-cabbage river crossing. | [`output/wolf-goat-cabbage.eye`](../examples/output/wolf-goat-cabbage.eye) |
|
|
473
|
+
| [`workplace-compliance.eye`](../examples/workplace-compliance.eye) | Classifies workplace compliance from explicit action facts. | [`output/workplace-compliance.eye`](../examples/output/workplace-compliance.eye) |
|
|
466
474
|
| [`zebra.eye`](../examples/zebra.eye) | Solves the zebra logic puzzle. | [`output/zebra.eye`](../examples/output/zebra.eye) |
|
|
467
475
|
|
|
468
476
|
## Golden outputs, tests, and conformance
|
|
@@ -123,7 +123,7 @@ A colon outside `:-` is not part of the language. Namespace-like names SHOULD be
|
|
|
123
123
|
|
|
124
124
|
### 3.4 Variables
|
|
125
125
|
|
|
126
|
-
A variable starts with `?` followed by an ASCII letter or underscore and then zero or more ASCII letters, digits, or underscores. This N3/SPARQL-style spelling is the only source-level variable spelling in eyelang.
|
|
126
|
+
A variable is either the bare anonymous variable `?`, or starts with `?` followed by an ASCII letter or underscore and then zero or more ASCII letters, digits, or underscores. This N3/SPARQL-style spelling is the only source-level variable spelling in eyelang.
|
|
127
127
|
|
|
128
128
|
Examples:
|
|
129
129
|
|
|
@@ -131,10 +131,10 @@ Examples:
|
|
|
131
131
|
?x
|
|
132
132
|
?person
|
|
133
133
|
?_thing
|
|
134
|
-
?
|
|
134
|
+
?
|
|
135
135
|
```
|
|
136
136
|
|
|
137
|
-
Each
|
|
137
|
+
Each bare `?` anonymous variable occurrence is fresh. A bare `_` is not a variable in eyelang source.
|
|
138
138
|
|
|
139
139
|
### 3.5 Atom constants
|
|
140
140
|
|
|
@@ -171,7 +171,7 @@ A quoted atom constant is enclosed in single quotes. A single quote inside a quo
|
|
|
171
171
|
A graphic atom constant is one or more graphic characters from this set:
|
|
172
172
|
|
|
173
173
|
```text
|
|
174
|
-
|
|
174
|
+
#$&*+-/<=>@^~\
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
Angle-bracket IRI syntax is recognized only for absolute IRI-like contents. Graphic atoms such as `<=>`, `<`, and `>=` remain graphic atoms.
|
package/examples/animal.eye
CHANGED
|
@@ -17,15 +17,15 @@ cow(grazing, 540, 18, 5.8, 21).
|
|
|
17
17
|
|
|
18
18
|
% Maintenance scales with body weight; milk requirement scales with daily milk.
|
|
19
19
|
maintenance(?c, ?m) :-
|
|
20
|
-
cow(?c, ?weight,
|
|
20
|
+
cow(?c, ?weight, ?, ?, ?),
|
|
21
21
|
mul(?weight, 0.08, ?m).
|
|
22
22
|
|
|
23
23
|
milk_requirement(?c, ?r) :-
|
|
24
|
-
cow(?c,
|
|
24
|
+
cow(?c, ?, ?milk, ?, ?),
|
|
25
25
|
mul(?milk, 5.0, ?r).
|
|
26
26
|
|
|
27
27
|
ration_supply(?c, ?s) :-
|
|
28
|
-
cow(?c,
|
|
28
|
+
cow(?c, ?, ?, ?density, ?intake),
|
|
29
29
|
mul(?density, ?intake, ?s).
|
|
30
30
|
|
|
31
31
|
total_requirement(?c, ?r) :-
|
|
@@ -41,7 +41,7 @@ candidate(pathRelay, [depotA, relay, labD]).
|
|
|
41
41
|
candidate(pathDirectC, [depotA, labD]).
|
|
42
42
|
candidate(pathViaC, [depotA, depotC, depotB, labD]).
|
|
43
43
|
|
|
44
|
-
route_cost([?
|
|
44
|
+
route_cost([?], 0.0, 0.0, 0).
|
|
45
45
|
route_cost([?from, ?to|?rest], ?raw, ?risk, ?edges) :-
|
|
46
46
|
route_segment(?from, ?to, ?stepraw, ?steprisk),
|
|
47
47
|
route_cost([?to|?rest], ?restraw, ?restrisk, ?restedges),
|
|
@@ -24,18 +24,18 @@ trip_data(cold_commute, 120, 90, -8, 100, 35, 0.19).
|
|
|
24
24
|
|
|
25
25
|
% Each world adds a different combination of speed, temperature, payload, and
|
|
26
26
|
% reserve factors before comparing required energy with usable battery.
|
|
27
|
-
speed_factor(?t, 1.20) :- trip_data(?t,
|
|
28
|
-
speed_factor(?t, 1.00) :- trip_data(?t,
|
|
27
|
+
speed_factor(?t, 1.20) :- trip_data(?t, ?, ?s, ?, ?, ?, ?), gt(?s, 100).
|
|
28
|
+
speed_factor(?t, 1.00) :- trip_data(?t, ?, ?s, ?, ?, ?, ?), le(?s, 100).
|
|
29
29
|
|
|
30
|
-
temperature_factor(?t, 1.15) :- trip_data(?t,
|
|
31
|
-
temperature_factor(?t, 1.00) :- trip_data(?t,
|
|
30
|
+
temperature_factor(?t, 1.15) :- trip_data(?t, ?, ?, ?temp, ?, ?, ?), lt(?temp, 0).
|
|
31
|
+
temperature_factor(?t, 1.00) :- trip_data(?t, ?, ?, ?temp, ?, ?, ?), ge(?temp, 0).
|
|
32
32
|
|
|
33
|
-
payload_factor(?t, 1.15) :- trip_data(?t,
|
|
34
|
-
payload_factor(?t, 1.08) :- trip_data(?t,
|
|
35
|
-
payload_factor(?t, 1.00) :- trip_data(?t,
|
|
33
|
+
payload_factor(?t, 1.15) :- trip_data(?t, ?, ?, ?, ?p, ?, ?), gt(?p, 500).
|
|
34
|
+
payload_factor(?t, 1.08) :- trip_data(?t, ?, ?, ?, ?p, ?, ?), gt(?p, 250), le(?p, 500).
|
|
35
|
+
payload_factor(?t, 1.00) :- trip_data(?t, ?, ?, ?, ?p, ?, ?), le(?p, 250).
|
|
36
36
|
|
|
37
37
|
base_energy(?t, ?e) :-
|
|
38
|
-
trip_data(?t, ?d,
|
|
38
|
+
trip_data(?t, ?d, ?, ?, ?, ?, ?b),
|
|
39
39
|
mul(?d, ?b, ?e).
|
|
40
40
|
|
|
41
41
|
required_energy(?t, w1, ?e) :-
|
|
@@ -61,12 +61,12 @@ required_energy(?t, w3, ?e) :-
|
|
|
61
61
|
|
|
62
62
|
% safe_in_world/2 compares required trip energy with usable battery capacity.
|
|
63
63
|
safe_in_world(?t, ?w) :-
|
|
64
|
-
trip_data(?t,
|
|
64
|
+
trip_data(?t, ?, ?, ?, ?, ?battery, ?),
|
|
65
65
|
required_energy(?t, ?w, ?required),
|
|
66
66
|
le(?required, ?battery).
|
|
67
67
|
|
|
68
68
|
risky_in_world(?t, ?w) :-
|
|
69
|
-
trip_data(?t,
|
|
69
|
+
trip_data(?t, ?, ?, ?, ?, ?battery, ?),
|
|
70
70
|
required_energy(?t, ?w, ?required),
|
|
71
71
|
gt(?required, ?battery).
|
|
72
72
|
|
|
@@ -21,41 +21,41 @@ field(clay_surplus, 70, 90, 0.08, 120).
|
|
|
21
21
|
% total_n/2 and available_n/2 build the nutrient budget; surplus/deficit and
|
|
22
22
|
% leaching rules then explain the resulting field status.
|
|
23
23
|
total_n(?f, ?total) :-
|
|
24
|
-
field(?f, ?soil, ?fert,
|
|
24
|
+
field(?f, ?soil, ?fert, ?, ?),
|
|
25
25
|
add(?soil, ?fert, ?total).
|
|
26
26
|
|
|
27
27
|
available_n(?f, ?avail) :-
|
|
28
28
|
total_n(?f, ?total),
|
|
29
|
-
field(?f,
|
|
29
|
+
field(?f, ?, ?, ?loss, ?),
|
|
30
30
|
sub(1.0, ?loss, ?retained),
|
|
31
31
|
mul(?total, ?retained, ?avail).
|
|
32
32
|
|
|
33
33
|
% surplus_n/2 and deficit_n/2 split the signed balance into reportable quantities.
|
|
34
34
|
surplus_n(?f, ?surplus) :-
|
|
35
35
|
available_n(?f, ?avail),
|
|
36
|
-
field(?f,
|
|
36
|
+
field(?f, ?, ?, ?, ?demand),
|
|
37
37
|
gt(?avail, ?demand),
|
|
38
38
|
sub(?avail, ?demand, ?surplus).
|
|
39
39
|
|
|
40
40
|
surplus_n(?f, 0.0) :-
|
|
41
41
|
available_n(?f, ?avail),
|
|
42
|
-
field(?f,
|
|
42
|
+
field(?f, ?, ?, ?, ?demand),
|
|
43
43
|
le(?avail, ?demand).
|
|
44
44
|
|
|
45
45
|
deficit_n(?f, ?deficit) :-
|
|
46
46
|
available_n(?f, ?avail),
|
|
47
|
-
field(?f,
|
|
47
|
+
field(?f, ?, ?, ?, ?demand),
|
|
48
48
|
lt(?avail, ?demand),
|
|
49
49
|
sub(?demand, ?avail, ?deficit).
|
|
50
50
|
|
|
51
51
|
deficit_n(?f, 0.0) :-
|
|
52
52
|
available_n(?f, ?avail),
|
|
53
|
-
field(?f,
|
|
53
|
+
field(?f, ?, ?, ?, ?demand),
|
|
54
54
|
ge(?avail, ?demand).
|
|
55
55
|
|
|
56
56
|
leaching_index(?f, ?index) :-
|
|
57
57
|
surplus_n(?f, ?surplus),
|
|
58
|
-
field(?f,
|
|
58
|
+
field(?f, ?, ?, ?loss, ?),
|
|
59
59
|
mul(?surplus, ?loss, ?index).
|
|
60
60
|
|
|
61
61
|
status(?f, under_supplied) :- deficit_n(?f, ?d), gt(?d, 10.0).
|
|
@@ -112,8 +112,8 @@ distinctPrimeCount(case, 4) :-
|
|
|
112
112
|
|
|
113
113
|
smallestPrimeFactor(case, 3) :-
|
|
114
114
|
case(fta, ?n),
|
|
115
|
-
factor_smallest(?n, [3|?
|
|
115
|
+
factor_smallest(?n, [3|?]).
|
|
116
116
|
|
|
117
117
|
largestPrimeFactor(case, 3881) :-
|
|
118
118
|
case(fta, ?n),
|
|
119
|
-
factor_largest(?n, [3881|?
|
|
119
|
+
factor_largest(?n, [3881|?]).
|
package/examples/gps.eye
CHANGED
|
@@ -78,24 +78,24 @@ outcome(routeDirect, "Take the direct route via Brugge.").
|
|
|
78
78
|
|
|
79
79
|
% Verification checks, analogous to the false-producing guards in gps.n3.
|
|
80
80
|
check(c1, true) :-
|
|
81
|
-
traveller_path(i1, [drive_gent_brugge, drive_brugge_oostende],
|
|
81
|
+
traveller_path(i1, [drive_gent_brugge, drive_brugge_oostende], ?, ?, ?, ?).
|
|
82
82
|
|
|
83
83
|
check(c2, true) :-
|
|
84
|
-
traveller_path(i1, [drive_gent_kortrijk, drive_kortrijk_brugge, drive_brugge_oostende],
|
|
84
|
+
traveller_path(i1, [drive_gent_kortrijk, drive_kortrijk_brugge, drive_brugge_oostende], ?, ?, ?, ?).
|
|
85
85
|
|
|
86
86
|
check(c3, true) :-
|
|
87
|
-
route_metrics(routeDirect, ?d1,
|
|
88
|
-
route_metrics(routeViaKortrijk, ?d2,
|
|
87
|
+
route_metrics(routeDirect, ?d1, ?, ?, ?),
|
|
88
|
+
route_metrics(routeViaKortrijk, ?d2, ?, ?, ?),
|
|
89
89
|
lt(?d1, ?d2).
|
|
90
90
|
|
|
91
91
|
check(c4, true) :-
|
|
92
|
-
route_metrics(routeDirect,
|
|
93
|
-
route_metrics(routeViaKortrijk,
|
|
92
|
+
route_metrics(routeDirect, ?, ?c1, ?, ?),
|
|
93
|
+
route_metrics(routeViaKortrijk, ?, ?c2, ?, ?),
|
|
94
94
|
lt(?c1, ?c2).
|
|
95
95
|
|
|
96
96
|
check(c5, true) :-
|
|
97
|
-
route_metrics(routeDirect,
|
|
98
|
-
route_metrics(routeViaKortrijk,
|
|
97
|
+
route_metrics(routeDirect, ?, ?, ?b1, ?f1),
|
|
98
|
+
route_metrics(routeViaKortrijk, ?, ?, ?b2, ?f2),
|
|
99
99
|
gt(?b1, ?b2),
|
|
100
100
|
gt(?f1, ?f2).
|
|
101
101
|
|
|
@@ -67,22 +67,22 @@ fallacy(?a, hasty_generalization) :-
|
|
|
67
67
|
sample_size(?a, ?n),
|
|
68
68
|
required_sample_size(?a, ?min),
|
|
69
69
|
lt(?n, ?min),
|
|
70
|
-
concludes(?a, all(
|
|
70
|
+
concludes(?a, all(?, ?)).
|
|
71
71
|
|
|
72
72
|
fallacy(?a, false_dilemma) :-
|
|
73
73
|
argument(?a),
|
|
74
|
-
presented_alternatives(?a, ?
|
|
75
|
-
omitted_alternative(?a, ?
|
|
76
|
-
concludes(?a, ?
|
|
74
|
+
presented_alternatives(?a, ?),
|
|
75
|
+
omitted_alternative(?a, ?),
|
|
76
|
+
concludes(?a, ?).
|
|
77
77
|
|
|
78
78
|
reason(arg_affirming_consequent, "observing the consequent does not prove the antecedent").
|
|
79
79
|
reason(arg_denying_antecedent, "denying the antecedent does not disprove the consequent").
|
|
80
80
|
reason(arg_hasty_generalization, "sample size is below the threshold for a universal conclusion").
|
|
81
81
|
reason(arg_false_dilemma, "a relevant alternative is omitted").
|
|
82
82
|
|
|
83
|
-
type(?a, illegitimate_reasoning) :- fallacy(?a, ?
|
|
84
|
-
conclusion(?a, ?c) :- fallacy(?a, ?
|
|
85
|
-
reason(?a, ?r) :- fallacy(?a, ?
|
|
83
|
+
type(?a, illegitimate_reasoning) :- fallacy(?a, ?).
|
|
84
|
+
conclusion(?a, ?c) :- fallacy(?a, ?), concludes(?a, ?c).
|
|
85
|
+
reason(?a, ?r) :- fallacy(?a, ?), reason(?a, ?r).
|
|
86
86
|
sampleSize(?a, ?n) :- fallacy(?a, hasty_generalization), sample_size(?a, ?n).
|
|
87
87
|
requiredSampleSize(?a, ?min) :- fallacy(?a, hasty_generalization), required_sample_size(?a, ?min).
|
|
88
88
|
omittedAlternative(?a, ?alt) :- fallacy(?a, false_dilemma), omitted_alternative(?a, ?alt).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
% Four-colour search for the European Union neighbour graph.
|
|
2
|
+
%
|
|
3
|
+
% This is a finite executable version of the source map-colouring example. The
|
|
4
|
+
% neighbour facts are the EU country graph from the original input, represented
|
|
5
|
+
% with lowercase atom names. `once/1` asks for one valid colouring rather than
|
|
6
|
+
% enumerating all possible four-colour assignments.
|
|
7
|
+
|
|
8
|
+
materialize(four_color_answer, 2).
|
|
9
|
+
|
|
10
|
+
color(red).
|
|
11
|
+
color(green).
|
|
12
|
+
color(blue).
|
|
13
|
+
color(yellow).
|
|
14
|
+
|
|
15
|
+
place_order([belgium, netherlands, luxemburg, france, germany, italy, denmark, ireland, greece, spain, portugal, austria, sweden, finland, cyprus, malta, poland, hungary, czech_republic, slovakia, slovenia, estonia, latvia, lithuania, bulgaria, romania, croatia]).
|
|
16
|
+
|
|
17
|
+
neighbours(belgium, [france, netherlands, luxemburg, germany]).
|
|
18
|
+
neighbours(netherlands, [belgium, germany]).
|
|
19
|
+
neighbours(luxemburg, [belgium, france, germany]).
|
|
20
|
+
neighbours(france, [spain, belgium, luxemburg, germany, italy]).
|
|
21
|
+
neighbours(germany, [netherlands, belgium, luxemburg, denmark, france, austria, poland, czech_republic]).
|
|
22
|
+
neighbours(italy, [france, austria, slovenia]).
|
|
23
|
+
neighbours(denmark, [germany]).
|
|
24
|
+
neighbours(ireland, []).
|
|
25
|
+
neighbours(greece, [bulgaria]).
|
|
26
|
+
neighbours(spain, [france, portugal]).
|
|
27
|
+
neighbours(portugal, [spain]).
|
|
28
|
+
neighbours(austria, [czech_republic, germany, hungary, italy, slovenia, slovakia]).
|
|
29
|
+
neighbours(sweden, [finland]).
|
|
30
|
+
neighbours(finland, [sweden]).
|
|
31
|
+
neighbours(cyprus, []).
|
|
32
|
+
neighbours(malta, []).
|
|
33
|
+
neighbours(poland, [germany, czech_republic, slovakia, lithuania]).
|
|
34
|
+
neighbours(hungary, [austria, slovakia, romania, croatia, slovenia]).
|
|
35
|
+
neighbours(czech_republic, [germany, poland, slovakia, austria]).
|
|
36
|
+
neighbours(slovakia, [czech_republic, poland, hungary, austria]).
|
|
37
|
+
neighbours(slovenia, [austria, italy, hungary, croatia]).
|
|
38
|
+
neighbours(estonia, [latvia]).
|
|
39
|
+
neighbours(latvia, [estonia, lithuania]).
|
|
40
|
+
neighbours(lithuania, [latvia, poland]).
|
|
41
|
+
neighbours(bulgaria, [romania, greece]).
|
|
42
|
+
neighbours(romania, [hungary, bulgaria]).
|
|
43
|
+
neighbours(croatia, [slovenia, hungary]).
|
|
44
|
+
|
|
45
|
+
% Colour the tail first, like the source Prolog program. That gives each
|
|
46
|
+
% colour choice the already-coloured suffix to check against and avoids
|
|
47
|
+
% generating many doomed prefixes.
|
|
48
|
+
valid_color(?place, ?color, ?assigned) :-
|
|
49
|
+
neighbours(?place, ?neighbors),
|
|
50
|
+
not((member([?neighbor, ?color], ?assigned), member(?neighbor, ?neighbors))).
|
|
51
|
+
|
|
52
|
+
place_pairs([], []).
|
|
53
|
+
place_pairs([?place|?rest], [[?place, ?]|?pairs]) :-
|
|
54
|
+
place_pairs(?rest, ?pairs).
|
|
55
|
+
|
|
56
|
+
color_places([]).
|
|
57
|
+
color_places([[?place, ?color]|?tail]) :-
|
|
58
|
+
color_places(?tail),
|
|
59
|
+
color(?color),
|
|
60
|
+
valid_color(?place, ?color, ?tail).
|
|
61
|
+
|
|
62
|
+
four_color_answer(european_union, ?coloring) :-
|
|
63
|
+
place_order(?places),
|
|
64
|
+
place_pairs(?places, ?coloring),
|
|
65
|
+
once(color_places(?coloring)).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
% Matrix multiplication and non-commutativity.
|
|
2
|
+
%
|
|
3
|
+
% The original matrix example contains a larger matrix library. This compact
|
|
4
|
+
% Eyelang case keeps the core operation visible: multiply two 2x2 matrices and
|
|
5
|
+
% show that, in general, A*B is not the same matrix as B*A.
|
|
6
|
+
|
|
7
|
+
materialize(matrix_result, 2).
|
|
8
|
+
|
|
9
|
+
matrix_a([[1, 2], [0, 1]]).
|
|
10
|
+
matrix_b([[1, 0], [3, 1]]).
|
|
11
|
+
|
|
12
|
+
dot2([?x1, ?x2], [?y1, ?y2], ?r) :-
|
|
13
|
+
mul(?x1, ?y1, ?p1),
|
|
14
|
+
mul(?x2, ?y2, ?p2),
|
|
15
|
+
add(?p1, ?p2, ?r).
|
|
16
|
+
|
|
17
|
+
transpose2([[?a, ?b], [?c, ?d]], [[?a, ?c], [?b, ?d]]).
|
|
18
|
+
|
|
19
|
+
row_times_matrix(?row, ?matrix, [?r1, ?r2]) :-
|
|
20
|
+
transpose2(?matrix, [?col1, ?col2]),
|
|
21
|
+
dot2(?row, ?col1, ?r1),
|
|
22
|
+
dot2(?row, ?col2, ?r2).
|
|
23
|
+
|
|
24
|
+
matrix_mul([?row1, ?row2], ?matrix, [?out1, ?out2]) :-
|
|
25
|
+
row_times_matrix(?row1, ?matrix, ?out1),
|
|
26
|
+
row_times_matrix(?row2, ?matrix, ?out2).
|
|
27
|
+
|
|
28
|
+
matrix_result(ab, ?ab) :-
|
|
29
|
+
matrix_a(?a),
|
|
30
|
+
matrix_b(?b),
|
|
31
|
+
matrix_mul(?a, ?b, ?ab).
|
|
32
|
+
|
|
33
|
+
matrix_result(ba, ?ba) :-
|
|
34
|
+
matrix_a(?a),
|
|
35
|
+
matrix_b(?b),
|
|
36
|
+
matrix_mul(?b, ?a, ?ba).
|
|
37
|
+
|
|
38
|
+
matrix_result(commutative, false) :-
|
|
39
|
+
matrix_a(?a),
|
|
40
|
+
matrix_b(?b),
|
|
41
|
+
matrix_mul(?a, ?b, ?ab),
|
|
42
|
+
matrix_mul(?b, ?a, ?ba),
|
|
43
|
+
neq(?ab, ?ba).
|
|
@@ -19,9 +19,9 @@ plan(?moves) :-
|
|
|
19
19
|
goal_state(?g),
|
|
20
20
|
reachable(?i, ?moves, ?g).
|
|
21
21
|
|
|
22
|
-
candidate_plan([
|
|
23
|
-
candidate_plan([
|
|
24
|
-
candidate_plan([
|
|
22
|
+
candidate_plan([?, ?, ?]).
|
|
23
|
+
candidate_plan([?, ?, ?, ?]).
|
|
24
|
+
candidate_plan([?, ?, ?, ?, ?]).
|
|
25
25
|
|
|
26
26
|
reachable(?s, [], ?s).
|
|
27
27
|
reachable(?s1, [?m|?l], ?s3) :-
|
|
@@ -29,7 +29,7 @@ reachable(?s1, [?m|?l], ?s3) :-
|
|
|
29
29
|
reachable(?s2, ?l, ?s3).
|
|
30
30
|
|
|
31
31
|
initial_state([loc1, loc2, loc3, n, n]).
|
|
32
|
-
goal_state([
|
|
32
|
+
goal_state([?, ?, ?, ?, y]).
|
|
33
33
|
|
|
34
34
|
legal_move([?b, ?m, ?m, n, ?h], climb_on, [?b, ?m, ?m, y, ?h]).
|
|
35
35
|
legal_move([?b, ?m, ?m, y, ?h], climb_off, [?b, ?m, ?m, n, ?h]).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
four_color_answer(european_union, [[belgium, yellow], [netherlands, green], [luxemburg, green], [france, blue], [germany, red], [italy, red], [denmark, green], [ireland, red], [greece, red], [spain, green], [portugal, red], [austria, yellow], [sweden, green], [finland, red], [cyprus, red], [malta, red], [poland, blue], [hungary, blue], [czech_republic, green], [slovakia, red], [slovenia, green], [estonia, red], [latvia, green], [lithuania, red], [bulgaria, green], [romania, red], [croatia, red]]).
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
route_to_nantes(angers, go(angers, nantes, goal)).
|
|
2
|
+
route_to_nantes(paris, go(paris, chartres, go(chartres, lemans, go(lemans, angers, go(angers, nantes, goal))))).
|
|
3
|
+
route_to_nantes(chartres, go(chartres, lemans, go(lemans, angers, go(angers, nantes, goal)))).
|
|
4
|
+
route_to_nantes(lemans, go(lemans, angers, go(angers, nantes, goal))).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
polygon_area(sample, 7.5).
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
derivative_result(square, add(mul(const(1), var(x)), mul(var(x), const(1)))).
|
|
2
|
+
derivative_result(linear_plus_const, add(const(1), const(0))).
|
|
3
|
+
derivative_result(product, add(mul(add(const(1), const(0)), mul(add(pow(var(x), 2), const(2)), add(pow(var(x), 3), const(3)))), mul(add(var(x), const(1)), add(mul(add(mul(mul(const(2), pow(var(x), 1)), const(1)), const(0)), add(pow(var(x), 3), const(3))), mul(add(pow(var(x), 2), const(2)), add(mul(mul(const(3), pow(var(x), 2)), const(1)), const(0))))))).
|
|
4
|
+
derivative_result(nested_log, divide(divide(const(1), var(x)), log(var(x)))).
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
% Peano addition, multiplication, and factorial over explicit Herbrand terms.
|
|
2
|
+
%
|
|
3
|
+
% The original logic-programming example uses `0` and `s(...)`. Here zero is
|
|
4
|
+
% the atom `z`, so every natural number is an ordinary Eyelang term: z, s(z),
|
|
5
|
+
% s(s(z)), and so on. The rules are relational; the materialized facts choose
|
|
6
|
+
% a few finite calculations as readable examples.
|
|
7
|
+
|
|
8
|
+
materialize(peano_answer, 2).
|
|
9
|
+
table(padd, 3).
|
|
10
|
+
table(pmul, 3).
|
|
11
|
+
table(pfact, 2).
|
|
12
|
+
|
|
13
|
+
% Addition.
|
|
14
|
+
padd(?a, z, ?a).
|
|
15
|
+
padd(?a, s(?b), s(?c)) :-
|
|
16
|
+
padd(?a, ?b, ?c).
|
|
17
|
+
|
|
18
|
+
% Multiplication by repeated addition.
|
|
19
|
+
pmul(?_a, z, z).
|
|
20
|
+
pmul(?a, s(?b), ?c) :-
|
|
21
|
+
pmul(?a, ?b, ?d),
|
|
22
|
+
padd(?a, ?d, ?c).
|
|
23
|
+
|
|
24
|
+
% Factorial with an accumulator.
|
|
25
|
+
pfact(?n, ?value) :-
|
|
26
|
+
pfac(?n, s(z), ?value).
|
|
27
|
+
|
|
28
|
+
pfac(z, ?acc, ?acc).
|
|
29
|
+
pfac(s(?n), ?acc, ?value) :-
|
|
30
|
+
pmul(?acc, s(?n), ?next),
|
|
31
|
+
pfac(?n, ?next, ?value).
|
|
32
|
+
|
|
33
|
+
peano_answer(two_plus_three, ?n) :-
|
|
34
|
+
padd(s(s(z)), s(s(s(z))), ?n).
|
|
35
|
+
|
|
36
|
+
peano_answer(two_times_three, ?n) :-
|
|
37
|
+
pmul(s(s(z)), s(s(s(z))), ?n).
|
|
38
|
+
|
|
39
|
+
peano_answer(factorial_four, ?n) :-
|
|
40
|
+
pfact(s(s(s(s(z)))), ?n).
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
% Prime ranges and Euler totient over finite integer domains.
|
|
2
|
+
%
|
|
3
|
+
% The source example combines prime search with Euler's totient function. This
|
|
4
|
+
% Eyelang version keeps the computation finite and declarative: composite
|
|
5
|
+
% numbers are described by proper divisors, primes are candidates that are not
|
|
6
|
+
% composite, and `totient/2` counts numbers coprime with the input.
|
|
7
|
+
|
|
8
|
+
materialize(prime_result, 2).
|
|
9
|
+
table(gcd, 3).
|
|
10
|
+
|
|
11
|
+
candidate(?n) :-
|
|
12
|
+
between(2, 30, ?n).
|
|
13
|
+
|
|
14
|
+
composite(?n) :-
|
|
15
|
+
candidate(?n),
|
|
16
|
+
between(2, ?n, ?d),
|
|
17
|
+
lt(?d, ?n),
|
|
18
|
+
mod(?n, ?d, 0).
|
|
19
|
+
|
|
20
|
+
prime(?n) :-
|
|
21
|
+
candidate(?n),
|
|
22
|
+
not(composite(?n)).
|
|
23
|
+
|
|
24
|
+
% Euclid's algorithm, used for the totient calculation.
|
|
25
|
+
gcd(?n, 0, ?n).
|
|
26
|
+
gcd(?n, ?m, ?g) :-
|
|
27
|
+
gt(?m, 0),
|
|
28
|
+
mod(?n, ?m, ?r),
|
|
29
|
+
gcd(?m, ?r, ?g).
|
|
30
|
+
|
|
31
|
+
coprime(?n, ?k) :-
|
|
32
|
+
between(1, ?n, ?k),
|
|
33
|
+
gcd(?n, ?k, 1).
|
|
34
|
+
|
|
35
|
+
totient(?n, ?phi) :-
|
|
36
|
+
countall(coprime(?n, ?_k), ?phi).
|
|
37
|
+
|
|
38
|
+
prime_result(range_2_30, ?primes) :-
|
|
39
|
+
findall(?p, prime(?p), ?primes).
|
|
40
|
+
|
|
41
|
+
prime_result(count_2_30, ?count) :-
|
|
42
|
+
countall(prime(?p), ?count).
|
|
43
|
+
|
|
44
|
+
prime_result(totient_271, ?phi) :-
|
|
45
|
+
totient(271, ?phi).
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
% Route planning with explicit route terms.
|
|
2
|
+
%
|
|
3
|
+
% This is the Eyelang version of the classic Paris-to-Nantes path example: the
|
|
4
|
+
% facts describe one-way road links, and `path/2` derives both the endpoint pair
|
|
5
|
+
% and a structured `go(..., ..., ...)` plan. The plan is ordinary data, so the
|
|
6
|
+
% route can be inspected, stored, or used by later rules.
|
|
7
|
+
|
|
8
|
+
materialize(route_to_nantes, 2).
|
|
9
|
+
table(path, 2).
|
|
10
|
+
mode(path, 2, [in, out]).
|
|
11
|
+
|
|
12
|
+
oneway(paris, orleans).
|
|
13
|
+
oneway(paris, chartres).
|
|
14
|
+
oneway(paris, amiens).
|
|
15
|
+
oneway(orleans, blois).
|
|
16
|
+
oneway(orleans, bourges).
|
|
17
|
+
oneway(blois, tours).
|
|
18
|
+
oneway(chartres, lemans).
|
|
19
|
+
oneway(lemans, angers).
|
|
20
|
+
oneway(lemans, tours).
|
|
21
|
+
oneway(angers, nantes).
|
|
22
|
+
|
|
23
|
+
% A direct edge is a one-step plan.
|
|
24
|
+
path([?a, ?b], go(?a, ?b, goal)) :-
|
|
25
|
+
oneway(?a, ?b).
|
|
26
|
+
|
|
27
|
+
% A longer path prepends one edge to the remaining plan.
|
|
28
|
+
path([?a, ?c], go(?a, ?b, ?rest)) :-
|
|
29
|
+
oneway(?a, ?b),
|
|
30
|
+
path([?b, ?c], ?rest).
|
|
31
|
+
|
|
32
|
+
route_to_nantes(?from, ?plan) :-
|
|
33
|
+
path([?from, nantes], ?plan).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
% Polygon area by the shoelace formula.
|
|
2
|
+
%
|
|
3
|
+
% The input polygon is the same closed polygon shape used by the source example:
|
|
4
|
+
% the final point repeats the first point. Each recursive step consumes one
|
|
5
|
+
% adjacent pair and contributes `(x1*y2 - y1*x2) / 2` to the oriented area.
|
|
6
|
+
|
|
7
|
+
materialize(polygon_area, 2).
|
|
8
|
+
|
|
9
|
+
sample_polygon([[3, 2], [6, 2], [7, 6], [4, 6], [5, 5], [5, 3], [3, 2]]).
|
|
10
|
+
|
|
11
|
+
area([?_point], 0).
|
|
12
|
+
area([[?a, ?b], [?c, ?d]|?rest], ?total) :-
|
|
13
|
+
area([[?c, ?d]|?rest], ?subtotal),
|
|
14
|
+
mul(?a, ?d, ?ad),
|
|
15
|
+
mul(?b, ?c, ?bc),
|
|
16
|
+
sub(?ad, ?bc, ?cross),
|
|
17
|
+
div(?cross, 2.0, ?half),
|
|
18
|
+
add(?half, ?subtotal, ?total).
|
|
19
|
+
|
|
20
|
+
polygon_area(sample, ?area) :-
|
|
21
|
+
sample_polygon(?points),
|
|
22
|
+
area(?points, ?area).
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
% Symbolic differentiation over explicit expression terms.
|
|
2
|
+
%
|
|
3
|
+
% The source derivative example uses Prolog operators such as `+`, `*`, `^`, and
|
|
4
|
+
% cut. Eyelang keeps expressions as ordinary terms: `add/2`, `mul/2`, `pow/2`,
|
|
5
|
+
% `log/1`, and so on. The result is intentionally unsimplified so the rule that
|
|
6
|
+
% produced each part remains visible.
|
|
7
|
+
|
|
8
|
+
materialize(derivative_result, 2).
|
|
9
|
+
|
|
10
|
+
expr(square, mul(var(x), var(x))).
|
|
11
|
+
expr(linear_plus_const, add(var(x), const(3))).
|
|
12
|
+
expr(product, mul(add(var(x), const(1)), mul(add(pow(var(x), 2), const(2)), add(pow(var(x), 3), const(3))))).
|
|
13
|
+
expr(nested_log, log(log(var(x)))).
|
|
14
|
+
|
|
15
|
+
d(const(?_c), ?_x, const(0)).
|
|
16
|
+
d(var(?x), ?x, const(1)).
|
|
17
|
+
d(var(?y), ?x, const(0)) :-
|
|
18
|
+
neq(?x, ?y).
|
|
19
|
+
d(add(?u, ?v), ?x, add(?du, ?dv)) :-
|
|
20
|
+
d(?u, ?x, ?du),
|
|
21
|
+
d(?v, ?x, ?dv).
|
|
22
|
+
d(sub(?u, ?v), ?x, sub(?du, ?dv)) :-
|
|
23
|
+
d(?u, ?x, ?du),
|
|
24
|
+
d(?v, ?x, ?dv).
|
|
25
|
+
d(mul(?u, ?v), ?x, add(mul(?du, ?v), mul(?u, ?dv))) :-
|
|
26
|
+
d(?u, ?x, ?du),
|
|
27
|
+
d(?v, ?x, ?dv).
|
|
28
|
+
d(divide(?u, ?v), ?x, divide(sub(mul(?du, ?v), mul(?u, ?dv)), pow(?v, 2))) :-
|
|
29
|
+
d(?u, ?x, ?du),
|
|
30
|
+
d(?v, ?x, ?dv).
|
|
31
|
+
d(pow(?u, ?n), ?x, mul(mul(const(?n), pow(?u, ?n1)), ?du)) :-
|
|
32
|
+
sub(?n, 1, ?n1),
|
|
33
|
+
d(?u, ?x, ?du).
|
|
34
|
+
d(log(?u), ?x, divide(?du, ?u)) :-
|
|
35
|
+
d(?u, ?x, ?du).
|
|
36
|
+
|
|
37
|
+
derivative_result(?name, ?derivative) :-
|
|
38
|
+
expr(?name, ?expr),
|
|
39
|
+
d(?expr, x, ?derivative).
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
% Workplace compliance from explicit action facts.
|
|
2
|
+
%
|
|
3
|
+
% The source example generated a large dynamic dataset. Eyelang keeps the data
|
|
4
|
+
% explicit and reproducible: each `does/2` fact records an observed employee
|
|
5
|
+
% action, and the rules classify compliant and non-compliant behaviour.
|
|
6
|
+
|
|
7
|
+
materialize(status, 2).
|
|
8
|
+
|
|
9
|
+
employee(alice).
|
|
10
|
+
employee(bob).
|
|
11
|
+
employee(carol).
|
|
12
|
+
employee(dave).
|
|
13
|
+
|
|
14
|
+
does(alice, log_off_at_end_of_shift).
|
|
15
|
+
does(bob, work_related_task).
|
|
16
|
+
does(bob, log_off_at_end_of_shift).
|
|
17
|
+
does(carol, access_social_media).
|
|
18
|
+
does(dave, work_related_task).
|
|
19
|
+
|
|
20
|
+
% Work-related activity is compliant when the employee also logs off.
|
|
21
|
+
status(?person, compliant) :-
|
|
22
|
+
employee(?person),
|
|
23
|
+
does(?person, work_related_task),
|
|
24
|
+
does(?person, log_off_at_end_of_shift).
|
|
25
|
+
|
|
26
|
+
% Logging off is compliant by itself when no work task was observed.
|
|
27
|
+
status(?person, compliant) :-
|
|
28
|
+
employee(?person),
|
|
29
|
+
does(?person, log_off_at_end_of_shift),
|
|
30
|
+
not(does(?person, work_related_task)).
|
|
31
|
+
|
|
32
|
+
% A work task without the required log-off is non-compliant.
|
|
33
|
+
status(?person, non_compliant) :-
|
|
34
|
+
employee(?person),
|
|
35
|
+
does(?person, work_related_task),
|
|
36
|
+
not(does(?person, log_off_at_end_of_shift)).
|
|
37
|
+
|
|
38
|
+
% Accessing social media is non-compliant in this policy.
|
|
39
|
+
status(?person, non_compliant) :-
|
|
40
|
+
employee(?person),
|
|
41
|
+
does(?person, access_social_media).
|
package/examples/zebra.eye
CHANGED
|
@@ -12,33 +12,33 @@ materialize(solved, 2).
|
|
|
12
12
|
|
|
13
13
|
% The single zebra/2 rule is a finite constraint model over the five house slots.
|
|
14
14
|
zebra(?waterdrinker, ?zebraowner) :-
|
|
15
|
-
eq(?houses, [
|
|
16
|
-
first(?houses, house(
|
|
17
|
-
third(?houses, house(
|
|
18
|
-
adjacent(house(
|
|
19
|
-
next_to(house(ivory,
|
|
20
|
-
member(house(red, english,
|
|
21
|
-
member(house(green,
|
|
22
|
-
member(house(yellow,
|
|
23
|
-
member(house(
|
|
24
|
-
member(house(
|
|
25
|
-
member(house(
|
|
26
|
-
adjacent(house(
|
|
27
|
-
adjacent(house(
|
|
28
|
-
member(house(
|
|
29
|
-
member(house(
|
|
30
|
-
member(house(
|
|
31
|
-
member(house(
|
|
15
|
+
eq(?houses, [?, ?, ?, ?, ?]),
|
|
16
|
+
first(?houses, house(?, norwegian, ?, ?, ?)),
|
|
17
|
+
third(?houses, house(?, ?, ?, milk, ?)),
|
|
18
|
+
adjacent(house(?, norwegian, ?, ?, ?), house(blue, ?, ?, ?, ?), ?houses),
|
|
19
|
+
next_to(house(ivory, ?, ?, ?, ?), house(green, ?, ?, ?, ?), ?houses),
|
|
20
|
+
member(house(red, english, ?, ?, ?), ?houses),
|
|
21
|
+
member(house(green, ?, ?, coffee, ?), ?houses),
|
|
22
|
+
member(house(yellow, ?, ?, ?, kools), ?houses),
|
|
23
|
+
member(house(?, spanish, dog, ?, ?), ?houses),
|
|
24
|
+
member(house(?, ukrainian, ?, tea, ?), ?houses),
|
|
25
|
+
member(house(?, ?, snail, ?, old_gold), ?houses),
|
|
26
|
+
adjacent(house(?, ?, ?, ?, chesterfields), house(?, ?, fox, ?, ?), ?houses),
|
|
27
|
+
adjacent(house(?, ?, ?, ?, kools), house(?, ?, horse, ?, ?), ?houses),
|
|
28
|
+
member(house(?, ?, ?, orange_juice, lucky_strike), ?houses),
|
|
29
|
+
member(house(?, japanese, ?, ?, parliaments), ?houses),
|
|
30
|
+
member(house(?, ?waterdrinker, ?, water, ?), ?houses),
|
|
31
|
+
member(house(?, ?zebraowner, zebra, ?, ?), ?houses).
|
|
32
32
|
|
|
33
33
|
% Positional and neighborhood helpers keep the clue encoding readable.
|
|
34
|
-
first([?x|?
|
|
35
|
-
third([
|
|
34
|
+
first([?x|?], ?x).
|
|
35
|
+
third([?, ?, ?x|?], ?x).
|
|
36
36
|
|
|
37
37
|
adjacent(?a, ?b, ?list) :- next_to(?a, ?b, ?list).
|
|
38
38
|
adjacent(?a, ?b, ?list) :- next_to(?b, ?a, ?list).
|
|
39
39
|
|
|
40
|
-
next_to(?x, ?y, [?x, ?y|?
|
|
41
|
-
next_to(?x, ?y, [
|
|
40
|
+
next_to(?x, ?y, [?x, ?y|?]).
|
|
41
|
+
next_to(?x, ?y, [?|?zs]) :- next_to(?x, ?y, ?zs).
|
|
42
42
|
|
|
43
43
|
waterDrinker(zebraPuzzle, ?waterdrinker) :- zebra(?waterdrinker, ?_zebraowner).
|
|
44
44
|
zebraOwner(zebraPuzzle, ?zebraowner) :- zebra(?_waterdrinker, ?zebraowner).
|
package/package.json
CHANGED
package/playground.html
CHANGED
|
@@ -522,6 +522,7 @@
|
|
|
522
522
|
"hamming-code",
|
|
523
523
|
"hanoi",
|
|
524
524
|
"heat-loss",
|
|
525
|
+
"herbrand-witnesses",
|
|
525
526
|
"heron-theorem",
|
|
526
527
|
"ideal-gas-law",
|
|
527
528
|
"illegitimate-reasoning",
|
|
@@ -537,7 +538,9 @@
|
|
|
537
538
|
"list-collection",
|
|
538
539
|
"lldm",
|
|
539
540
|
"manufacturing-quality-control",
|
|
541
|
+
"map-four-color-search",
|
|
540
542
|
"matrix-chain-order",
|
|
543
|
+
"matrix-noncommutativity",
|
|
541
544
|
"microgrid-dispatch",
|
|
542
545
|
"missionaries-cannibals",
|
|
543
546
|
"modal-logic-kripke",
|
|
@@ -554,21 +557,24 @@
|
|
|
554
557
|
"orbital-transfer-design",
|
|
555
558
|
"path-discovery",
|
|
556
559
|
"peano-arithmetic",
|
|
560
|
+
"peano-calculus",
|
|
557
561
|
"peasant",
|
|
558
562
|
"pell-equation",
|
|
559
563
|
"pendulum-period",
|
|
560
564
|
"polynomial",
|
|
565
|
+
"prime-range",
|
|
561
566
|
"proof-contrapositive",
|
|
562
567
|
"quadratic-formula",
|
|
563
568
|
"radioactive-decay",
|
|
564
569
|
"reusable-builtins",
|
|
565
570
|
"riemann-hypothesis",
|
|
571
|
+
"route-planning",
|
|
566
572
|
"security-incident-correlation",
|
|
567
573
|
"send-more-money",
|
|
568
574
|
"service-impact",
|
|
575
|
+
"shoelace-polygon-area",
|
|
569
576
|
"sieve",
|
|
570
577
|
"skolem-functions",
|
|
571
|
-
"herbrand-witnesses",
|
|
572
578
|
"socket-age",
|
|
573
579
|
"socket-family",
|
|
574
580
|
"socrates",
|
|
@@ -577,6 +583,7 @@
|
|
|
577
583
|
"stirling-bell-numbers",
|
|
578
584
|
"sudoku-4x4",
|
|
579
585
|
"superdense-coding",
|
|
586
|
+
"symbolic-derivative",
|
|
580
587
|
"term-tools",
|
|
581
588
|
"totient-summatory",
|
|
582
589
|
"trust-flow-provenance-threshold",
|
|
@@ -587,6 +594,7 @@
|
|
|
587
594
|
"weighted-interval-scheduling",
|
|
588
595
|
"witch",
|
|
589
596
|
"wolf-goat-cabbage",
|
|
597
|
+
"workplace-compliance",
|
|
590
598
|
"zebra"
|
|
591
599
|
];
|
|
592
600
|
const FALLBACK_SOURCE = `materialize(answer, 1).
|
|
@@ -861,9 +869,12 @@ answer(ok) :- eq(ok, ok).
|
|
|
861
869
|
while (j < text.length && /[\d.]/.test(text[j])) j++;
|
|
862
870
|
out += span('number', text.slice(i, j));
|
|
863
871
|
i = j;
|
|
864
|
-
} else if (ch === '?'
|
|
865
|
-
let j = i +
|
|
866
|
-
|
|
872
|
+
} else if (ch === '?') {
|
|
873
|
+
let j = i + 1;
|
|
874
|
+
if (/[A-Za-z_]/.test(text[j] || '')) {
|
|
875
|
+
j++;
|
|
876
|
+
while (j < text.length && /[A-Za-z0-9_]/.test(text[j])) j++;
|
|
877
|
+
}
|
|
867
878
|
out += span('variable', text.slice(i, j));
|
|
868
879
|
i = j;
|
|
869
880
|
} else if (/[a-z]/.test(ch)) {
|
package/src/parser.js
CHANGED
|
@@ -43,14 +43,14 @@ function isNameContinueCode(code) {
|
|
|
43
43
|
function isQuestionVariableStart(source, pos) {
|
|
44
44
|
if (source[pos] !== '?') return false;
|
|
45
45
|
const code = (source[pos + 1] ?? '').charCodeAt(0);
|
|
46
|
-
return code === 95 || isAsciiLetterCode(code);
|
|
46
|
+
return !source[pos + 1] || code === 95 || isAsciiLetterCode(code) || !isNameContinueCode(code);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function isPlainAtomStartCode(code) {
|
|
50
50
|
return code >= 97 && code <= 122;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const graphicAtomChars = '
|
|
53
|
+
const graphicAtomChars = '#$&*+-/<=>@^~\\';
|
|
54
54
|
|
|
55
55
|
function isGraphicAtomCode(code) {
|
|
56
56
|
return graphicAtomChars.includes(String.fromCharCode(code));
|
|
@@ -172,10 +172,9 @@ class Parser {
|
|
|
172
172
|
if (isQuestionVariableStart(this.source, this.pos)) {
|
|
173
173
|
const start = this.pos;
|
|
174
174
|
this.take(); // ?
|
|
175
|
-
this.take();
|
|
175
|
+
if (isNameContinueCode(this.peek().charCodeAt(0))) this.take();
|
|
176
176
|
while (isNameContinueCode(this.peek().charCodeAt(0))) this.take();
|
|
177
|
-
|
|
178
|
-
if (text === '?_') text = `__anon${this.anonymous++}`;
|
|
177
|
+
const text = this.source.slice(start, this.pos);
|
|
179
178
|
return { type: TOK.VAR, text, line };
|
|
180
179
|
}
|
|
181
180
|
|
|
@@ -259,6 +258,7 @@ class Parser {
|
|
|
259
258
|
if (this.token.type === TOK.VAR) {
|
|
260
259
|
const name = this.token.text;
|
|
261
260
|
this.advance();
|
|
261
|
+
if (name === '?') return variable(`__anon${this.anonymous++}`);
|
|
262
262
|
return variable(name);
|
|
263
263
|
}
|
|
264
264
|
if (this.token.type === TOK.STRING) {
|
|
@@ -346,9 +346,9 @@ function isSimpleName(text) {
|
|
|
346
346
|
const SIMPLE_NUMBER = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
347
347
|
const FAST_BINARY_FACT = /^([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\.$/;
|
|
348
348
|
const FAST_BINARY_RULE = /^([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\s*:-\s*([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\.$/;
|
|
349
|
-
const SIMPLE_VARIABLE = /^\?[A-Za-z_][A-Za-z0-9_]
|
|
349
|
+
const SIMPLE_VARIABLE = /^\?(?:[A-Za-z_][A-Za-z0-9_]*)?$/;
|
|
350
350
|
const SIMPLE_ATOM = /^[a-z][A-Za-z0-9_]*$/;
|
|
351
|
-
const GRAPHIC_ATOM = /^[
|
|
351
|
+
const GRAPHIC_ATOM = /^[#$&*+\-\/<=>@^~\\]+$/;
|
|
352
352
|
|
|
353
353
|
function parseClausesFastNoSource(source) {
|
|
354
354
|
source = String(source ?? '');
|
|
@@ -370,7 +370,7 @@ function parseClausesFastNoSource(source) {
|
|
|
370
370
|
const scalarOrVariableFast = (text) => {
|
|
371
371
|
if (!text || !isFastScalarToken(text)) throw new Error('bad simple term');
|
|
372
372
|
const first = text.charCodeAt(0);
|
|
373
|
-
if (text === '?
|
|
373
|
+
if (text === '?') return variable(`__anon${anonymous++}`);
|
|
374
374
|
if (SIMPLE_VARIABLE.test(text)) {
|
|
375
375
|
const existing = variableCache.get(text);
|
|
376
376
|
if (existing) return existing;
|
package/src/term.js
CHANGED
|
@@ -136,7 +136,7 @@ export function termIsGround(term, env = new Env()) {
|
|
|
136
136
|
return resolved.args.every((arg) => termIsGround(arg, env));
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
const graphicAtomChars = new Set('
|
|
139
|
+
const graphicAtomChars = new Set('#$&*+-/<=>@^~\\'.split(''));
|
|
140
140
|
|
|
141
141
|
function isAbsoluteIriText(text) {
|
|
142
142
|
return /^[A-Za-z][A-Za-z0-9+.-]*:[^\s<>"'{}|\\^`]*$/.test(text);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(division_by_zero_fails) :- div(1, 0, ?
|
|
2
|
+
answer(division_by_zero_fails) :- div(1, 0, ?).
|
|
@@ -3,5 +3,5 @@ materialize(iri_subject, 1).
|
|
|
3
3
|
materialize(iri_object, 1).
|
|
4
4
|
triple(<https://example.org/alice>, <https://schema.org/name>, "Alice").
|
|
5
5
|
triple(<urn:example:bob>, <https://schema.org/knows>, <https://example.org/alice>).
|
|
6
|
-
iri_subject(?iri) :- triple(?iri,
|
|
7
|
-
iri_object(?iri) :- triple(
|
|
6
|
+
iri_subject(?iri) :- triple(?iri, ?, ?).
|
|
7
|
+
iri_object(?iri) :- triple(?, <https://schema.org/knows>, ?iri).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(difference_end_before_start_fails) :- difference("2024-01-01", "2024-01-02", ?
|
|
2
|
+
answer(difference_end_before_start_fails) :- difference("2024-01-01", "2024-01-02", ?).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(difference_invalid_date_fails) :- difference("2024-02-30", "2024-02-01", ?
|
|
2
|
+
answer(difference_invalid_date_fails) :- difference("2024-02-30", "2024-02-01", ?).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(holds_ignores_string_parts) :- holds("not a term",
|
|
2
|
+
answer(holds_ignores_string_parts) :- holds("not a term", ?, ?).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
% Reference 5.3, 5.4: lists may contain structured terms that unify positionally.
|
|
2
2
|
node([pair(a, b), pair(c, d)]).
|
|
3
|
-
answer(first_key, ?x) :- node([pair(?x, ?
|
|
3
|
+
answer(first_key, ?x) :- node([pair(?x, ?), pair(c, d)]).
|
|
4
4
|
answer(second_key, ?x) :- node([pair(a, b), pair(?x, d)]).
|
|
5
5
|
materialize(answer, 2).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(length_improper_fails) :- length([a | b], ?
|
|
2
|
+
answer(length_improper_fails) :- length([a | b], ?).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
% Reference 5.3, 6, 7.1: structured rule heads destructure matching goals.
|
|
2
2
|
unpack(pair(?x, ?y), ?x, ?y).
|
|
3
|
-
answer(first, ?a) :- unpack(pair(alpha, beta), ?a, ?
|
|
4
|
-
answer(second, ?b) :- unpack(pair(alpha, beta),
|
|
3
|
+
answer(first, ?a) :- unpack(pair(alpha, beta), ?a, ?).
|
|
4
|
+
answer(second, ?b) :- unpack(pair(alpha, beta), ?, ?b).
|
|
5
5
|
materialize(answer, 2).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(arg_atom_fails) :- arg(1, atom, ?
|
|
2
|
+
answer(arg_atom_fails) :- arg(1, atom, ?).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(arg_zero_fails) :- arg(0, pair(a, b), ?
|
|
2
|
+
answer(arg_zero_fails) :- arg(0, pair(a, b), ?).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(compound_name_arguments_bad_args_fails) :- compound_name_arguments(
|
|
2
|
+
answer(compound_name_arguments_bad_args_fails) :- compound_name_arguments(?, pair, not_a_list).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
materialize(answer, 1).
|
|
2
|
-
answer(anonymous_not_reused) :- eq(pair(
|
|
2
|
+
answer(anonymous_not_reused) :- eq(pair(?, ?), pair(a, b)).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
% Each
|
|
1
|
+
% Each `?` occurrence is anonymous and independent.
|
|
2
2
|
materialize(answer, 1).
|
|
3
3
|
pair(a, b).
|
|
4
4
|
pair(c, d).
|
|
5
|
-
answer(left(?x)) :- pair(?x, ?
|
|
6
|
-
answer(right(?y)) :- pair(
|
|
5
|
+
answer(left(?x)) :- pair(?x, ?).
|
|
6
|
+
answer(right(?y)) :- pair(?, ?y).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
parse line 1:
|
|
1
|
+
parse line 1: bad character "?"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
parse line 1:
|
|
1
|
+
parse line 1: bad character "?"
|
package/test/run-regression.mjs
CHANGED
|
@@ -639,9 +639,9 @@ function whiteBoxCases() {
|
|
|
639
639
|
},
|
|
640
640
|
},
|
|
641
641
|
{
|
|
642
|
-
name: 'parser treats question
|
|
642
|
+
name: 'parser treats bare question mark as anonymous',
|
|
643
643
|
run: () => {
|
|
644
|
-
const clauses = parseProgramText('p(
|
|
644
|
+
const clauses = parseProgramText('p(?, ?).\n');
|
|
645
645
|
const left = clauses[0].head.args[0].name;
|
|
646
646
|
const right = clauses[0].head.args[1].name;
|
|
647
647
|
assertEqual(left.startsWith('__anon'), true, 'left anonymous');
|