eyeprolog 0.5.18 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/README.md +2 -2
  2. package/conformance-report.md +2 -2
  3. package/examples/blocks-world-planning.pl +3 -3
  4. package/examples/combinatorics-findall-sort.pl +4 -4
  5. package/examples/complex.pl +3 -3
  6. package/examples/d3-group.pl +3 -3
  7. package/examples/dijkstra-findall-sort.pl +3 -3
  8. package/examples/enigma1225.pl +1 -1
  9. package/examples/eulerian-path.pl +4 -4
  10. package/examples/four-color-map.pl +2 -2
  11. package/examples/input/odrl-dpv-healthcare-risk-ranked-rules.pl +1 -1
  12. package/examples/input/odrl-dpv-risk-ranked-rules.pl +1 -1
  13. package/examples/input/rdf12-annotated-claims-rules.pl +1 -1
  14. package/examples/odrl-dpv-healthcare-risk-ranked.pl +1 -1
  15. package/examples/odrl-dpv-risk-ranked.pl +1 -1
  16. package/examples/output/complex.pl +5 -0
  17. package/examples/output/enigma1225.pl +1 -1
  18. package/examples/output/iso-integer-arithmetic.pl +1 -1
  19. package/examples/proof/d3-group.pl +4 -4
  20. package/examples/proof/iso-dynamic-database.pl +1 -1
  21. package/examples/quine-mccluskey.pl +7 -7
  22. package/examples/rdf12-annotated-claims.pl +1 -1
  23. package/examples/sudoku.pl +1 -1
  24. package/package.json +1 -1
  25. package/playground.html +0 -2
  26. package/src/eyeprolog-autoload.js +1 -7
  27. package/src/eyeprolog-common-library.pl +1 -1
  28. package/src/eyeprolog-library.pl +10 -57
  29. package/src/iso.js +229 -19
  30. package/src/parser.js +39 -19
  31. package/src/program.js +5 -2
  32. package/test/conformance/ISO-MATRIX.md +37 -0
  33. package/test/conformance/README.md +3 -1
  34. package/test/conformance/cases/aggregation/098_aggregation_nested_templates.pl +3 -0
  35. package/test/conformance/cases/arithmetic/062_reusable_numeric_builtins.pl +2 -2
  36. package/test/conformance/cases/arithmetic/081_zero_safe_numeric_functions.pl +2 -2
  37. package/test/conformance/cases/arithmetic/extra_acos_one.pl +1 -1
  38. package/test/conformance/cases/arithmetic/extra_asin_zero.pl +1 -1
  39. package/test/conformance/cases/arithmetic/extra_atan2_axis.pl +1 -1
  40. package/test/conformance/cases/iso/corrigenda_arithmetic.pl +15 -0
  41. package/test/conformance/cases/iso/corrigenda_bar_operator.pl +10 -0
  42. package/test/conformance/cases/iso/corrigenda_call_closure.pl +9 -0
  43. package/test/conformance/cases/iso/corrigenda_catch_callability.pl +7 -0
  44. package/test/conformance/cases/iso/corrigenda_retractall.pl +14 -0
  45. package/test/conformance/cases/iso/corrigenda_sort_keysort.pl +10 -0
  46. package/test/conformance/cases/iso/corrigenda_term_predicates.pl +11 -0
  47. package/test/conformance/cases/iso/corrigendum1_double_quote_operator.pl +9 -0
  48. package/test/conformance/cases/iso/corrigendum3_write_variable_names.pl +8 -0
  49. package/test/conformance/cases/lists/031_lists_aggregation_ordering.pl +1 -1
  50. package/test/conformance/cases/lists/045_sort_deduplicates_atoms.pl +2 -2
  51. package/test/conformance/cases/lists/087_sort_reverse_length.pl +2 -2
  52. package/test/conformance/cases/lists/extra_sort_iri_atoms.pl +1 -1
  53. package/test/conformance/cases/lists/sort_structured_terms.pl +1 -1
  54. package/test/conformance/errors/iso/arithmetic_float_overflow.pl +3 -0
  55. package/test/conformance/errors/iso/arithmetic_underflow.pl +3 -0
  56. package/test/conformance/errors/iso/catch_unbound_goal.pl +1 -1
  57. package/test/conformance/errors/iso/corrigenda_atan2_zero.pl +3 -0
  58. package/test/conformance/errors/iso/corrigenda_integer_negative_power.pl +3 -0
  59. package/test/conformance/errors/iso/corrigenda_keysort_pair_type.pl +3 -0
  60. package/test/conformance/errors/iso/corrigenda_op_bar_priority.pl +3 -0
  61. package/test/conformance/errors/iso/corrigenda_op_empty_list.pl +3 -0
  62. package/test/conformance/errors/iso/corrigenda_op_infix_postfix_conflict.pl +5 -0
  63. package/test/conformance/errors/iso/corrigenda_open_uninstantiation.pl +3 -0
  64. package/test/conformance/errors/iso/corrigenda_retractall_static.pl +4 -0
  65. package/test/conformance/errors/iso/corrigenda_sort_output_type.pl +3 -0
  66. package/test/conformance/errors/iso/corrigenda_sort_partial.pl +3 -0
  67. package/test/conformance/errors/iso/corrigendum3_close_option_component_variable.pl +3 -0
  68. package/test/conformance/errors/iso/corrigendum3_open_option_variable.pl +3 -0
  69. package/test/conformance/errors/iso/corrigendum3_write_option_variable.pl +3 -0
  70. package/test/conformance/expected/aggregation/098_aggregation_nested_templates.pl +1 -0
  71. package/test/conformance/expected/iso/corrigenda_arithmetic.pl +1 -0
  72. package/test/conformance/expected/iso/corrigenda_bar_operator.pl +1 -0
  73. package/test/conformance/expected/iso/corrigenda_call_closure.pl +1 -0
  74. package/test/conformance/expected/iso/corrigenda_catch_callability.pl +1 -0
  75. package/test/conformance/expected/iso/corrigenda_retractall.pl +1 -0
  76. package/test/conformance/expected/iso/corrigenda_sort_keysort.pl +1 -0
  77. package/test/conformance/expected/iso/corrigenda_term_predicates.pl +1 -0
  78. package/test/conformance/expected/iso/corrigendum1_double_quote_operator.pl +1 -0
  79. package/test/conformance/expected/iso/corrigendum3_write_variable_names.pl +2 -0
  80. package/test/conformance/expected-errors/iso/arithmetic_float_overflow.txt +1 -0
  81. package/test/conformance/expected-errors/iso/arithmetic_underflow.txt +1 -0
  82. package/test/conformance/expected-errors/iso/corrigenda_atan2_zero.txt +1 -0
  83. package/test/conformance/expected-errors/iso/corrigenda_integer_negative_power.txt +1 -0
  84. package/test/conformance/expected-errors/iso/corrigenda_keysort_pair_type.txt +1 -0
  85. package/test/conformance/expected-errors/iso/corrigenda_op_bar_priority.txt +1 -0
  86. package/test/conformance/expected-errors/iso/corrigenda_op_empty_list.txt +1 -0
  87. package/test/conformance/expected-errors/iso/corrigenda_op_infix_postfix_conflict.txt +1 -0
  88. package/test/conformance/expected-errors/iso/corrigenda_open_uninstantiation.txt +1 -0
  89. package/test/conformance/expected-errors/iso/corrigenda_retractall_static.txt +1 -0
  90. package/test/conformance/expected-errors/iso/corrigenda_sort_output_type.txt +1 -0
  91. package/test/conformance/expected-errors/iso/corrigenda_sort_partial.txt +1 -0
  92. package/test/conformance/expected-errors/iso/corrigendum3_close_option_component_variable.txt +1 -0
  93. package/test/conformance/expected-errors/iso/corrigendum3_open_option_variable.txt +1 -0
  94. package/test/conformance/expected-errors/iso/corrigendum3_write_option_variable.txt +1 -0
  95. package/test/conformance/expected-errors/iso/retract_static_procedure.txt +1 -1
  96. package/test/run-regression.mjs +3 -3
  97. package/the-art-of-eyeprolog.md +43 -42
package/README.md CHANGED
@@ -29,8 +29,8 @@ proper list of one-character atoms (`chars`), matching Trealla and Scryer.
29
29
 
30
30
  ## Portable library
31
31
 
32
- EyeProlog adds 50 public library predicates to its 115-predicate ISO profile.
33
- **All 50 are ordinary Prolog clauses** across `src/eyeprolog-library.pl` and
32
+ EyeProlog adds 44 public library predicates to its 127-entry ISO core registry.
33
+ **All 44 are ordinary Prolog clauses** across `src/eyeprolog-library.pl` and
34
34
  `src/eyeprolog-common-library.pl`; both are autoloaded in Node and the
35
35
  browser. None requires host support. Other Prolog systems should load only
36
36
  `eyeprolog-library.pl`, which avoids redefining their common list predicates.
@@ -11,7 +11,7 @@ This report summarizes the file-based conformance corpus under `test/conformance
11
11
  | builtins | 11 | 0 | 0 | 0 | 11 |
12
12
  | context | 11 | 0 | 0 | 0 | 11 |
13
13
  | control | 15 | 0 | 0 | 0 | 15 |
14
- | iso | 121 | 159 | 0 | 0 | 280 |
14
+ | iso | 130 | 174 | 0 | 0 | 304 |
15
15
  | lists | 52 | 3 | 0 | 0 | 55 |
16
16
  | negation | 8 | 0 | 19 | 0 | 27 |
17
17
  | proofs | 0 | 0 | 0 | 21 | 21 |
@@ -22,4 +22,4 @@ This report summarizes the file-based conformance corpus under `test/conformance
22
22
  | terms | 26 | 3 | 0 | 0 | 29 |
23
23
  | unification | 18 | 0 | 0 | 0 | 18 |
24
24
  | variables | 16 | 9 | 0 | 0 | 25 |
25
- | **Total** | **434** | **212** | **19** | **21** | **686** |
25
+ | **Total** | **443** | **227** | **19** | **21** | **710** |
@@ -48,7 +48,7 @@ move(State, move(Block, From, To), Newstate) :-
48
48
  (Block \= To),
49
49
  (From \= To),
50
50
  select(on(Block, From), State, Rest),
51
- sort_unique([on(Block, To)|Rest], Newstate).
51
+ sort([on(Block, To)|Rest], Newstate).
52
52
 
53
53
  plan(State, Goal, 0, _visited, [], State) :-
54
54
  (State = Goal).
@@ -63,8 +63,8 @@ plan(State, Goal, Depth, Visited, [Move|Moves], Final) :-
63
63
  five_move_plan(Moves, Final) :-
64
64
  initial(Start),
65
65
  goal(Goal),
66
- sort_unique(Start, Sortedstart),
67
- sort_unique(Goal, Sortedgoal),
66
+ sort(Start, Sortedstart),
67
+ sort(Goal, Sortedgoal),
68
68
  plan(Sortedstart, Sortedgoal, 5, [Sortedstart], Moves, Final).
69
69
 
70
70
  status(blocks_world, planned) :-
@@ -1,7 +1,7 @@
1
- % Eyelet-inspired combinations example using findall/3 and sort_unique/2.
1
+ % Eyelet-inspired combinations example using findall/3 and sort/2.
2
2
  %
3
3
  % combination/3 generates the same subset in several selection orders. findall/3
4
- % collects those candidates, and sort_unique/2 canonicalizes the list so each unordered
4
+ % collects those candidates, and sort/2 canonicalizes the list so each unordered
5
5
  % 3-combination of five items is reported once.
6
6
  %% goal: combinations(X0, X1)
7
7
 
@@ -24,12 +24,12 @@ combination(I, Items, Combination) :-
24
24
  select(Item, Items, Remaining),
25
25
  (J is I - 1),
26
26
  combination(J, Remaining, Partial),
27
- sort_unique([Item | Partial], Combination).
27
+ sort([Item | Partial], Combination).
28
28
 
29
29
  % findall collects all generation orders; sort canonicalizes and deduplicates.
30
30
  unique_combinations(K, Items, Unique) :-
31
31
  findall(C, combination(K, Items, C), All),
32
- sort_unique(All, Unique).
32
+ sort(All, Unique).
33
33
 
34
34
  combinations(combinations_5_choose_3, Unique) :-
35
35
  unique_combinations(3, [1, 2, 3, 4, 5], Unique).
@@ -50,7 +50,7 @@ complex_asin([A, B], [C, D]) :-
50
50
  (E is Z10 / 2),
51
51
  (Z11 is Z5 + Z9),
52
52
  (F is Z11 / 2),
53
- asin(E, C),
53
+ (C is asin(E)),
54
54
  (Z12 is F ** 2),
55
55
  (Z13 is Z12 - 1),
56
56
  (Z14 is Z13 ** 0.5),
@@ -71,7 +71,7 @@ complex_acos([A, B], [C, D]) :-
71
71
  (E is Z10 / 2),
72
72
  (Z11 is Z5 + Z9),
73
73
  (F is Z11 / 2),
74
- acos(E, C),
74
+ (C is acos(E)),
75
75
  (Z12 is F ** 2),
76
76
  (Z13 is Z12 - 1),
77
77
  (Z14 is Z13 ** 0.5),
@@ -86,7 +86,7 @@ complex_polar([X, Y], [R, Tp]) :-
86
86
  (R is Z3 ** 0.5),
87
87
  (Z4 is abs(X)),
88
88
  (Z5 is Z4 / R),
89
- acos(Z5, T),
89
+ (T is acos(Z5)),
90
90
  complex_dial(X, Y, T, Tp).
91
91
 
92
92
  complex_dial(X, Y, T, Tp) :-
@@ -1,4 +1,4 @@
1
- % Eyelet-inspired D3 group example using findall/3 and sort_unique/2.
1
+ % Eyelet-inspired D3 group example using findall/3 and sort/2.
2
2
  % The six facts are the symmetries of an equilateral triangle, with compose/3 as
3
3
  % the Cayley table and inverse/2 as the inverse relation. Candidate subsets are
4
4
  % generated as subsequences, then filtered for subgroup closure.
@@ -72,7 +72,7 @@ subsequence([_head | Tail], Rest) :-
72
72
 
73
73
  all_symmetries(Symmetries) :-
74
74
  findall(X, symmetry(X), Raw),
75
- sort_unique(Raw, Symmetries).
75
+ sort(Raw, Symmetries).
76
76
 
77
77
  % A valid subgroup is closed under both composition and inverse.
78
78
  closed_under_composition(Group) :-
@@ -90,7 +90,7 @@ valid_group(Group) :-
90
90
 
91
91
  all_subgroups(Groups) :-
92
92
  findall(G, valid_group(G), Raw),
93
- sort_unique(Raw, Groups).
93
+ sort(Raw, Groups).
94
94
 
95
95
  subgroups(d3_group, Groups) :-
96
96
  all_subgroups(Groups).
@@ -1,7 +1,7 @@
1
- % Eyelet-inspired Dijkstra example using findall/3 and sort_unique/2.
1
+ % Eyelet-inspired Dijkstra example using findall/3 and sort/2.
2
2
  % The priority queue is represented as sorted list entries [Cost, Node | Path].
3
3
  % Each expansion collects unvisited neighbors with findall/3, appends them to
4
- % the frontier, and uses sort_unique/2 so the cheapest frontier entry is processed next.
4
+ % the frontier, and uses sort/2 so the cheapest frontier entry is processed next.
5
5
 
6
6
  %% goal: shortestPath(X0, X1)
7
7
 
@@ -34,7 +34,7 @@ dijkstra_queue([[Cost, Node | Path] | Queue], Goal, Visited, Resultpath, Resultc
34
34
  (edge(Node, Neighbor, Weight), \+ member(Neighbor, Visited), (Newcost is Cost + Weight)),
35
35
  Neighbors),
36
36
  append(Queue, Neighbors, Newqueue),
37
- sort_unique(Newqueue, Sortedqueue),
37
+ sort(Newqueue, Sortedqueue),
38
38
  dijkstra_queue(Sortedqueue, Goal, [Node | Visited], Resultpath, Resultcost).
39
39
 
40
40
  shortestPath(dijkstra_findall_sort, Path) :-
@@ -89,7 +89,7 @@ eval_matrix(Matrix, FreqSorted) :-
89
89
  setof(E, member(E, Entries), Set),
90
90
  maplist(count_var(Entries), Set, Multiplicities),
91
91
  zip(Multiplicities, Set, Frequencies),
92
- sort_unique(Frequencies, FreqSorted),
92
+ sort(Frequencies, FreqSorted),
93
93
  maplist(snd, FreqSorted, VarsSorted),
94
94
  length(VarsSorted, NVars),
95
95
  from_to(1, NVars, VarsSorted).
@@ -1,4 +1,4 @@
1
- % Eyelet-inspired Eulerian path example using findall/3 and sort_unique/2.
1
+ % Eyelet-inspired Eulerian path example using findall/3 and sort/2.
2
2
  %
3
3
  % The graph is undirected; edges have identifiers so the trail consumes each
4
4
  % physical edge exactly once even when vertices are revisited. The remaining
@@ -49,15 +49,15 @@ odd_degree(V) :-
49
49
 
50
50
  odd_vertices(Odds) :-
51
51
  findall(V, odd_degree(V), Raw),
52
- sort_unique(Raw, Odds).
52
+ sort(Raw, Odds).
53
53
 
54
54
  all_edges(Edges) :-
55
55
  findall(E, edge(E, _a, _b), Raw),
56
- sort_unique(Raw, Edges).
56
+ sort(Raw, Edges).
57
57
 
58
58
  vertices(Vertices) :-
59
59
  findall(V, vertex(V), Raw),
60
- sort_unique(Raw, Vertices).
60
+ sort(Raw, Vertices).
61
61
 
62
62
  eulerian_start(Start) :-
63
63
  odd_vertices([Start, _end]).
@@ -102,13 +102,13 @@ border_count(36).
102
102
 
103
103
  all_countries_coloured(map_eu) :-
104
104
  findall(Country, valid_assignment(Country), Countries),
105
- sort_unique(Countries, Uniquecountries),
105
+ sort(Countries, Uniquecountries),
106
106
  length(Uniquecountries, Count),
107
107
  country_count(Count).
108
108
 
109
109
  all_borders_checked(map_eu) :-
110
110
  findall([A, B], border_colours_differ(A, B), Borders),
111
- sort_unique(Borders, Uniqueborders),
111
+ sort(Borders, Uniqueborders),
112
112
  length(Uniqueborders, Count),
113
113
  border_count(Count).
114
114
 
@@ -15,7 +15,7 @@ healthcare_risk_report(Ranked) :-
15
15
  ),
16
16
  Unsorted
17
17
  ),
18
- sort_unique(Unsorted, Sorted),
18
+ sort(Unsorted, Sorted),
19
19
  ranked_values(Sorted, 1, Ranked).
20
20
 
21
21
  risk_report(Risk, Score, Level, Clause, Mitigation) :-
@@ -15,7 +15,7 @@ consumer_risk_report(Ranked) :-
15
15
  ),
16
16
  Unsorted
17
17
  ),
18
- sort_unique(Unsorted, Sorted),
18
+ sort(Unsorted, Sorted),
19
19
  ranked_values(Sorted, 1, Ranked).
20
20
 
21
21
  risk_report(Risk, Score, Level, Clause, Mitigation) :-
@@ -25,7 +25,7 @@ ranked_claims(Claims) :-
25
25
  ),
26
26
  Unsorted
27
27
  ),
28
- sort_unique(Unsorted, Sorted),
28
+ sort(Unsorted, Sorted),
29
29
  pair_values(Sorted, Claims).
30
30
 
31
31
  annotated_status_claim(Status, Source, Score) :-
@@ -56,7 +56,7 @@ healthcare_risk_report(Ranked) :-
56
56
  ),
57
57
  Unsorted
58
58
  ),
59
- sort_unique(Unsorted, Sorted),
59
+ sort(Unsorted, Sorted),
60
60
  ranked_values(Sorted, 1, Ranked).
61
61
 
62
62
  risk_report(Risk, Score, Level, Clause, Mitigation) :-
@@ -68,7 +68,7 @@ consumer_risk_report(Ranked) :-
68
68
  ),
69
69
  Unsorted
70
70
  ),
71
- sort_unique(Unsorted, Sorted),
71
+ sort(Unsorted, Sorted),
72
72
  ranked_values(Sorted, 1, Ranked).
73
73
 
74
74
  risk_report(Risk, Score, Level, Clause, Mitigation) :-
@@ -1 +1,6 @@
1
+ complex_power(sqrt_minus_one, [-1, 0], [0.5, 0], [6.123233995736766e-17, 1.0]).
2
+ complex_power(e_to_i_pi, [2.718281828459045, 0], [0, 3.141592653589793], [-1.0, 1.2246467991473532e-16]).
1
3
  complex_power(i_to_i, [0, 1], [0, 1], [0.20787957635076193, 0.0]).
4
+ complex_power(e_to_minus_pi_over_two, [2.718281828459045, 0], [-1.57079632679, 0], [0.20787957635177984, 0.0]).
5
+ complex_function(asin, two, [2, 0], [1.5707963267948966, 1.3169578969248166]).
6
+ complex_function(acos, two, [2, 0], [0.0, -1.3169578969248166]).
@@ -1 +1 @@
1
- enigma1225(8, [[2, 1, 4, 3, 6, 5, 8, 7], [[16, 16, 1, 2, 3, 4, 5, 6], [16, 16, 2, 1, 4, 3, 6, 5], [2, 1, 7, 7, 8, 9, 10, 11], [1, 2, 7, 7, 9, 8, 11, 10], [4, 3, 9, 8, 12, 12, 13, 14], [3, 4, 8, 9, 12, 12, 14, 13], [6, 5, 11, 10, 14, 13, 15, 15], [5, 6, 10, 11, 13, 14, 15, 15]], 544]).
1
+ enigma1225(8, [[2, 1, 4, 3, 6, 5, 8, 7], [[1, 1, 2, 3, 4, 5, 6, 7], [1, 1, 3, 2, 5, 4, 7, 6], [3, 2, 8, 8, 9, 10, 11, 12], [2, 3, 8, 8, 10, 9, 12, 11], [5, 4, 10, 9, 13, 13, 14, 15], [4, 5, 9, 10, 13, 13, 15, 14], [7, 6, 12, 11, 15, 14, 16, 16], [6, 7, 11, 12, 14, 15, 16, 16]], 544]).
@@ -1,4 +1,4 @@
1
- report(div_mod, quotient_remainder(-2, 2)).
1
+ report(div_mod, quotient_remainder(-3, 2)).
2
2
  report(quotient_rem, quotient_remainder(-2, -1)).
3
3
  report(bit_mask, 4).
4
4
  report(bit_union, 11).
@@ -16,8 +16,8 @@ why(
16
16
  by(builtin(findall, 3))
17
17
  ),
18
18
  proof(
19
- goal(sort_unique([], [])),
20
- by(library(sort_unique, 2))
19
+ goal(sort([], [])),
20
+ by(builtin(sort, 2))
21
21
  )
22
22
  ])
23
23
  )
@@ -43,8 +43,8 @@ why(
43
43
  by(builtin(findall, 3))
44
44
  ),
45
45
  proof(
46
- goal(sort_unique([], [])),
47
- by(library(sort_unique, 2))
46
+ goal(sort([], [])),
47
+ by(builtin(sort, 2))
48
48
  )
49
49
  ])
50
50
  ),
@@ -12,7 +12,7 @@ why(
12
12
  uses([
13
13
  proof(
14
14
  goal(task(check_power, urgent)),
15
- by(fact("<input>", clause(303)))
15
+ by(fact("<input>", clause(278)))
16
16
  )
17
17
  ])
18
18
  )
@@ -75,7 +75,7 @@ check(4, 'Canonical Tie-Breaking (Lexicographical First)', Status) :-
75
75
  find_combination(Size, Primes, C),
76
76
  covers_all(C, Minterms)
77
77
  ), Alternatives),
78
- sort_unique(Alternatives, [Best|_]),
78
+ sort(Alternatives, [Best|_]),
79
79
  equality_status(Cover, Best, Status).
80
80
 
81
81
  check(5, 'Consistency (Solution is subset of Primes)', Status) :-
@@ -166,9 +166,9 @@ compute_primes(Primes) :-
166
166
  findall(B, (minterm(M), int_to_bits(M, B)), Mts),
167
167
  findall(B, (dont_care(D), int_to_bits(D, B)), Dcs),
168
168
  append(Mts, Dcs, All),
169
- sort_unique(All, Init),
169
+ sort(All, Init),
170
170
  generate_loop(Init, [], RawPrimes),
171
- sort_unique(RawPrimes, Primes).
171
+ sort(RawPrimes, Primes).
172
172
 
173
173
  generate_loop(Group, Acc, Final) :-
174
174
  findall(Nx-[P1,P2], (
@@ -176,8 +176,8 @@ generate_loop(Group, Acc, Final) :-
176
176
  ), Pairs),
177
177
  findall(N, member(N-_, Pairs), NextRaw),
178
178
  findall(P, (member(_-Pars, Pairs), member(P, Pars)), UsedRaw),
179
- sort_unique(NextRaw, NextGen),
180
- sort_unique(UsedRaw, Used),
179
+ sort(NextRaw, NextGen),
180
+ sort(UsedRaw, Used),
181
181
  findall(P, (member(P, Group), \+ member(P, Used)), New),
182
182
  append(Acc, New, AccUpd),
183
183
  (NextGen = [] -> Final = AccUpd ; generate_loop(NextGen, AccUpd, Final)).
@@ -187,13 +187,13 @@ solve_minimal_cover(Primes, MinimalCover) :-
187
187
  % 1. Essentials
188
188
  findall(M-Ps, (member(M, Minterms), findall(P, (member(P, Primes), covers_int(P, M)), Ps)), Chart),
189
189
  findall(P, member(_-[P], Chart), EssRaw),
190
- sort_unique(EssRaw, Essentials),
190
+ sort(EssRaw, Essentials),
191
191
  % 2. Remaining
192
192
  remaining_minterms(Minterms, Essentials, RemMts),
193
193
  subtract_list(Primes, Essentials, NonEss),
194
194
  (RemMts = [] -> BestRest = [] ; find_smallest_subset(NonEss, RemMts, BestRest)),
195
195
  append(Essentials, BestRest, Total),
196
- sort_unique(Total, MinimalCover).
196
+ sort(Total, MinimalCover).
197
197
 
198
198
  remaining_minterms([], _, []).
199
199
  remaining_minterms([M|Ms], Essentials, Rest) :-
@@ -41,7 +41,7 @@ ranked_claims(Claims) :-
41
41
  ),
42
42
  Unsorted
43
43
  ),
44
- sort_unique(Unsorted, Sorted),
44
+ sort(Unsorted, Sorted),
45
45
  pair_values(Sorted, Claims).
46
46
 
47
47
  annotated_status_claim(Status, Source, Score) :-
@@ -46,7 +46,7 @@ best_choice(Grid, Row, Column, Candidates) :-
46
46
  ),
47
47
  Choices
48
48
  ),
49
- sort_unique(Choices, [choice(_Count, Row, Column, Candidates)|_]).
49
+ sort(Choices, [choice(_Count, Row, Column, Candidates)|_]).
50
50
 
51
51
  empty_cell(Grid, Row, Column) :-
52
52
  between(0, 8, Row),
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.5.18",
6
+ "version": "0.6.0",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/playground.html CHANGED
@@ -654,7 +654,6 @@
654
654
  "aggregate_max",
655
655
  "aggregate_min",
656
656
  "append",
657
- "apply",
658
657
  "arg",
659
658
  "asin",
660
659
  "atan2",
@@ -707,7 +706,6 @@
707
706
  "sin",
708
707
  "slice",
709
708
  "smallest_divisor_from",
710
- "sort_unique",
711
709
  "split",
712
710
  "sqrt",
713
711
  "string_concat",
@@ -8,12 +8,7 @@ export const eyePrologNativeLibraryIndicators = Object.freeze([]);
8
8
  export const eyePrologPortableLibraryIndicators = Object.freeze([
9
9
  'uuid/3',
10
10
  'difference/3',
11
- 'apply/3',
12
11
  'maplist/3',
13
- 'tan/2',
14
- 'asin/2',
15
- 'acos/2',
16
- 'atan2/3',
17
12
  'lt/2',
18
13
  'gt/2',
19
14
  'le/2',
@@ -51,7 +46,6 @@ export const eyePrologPortableLibraryIndicators = Object.freeze([
51
46
  'min_list/2',
52
47
  'max_list/2',
53
48
  'list_to_set/2',
54
- 'sort_unique/2',
55
49
  'countall/2',
56
50
  'sumall/3',
57
51
  'aggregate_min/5',
@@ -70,7 +64,7 @@ const libraryFiles = [
70
64
  ];
71
65
  const libraryCacheKey = isNode
72
66
  ? null
73
- : (new URL(import.meta.url).searchParams.get('playground') ?? '20260807b');
67
+ : (new URL(import.meta.url).searchParams.get('playground') ?? '20260808a');
74
68
  const librarySources = await Promise.all(libraryFiles.map(async (filename) => ({
75
69
  filename,
76
70
  source: await loadLibrarySource(libraryFileUrl(filename)),
@@ -7,7 +7,7 @@
7
7
 
8
8
  maplist(_, [], []).
9
9
  maplist(Closure, [A|As], [B|Bs]) :-
10
- apply(Closure, A, B),
10
+ call(Closure, A, B),
11
11
  maplist(Closure, As, Bs).
12
12
 
13
13
  append([], Ys, Ys).
@@ -35,7 +35,7 @@ eyeprolog__atomic_chars(Value, Chars) :-
35
35
  eyeprolog__char_list(Value),
36
36
  Value = Chars.
37
37
 
38
- % ---------- core/meta ----------
38
+ % ---------- core helpers ----------
39
39
 
40
40
  eyeprolog__append([], Ys, Ys).
41
41
  eyeprolog__append([X|Xs], Ys, [X|Zs]) :- eyeprolog__append(Xs, Ys, Zs).
@@ -43,29 +43,8 @@ eyeprolog__append([X|Xs], Ys, [X|Zs]) :- eyeprolog__append(Xs, Ys, Zs).
43
43
  eyeprolog__member(X, [X|_]).
44
44
  eyeprolog__member(X, [_|Xs]) :- eyeprolog__member(X, Xs).
45
45
 
46
- apply(Closure, A, B) :-
47
- Closure =.. Parts,
48
- eyeprolog__append(Parts, [A, B], CallParts),
49
- Goal =.. CallParts,
50
- call(Goal).
51
-
52
46
  % ---------- arithmetic helpers ----------
53
47
 
54
- tan(X, Y) :- Y is sin(X) / cos(X).
55
-
56
- asin(1, Y) :- Y is pi / 2.
57
- asin(-1, Y) :- Y is -pi / 2.
58
- asin(X, Y) :- X > -1, X < 1, Y is atan(X / sqrt(1 - X * X)).
59
-
60
- acos(X, Y) :- asin(X, A), Y is pi / 2 - A.
61
-
62
- atan2(Y, X, A) :- X > 0, A is atan(Y / X).
63
- atan2(Y, X, A) :- X < 0, Y >= 0, A is atan(Y / X) + pi.
64
- atan2(Y, X, A) :- X < 0, Y < 0, A is atan(Y / X) - pi.
65
- atan2(Y, 0, A) :- Y > 0, A is pi / 2.
66
- atan2(Y, 0, A) :- Y < 0, A is -pi / 2.
67
- atan2(0, 0, 0).
68
-
69
48
  eyeprolog__atom_number(Text, Number) :-
70
49
  eyeprolog__text_chars(Text, Chars),
71
50
  catch(number_chars(Number, Chars), _, fail).
@@ -724,17 +703,6 @@ eyeprolog__list_to_set([X|Xs], Seen, [X|Set]) :-
724
703
  eyeprolog__identical_member(X, [Y|_]) :- X == Y.
725
704
  eyeprolog__identical_member(X, [_|Ys]) :- eyeprolog__identical_member(X, Ys).
726
705
 
727
- sort_unique(List, Sorted) :- eyeprolog__sort(List, [], Sorted).
728
- eyeprolog__sort([], Sorted, Sorted).
729
- eyeprolog__sort([X|Xs], Acc, Sorted) :-
730
- eyeprolog__insert_sorted(X, Acc, Next),
731
- eyeprolog__sort(Xs, Next, Sorted).
732
-
733
- eyeprolog__insert_sorted(X, [], [X]).
734
- eyeprolog__insert_sorted(X, [Y|Ys], [Y|Ys]) :- X == Y.
735
- eyeprolog__insert_sorted(X, [Y|Ys], [X,Y|Ys]) :- X @< Y.
736
- eyeprolog__insert_sorted(X, [Y|Ys], [Y|Zs]) :- X @> Y, eyeprolog__insert_sorted(X, Ys, Zs).
737
-
738
706
  % ---------- aggregation ----------
739
707
 
740
708
  sumall(Expression, Goal, Sum) :-
@@ -742,29 +710,14 @@ sumall(Expression, Goal, Sum) :-
742
710
  eyeprolog__sum_list(Values, 0, Sum).
743
711
 
744
712
  aggregate_min(Key, Value, Goal, BestKey, BestValue) :-
745
- findall(pair(Key, Value), Goal, Pairs),
746
- eyeprolog__aggregate_min(Pairs, BestKey, BestValue).
747
-
748
- eyeprolog__aggregate_min([pair(K,V)|Pairs], BestKey, BestValue) :-
749
- eyeprolog__aggregate_min_rest(Pairs, K, V, BestKey, BestValue).
750
- eyeprolog__aggregate_min_rest([], K, V, K, V).
751
- eyeprolog__aggregate_min_rest([pair(K,V)|Pairs], CK, _, BK, BV) :-
752
- K @< CK,
753
- eyeprolog__aggregate_min_rest(Pairs, K, V, BK, BV).
754
- eyeprolog__aggregate_min_rest([pair(K,_)|Pairs], CK, CV, BK, BV) :-
755
- K @>= CK,
756
- eyeprolog__aggregate_min_rest(Pairs, CK, CV, BK, BV).
713
+ findall(Key-Value, Goal, Pairs),
714
+ keysort(Pairs, [BestKey-BestValue|_]).
757
715
 
758
716
  aggregate_max(Key, Value, Goal, BestKey, BestValue) :-
759
- findall(pair(Key, Value), Goal, Pairs),
760
- eyeprolog__aggregate_max(Pairs, BestKey, BestValue).
761
-
762
- eyeprolog__aggregate_max([pair(K,V)|Pairs], BestKey, BestValue) :-
763
- eyeprolog__aggregate_max_rest(Pairs, K, V, BestKey, BestValue).
764
- eyeprolog__aggregate_max_rest([], K, V, K, V).
765
- eyeprolog__aggregate_max_rest([pair(K,V)|Pairs], CK, _, BK, BV) :-
766
- K @> CK,
767
- eyeprolog__aggregate_max_rest(Pairs, K, V, BK, BV).
768
- eyeprolog__aggregate_max_rest([pair(K,_)|Pairs], CK, CV, BK, BV) :-
769
- K @=< CK,
770
- eyeprolog__aggregate_max_rest(Pairs, CK, CV, BK, BV).
717
+ findall(Key-Value, Goal, Pairs),
718
+ eyeprolog__reverse(Pairs, [], ReversePairs),
719
+ keysort(ReversePairs, Sorted),
720
+ eyeprolog__last_pair(Sorted, BestKey-BestValue).
721
+
722
+ eyeprolog__last_pair([Pair], Pair).
723
+ eyeprolog__last_pair([_|Pairs], Pair) :- eyeprolog__last_pair(Pairs, Pair).