eyeprolog 1.3.3 → 1.3.4
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 +12 -4
- package/examples/book/chapter-08/01-findall.pl +1 -0
- package/examples/book/chapter-39/04-cost.pl +1 -0
- package/examples/chart-parser.pl +1 -0
- package/examples/dog.pl +1 -0
- package/examples/donald-gerald-robert.pl +1 -0
- package/examples/equality-saturation.pl +1 -0
- package/examples/job-shop-scheduling.pl +1 -0
- package/examples/knapsack-optimization.pl +1 -0
- package/examples/knuth-bendix-completion.pl +1 -0
- package/examples/matrix-chain-order.pl +1 -0
- package/examples/missionaries-cannibals.pl +1 -0
- package/examples/prime-range.pl +1 -0
- package/examples/register-allocation.pl +1 -0
- package/examples/send-more-money.pl +1 -0
- package/examples/stable-marriage.pl +1 -0
- package/examples/totient-summatory.pl +1 -0
- package/examples/weighted-interval-scheduling.pl +1 -0
- package/package.json +1 -1
- package/src/iso.js +41 -5
- package/src/lib/iso_ext.pl +4 -0
- package/src/lib/lists.pl +0 -3
- package/src/solver.js +49 -5
- package/src/standard-library.js +7 -7
- package/test/run-conformance.mjs +1 -0
- package/test/run-regression.mjs +42 -2
- package/the-art-of-eyeprolog.md +25 -13
package/README.md
CHANGED
|
@@ -143,12 +143,20 @@ Trealla/Scryer organization for predicates such as `member/2`, `memberchk/2`,
|
|
|
143
143
|
`length(Xs, N)` enumerates lists of increasing length together with `N = 0, 1,
|
|
144
144
|
2, ...`.
|
|
145
145
|
|
|
146
|
+
`library(iso_ext)` is also accepted as a common interop module name.
|
|
147
|
+
EyeProlog exports `call_nth/2` there, so Scryer-style source can explicitly use
|
|
148
|
+
`:- use_module(library(iso_ext)).`; unqualified source may still autoload it.
|
|
149
|
+
The aligned `library(lists)` and `library(iso_ext)` exports are kept disjoint so
|
|
150
|
+
they can be imported together without an accidental import conflict. EyeProlog's
|
|
151
|
+
legacy `library(prologue)` remains a compatibility umbrella and should be
|
|
152
|
+
selectively imported when mixed with the aligned modules.
|
|
153
|
+
|
|
146
154
|
Outside `--iso-strict`, an otherwise undefined unqualified call may autoload a
|
|
147
155
|
predicate only when the interop profile has one canonical EyeProlog provider.
|
|
148
|
-
For example, `member/2` autoloads from `library(lists)`,
|
|
149
|
-
`
|
|
150
|
-
|
|
151
|
-
|
|
156
|
+
For example, `member/2` autoloads from `library(lists)`, `call_nth/2` from
|
|
157
|
+
`library(iso_ext)`, and `between/3` from EyeProlog's internal
|
|
158
|
+
`library(prologue)` implementation. Use `--no-autoload` to disable this
|
|
159
|
+
convenience. Strict ISO mode never autoloads library predicates.
|
|
152
160
|
|
|
153
161
|
Use `-w` / `--warnings` to diagnose dependencies outside the interop profile,
|
|
154
162
|
or `--portable` to make such diagnostics fail the run. This catches both
|
package/examples/chart-parser.pl
CHANGED
package/examples/dog.pl
CHANGED
package/examples/prime-range.pl
CHANGED
package/package.json
CHANGED
package/src/iso.js
CHANGED
|
@@ -2032,11 +2032,28 @@ function prologErrorBall(error) {
|
|
|
2032
2032
|
return freshCopy(term, new Env());
|
|
2033
2033
|
}
|
|
2034
2034
|
function* catchBuiltin({ solver, goal, env }) {
|
|
2035
|
-
|
|
2035
|
+
let child = null;
|
|
2036
2036
|
try {
|
|
2037
2037
|
// Corrigendum 2 removed catch/3's own callability errors so that errors
|
|
2038
2038
|
// raised while converting/executing the protected goal are catchable.
|
|
2039
|
-
|
|
2039
|
+
const invoked = callable(goal.args[0], env);
|
|
2040
|
+
const direct = solver.registry.get(invoked.name, invoked.arity);
|
|
2041
|
+
if (direct?.deterministic && (direct.shouldUse == null || direct.shouldUse({ solver, goal: invoked, env }))) {
|
|
2042
|
+
// A deterministic builtin has no choice points whose lifetime must be
|
|
2043
|
+
// isolated in a child solver. Running it directly avoids constructing a
|
|
2044
|
+
// complete Solver for hot caught failures such as number_chars/2 syntax
|
|
2045
|
+
// probes, while the cloned environment keeps catch/3's rollback boundary.
|
|
2046
|
+
const iterator = direct.handler({ solver, goal: invoked, env: env.clone() });
|
|
2047
|
+
const result = iterator.next();
|
|
2048
|
+
if (result.done) solver.stats.deterministic_builtin_failures++;
|
|
2049
|
+
else {
|
|
2050
|
+
solver.stats.deterministic_builtin_successes++;
|
|
2051
|
+
yield result.value;
|
|
2052
|
+
}
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
child = solver.cloneForInnerGoal();
|
|
2056
|
+
yield* child.solve([invoked], env.clone(), 0);
|
|
2040
2057
|
} catch (error) {
|
|
2041
2058
|
const ball = error instanceof ThrownTerm
|
|
2042
2059
|
? error.term
|
|
@@ -2046,9 +2063,15 @@ function* catchBuiltin({ solver, goal, env }) {
|
|
|
2046
2063
|
if (ball == null) throw error;
|
|
2047
2064
|
const recovered = env.clone();
|
|
2048
2065
|
if (!unify(goal.args[1], ball, recovered)) throw error;
|
|
2049
|
-
|
|
2066
|
+
const recovery = callable(goal.args[2], recovered);
|
|
2067
|
+
if (recovery.type === ATOM && (recovery.name === 'false' || recovery.name === 'fail')) return;
|
|
2068
|
+
if (recovery.type === ATOM && recovery.name === 'true') {
|
|
2069
|
+
yield recovered;
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
yield* solver.solve([recovery], recovered, 0);
|
|
2050
2073
|
} finally {
|
|
2051
|
-
solver.absorbStatsFrom(child);
|
|
2074
|
+
if (child != null) solver.absorbStatsFrom(child);
|
|
2052
2075
|
}
|
|
2053
2076
|
}
|
|
2054
2077
|
function* throwBuiltin({ goal, env }) {
|
|
@@ -2071,7 +2094,20 @@ function* repeatBuiltin({ env }) {
|
|
|
2071
2094
|
while (true) yield env;
|
|
2072
2095
|
}
|
|
2073
2096
|
function* negationBuiltin({ solver, goal, env }) {
|
|
2074
|
-
|
|
2097
|
+
const invoked = callable(goal.args[0], env);
|
|
2098
|
+
const direct = solver.registry.get(invoked.name, invoked.arity);
|
|
2099
|
+
if (direct?.deterministic && (direct.shouldUse == null || direct.shouldUse({ solver, goal: invoked, env }))) {
|
|
2100
|
+
const iterator = direct.handler({ solver, goal: invoked, env: env.clone() });
|
|
2101
|
+
const result = iterator.next();
|
|
2102
|
+
if (result.done) {
|
|
2103
|
+
solver.stats.deterministic_builtin_failures++;
|
|
2104
|
+
yield env;
|
|
2105
|
+
} else {
|
|
2106
|
+
solver.stats.deterministic_builtin_successes++;
|
|
2107
|
+
}
|
|
2108
|
+
return;
|
|
2109
|
+
}
|
|
2110
|
+
for (const _ of solver.cloneForInnerGoal(1).solve([invoked], env.clone(), 0)) return;
|
|
2075
2111
|
yield env;
|
|
2076
2112
|
}
|
|
2077
2113
|
function* solveControlBranch(solver, goal, env) {
|
package/src/lib/iso_ext.pl
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** Widely implemented extensions to the ISO Prolog core. */
|
|
2
2
|
|
|
3
3
|
:- module(iso_ext, [
|
|
4
|
+
call_nth/2,
|
|
4
5
|
countall/2,
|
|
5
6
|
forall/2,
|
|
6
7
|
succ/2,
|
|
@@ -9,6 +10,7 @@
|
|
|
9
10
|
variant/2
|
|
10
11
|
]).
|
|
11
12
|
|
|
13
|
+
:- meta_predicate(call_nth(0, '?')).
|
|
12
14
|
:- meta_predicate(countall(0, '?')).
|
|
13
15
|
:- meta_predicate(forall(0, 0)).
|
|
14
16
|
:- meta_predicate(findall('?', 0, '?', '?')).
|
|
@@ -17,6 +19,8 @@
|
|
|
17
19
|
% Trealla. These definitions use only EyeProlog's ISO profile; extensions that
|
|
18
20
|
% require runtime cleanup, choice-point, alarm, or timeout hooks are omitted.
|
|
19
21
|
|
|
22
|
+
call_nth(Goal, Nth) :- eyeprolog__call_nth(Goal, Nth).
|
|
23
|
+
|
|
20
24
|
countall(Goal, Count) :- eyeprolog__countall(Goal, Count).
|
|
21
25
|
|
|
22
26
|
forall(Condition, Action) :-
|
package/src/lib/lists.pl
CHANGED
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
min_list/2,
|
|
29
29
|
max_list/2,
|
|
30
30
|
list_to_set/2,
|
|
31
|
-
countall/2,
|
|
32
31
|
set_nth0/4,
|
|
33
32
|
take/3,
|
|
34
33
|
drop/3,
|
|
@@ -45,7 +44,6 @@
|
|
|
45
44
|
:- meta_predicate(foldl(3, '?', '?', '?')).
|
|
46
45
|
:- meta_predicate(foldl(4, '?', '?', '?', '?')).
|
|
47
46
|
:- meta_predicate(foldl(5, '?', '?', '?', '?', '?')).
|
|
48
|
-
:- meta_predicate(countall(0, '?')).
|
|
49
47
|
|
|
50
48
|
% Common pure-Prolog library predicates for EyeProlog.
|
|
51
49
|
%
|
|
@@ -168,7 +166,6 @@ max_list([X|Xs], Max) :- lists__max_list(Xs, X, Max).
|
|
|
168
166
|
|
|
169
167
|
list_to_set(List, Set) :- lists__list_to_set(List, [], Set).
|
|
170
168
|
|
|
171
|
-
countall(Goal, Count) :- eyeprolog__countall(Goal, Count).
|
|
172
169
|
|
|
173
170
|
set_nth0(0, [_|Xs], X, [X|Xs]).
|
|
174
171
|
set_nth0(N, [Y|Ys], X, [Y|Zs]) :-
|
package/src/solver.js
CHANGED
|
@@ -374,7 +374,24 @@ export class Solver {
|
|
|
374
374
|
}
|
|
375
375
|
qualifyMetaArguments(goal, group);
|
|
376
376
|
|
|
377
|
-
const
|
|
377
|
+
const memberIterator = bundledMemberIterator(this, group, goal, env);
|
|
378
|
+
if (memberIterator != null) {
|
|
379
|
+
const firstResult = memberIterator.next();
|
|
380
|
+
if (firstResult.done) break;
|
|
381
|
+
stack.push({
|
|
382
|
+
kind: 'resumeBuiltin',
|
|
383
|
+
iterator: memberIterator,
|
|
384
|
+
goals: rest,
|
|
385
|
+
depth: depth + 1,
|
|
386
|
+
active,
|
|
387
|
+
});
|
|
388
|
+
goals = rest;
|
|
389
|
+
env = firstResult.value;
|
|
390
|
+
depth++;
|
|
391
|
+
continue;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
const lengthIterator = bundledLengthIterator(this, group, goal, env);
|
|
378
395
|
if (lengthIterator != null) {
|
|
379
396
|
const firstResult = lengthIterator.next();
|
|
380
397
|
if (firstResult.done) break;
|
|
@@ -757,9 +774,36 @@ function groupNeedsActiveFrame(group) {
|
|
|
757
774
|
return group.cutReachable !== false || (group.recursive && !group.linearNumeric);
|
|
758
775
|
}
|
|
759
776
|
|
|
760
|
-
function
|
|
777
|
+
function bundledMemberIterator(solver, group, goal, env) {
|
|
778
|
+
if (solver.registry.eyePrologLibrary !== true ||
|
|
779
|
+
!['lists', 'prologue'].includes(group.module) || group.name !== 'member' || group.arity !== 2 ||
|
|
780
|
+
group.bundledLibrary !== true || group.clauses.length !== 2) {
|
|
781
|
+
return null;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
// Keep the relational/open-list cases in ordinary Prolog. When the second
|
|
785
|
+
// argument is already a finite list, however, the canonical two-clause
|
|
786
|
+
// member/2 definition is exactly a left-to-right scan and can avoid clause
|
|
787
|
+
// freshening and recursive solver frames for every element.
|
|
788
|
+
let cursor = deref(goal.args[1], env);
|
|
789
|
+
while (isCons(cursor)) cursor = deref(cursor.args[1], env);
|
|
790
|
+
if (!isEmptyList(cursor)) return null;
|
|
791
|
+
return bundledMemberSolutions(solver, goal, env);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function* bundledMemberSolutions(solver, goal, env) {
|
|
795
|
+
let cursor = deref(goal.args[1], env);
|
|
796
|
+
while (isCons(cursor)) {
|
|
797
|
+
const next = env.clone();
|
|
798
|
+
solver.stats.unify_calls++;
|
|
799
|
+
if (unify(goal.args[0], cursor.args[0], next)) yield next;
|
|
800
|
+
cursor = deref(cursor.args[1], env);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function bundledLengthIterator(solver, group, goal, env) {
|
|
761
805
|
if (solver.registry.eyePrologLibrary !== true ||
|
|
762
|
-
|
|
806
|
+
!['lists', 'prologue'].includes(group.module) || group.name !== 'length' || group.arity !== 2 ||
|
|
763
807
|
group.bundledLibrary !== true || group.clauses.length !== 2) {
|
|
764
808
|
return null;
|
|
765
809
|
}
|
|
@@ -778,10 +822,10 @@ function prologueLengthIterator(solver, group, goal, env) {
|
|
|
778
822
|
if (env._delays?.has(cursor.name)) return null;
|
|
779
823
|
if (length.type === VAR && cursor.name === length.name) return null;
|
|
780
824
|
}
|
|
781
|
-
return
|
|
825
|
+
return bundledLengthSolutions(solver, goal, env);
|
|
782
826
|
}
|
|
783
827
|
|
|
784
|
-
function*
|
|
828
|
+
function* bundledLengthSolutions(solver, goal, env) {
|
|
785
829
|
const requestedLength = deref(goal.args[1], env);
|
|
786
830
|
if (requestedLength.type !== VAR) {
|
|
787
831
|
if (requestedLength.type !== NUMBER || !isDecimalInteger(requestedLength.name)) {
|
package/src/standard-library.js
CHANGED
|
@@ -109,10 +109,10 @@ export const eyePrologInteropAutoload = Object.freeze({
|
|
|
109
109
|
'foldl/6': 'lists',
|
|
110
110
|
'sum_list/2': 'lists',
|
|
111
111
|
'list_to_set/2': 'lists',
|
|
112
|
-
// call_nth/2 is available in both Trealla and Scryer
|
|
113
|
-
// library(iso_ext)
|
|
114
|
-
//
|
|
115
|
-
'call_nth/2': '
|
|
112
|
+
// call_nth/2 is available in both Trealla and Scryer. EyeProlog exposes
|
|
113
|
+
// it from library(iso_ext), matching the explicit Scryer import while still
|
|
114
|
+
// allowing Trealla-style unqualified source to use the same autoload entry.
|
|
115
|
+
'call_nth/2': 'iso_ext',
|
|
116
116
|
// Trealla and Scryer expose between/3 without an EyeProlog-style
|
|
117
117
|
// library(prologue) dependency. EyeProlog keeps its implementation in the
|
|
118
118
|
// Prologue module but autoloads it so portable source need not name that
|
|
@@ -125,9 +125,9 @@ export const eyePrologInteropLibraryIndicators = Object.freeze(
|
|
|
125
125
|
);
|
|
126
126
|
|
|
127
127
|
// Libraries whose *name* is part of the current interop profile. A program
|
|
128
|
-
// may freely use_module
|
|
129
|
-
// outside eyePrologInteropLibraryIndicators are still diagnosed when used.
|
|
130
|
-
export const eyePrologInteropLibraryModules = Object.freeze(['lists']);
|
|
128
|
+
// may freely use_module/1 with these common module names; predicates in those
|
|
129
|
+
// modules outside eyePrologInteropLibraryIndicators are still diagnosed when used.
|
|
130
|
+
export const eyePrologInteropLibraryModules = Object.freeze(['lists', 'iso_ext']);
|
|
131
131
|
|
|
132
132
|
function runtimeStatistics(solver) {
|
|
133
133
|
return { ...solver.stats, ...memoryStatistics() };
|
package/test/run-conformance.mjs
CHANGED
|
@@ -18,6 +18,7 @@ function withStandardModules(text) {
|
|
|
18
18
|
return `:- use_module(library(aggregate)).
|
|
19
19
|
:- use_module(library(comparison)).
|
|
20
20
|
:- use_module(library(dates)).
|
|
21
|
+
:- use_module(library(iso_ext)).
|
|
21
22
|
:- use_module(library(lists)).
|
|
22
23
|
:- use_module(library(primes)).
|
|
23
24
|
:- use_module(library(prologue), [between/3]).
|
package/test/run-regression.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
createDefaultRegistry,
|
|
21
21
|
getStrictIsoRegistry,
|
|
22
22
|
getEyePrologRegistry,
|
|
23
|
+
standardLibrarySources,
|
|
23
24
|
eyePrologLibraryIndicators,
|
|
24
25
|
eyePrologNativeLibraryIndicators,
|
|
25
26
|
eyePrologPortableLibraryIndicators,
|
|
@@ -67,6 +68,7 @@ function withStandardModules(source) {
|
|
|
67
68
|
return `:- use_module(library(aggregate)).
|
|
68
69
|
:- use_module(library(comparison)).
|
|
69
70
|
:- use_module(library(dates)).
|
|
71
|
+
:- use_module(library(iso_ext)).
|
|
70
72
|
:- use_module(library(lists)).
|
|
71
73
|
:- use_module(library(primes)).
|
|
72
74
|
:- use_module(library(prologue), [between/3]).
|
|
@@ -2214,6 +2216,22 @@ child.stdin.write(\`consult(${consultedAtom}).\\n\`);
|
|
|
2214
2216
|
assertEqual(result.stderr, '', 'stderr');
|
|
2215
2217
|
},
|
|
2216
2218
|
},
|
|
2219
|
+
{
|
|
2220
|
+
name: 'library(lists) and library(iso_ext) co-import without collisions',
|
|
2221
|
+
run: () => {
|
|
2222
|
+
const input = [
|
|
2223
|
+
':- use_module(library(lists)).',
|
|
2224
|
+
':- use_module(library(iso_ext)).',
|
|
2225
|
+
'%% goal: answer(N)',
|
|
2226
|
+
'answer(N) :- call_nth(member(_, [a,b,c]), N), N = 2.',
|
|
2227
|
+
'',
|
|
2228
|
+
].join('\n');
|
|
2229
|
+
const result = runCli(['--portable', '--no-autoload', '-'], { input });
|
|
2230
|
+
assertEqual(result.status, 0, 'exit status');
|
|
2231
|
+
assertEqual(result.stdout, 'answer(2).\n', 'stdout');
|
|
2232
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
2233
|
+
},
|
|
2234
|
+
},
|
|
2217
2235
|
{
|
|
2218
2236
|
name: 'strict ISO mode disables interop autoloading',
|
|
2219
2237
|
run: () => {
|
|
@@ -3618,10 +3636,10 @@ check(A, B, C, D, E, F) :-
|
|
|
3618
3636
|
assertEqual(registeredNativeEyePrologLibraryNames().length, 40, 'public native EyeProlog builtin count');
|
|
3619
3637
|
assertEqual(eyePrologPortableLibraryIndicators.length, 62, 'portable Prolog library count');
|
|
3620
3638
|
assertEqual(eyePrologInteropLibraryIndicators.length, 27, 'cross-implementation interop profile count');
|
|
3621
|
-
assertEqual(eyePrologInteropLibraryModules.join(','), 'lists', 'common explicit library module profile');
|
|
3639
|
+
assertEqual(eyePrologInteropLibraryModules.join(','), 'lists,iso_ext', 'common explicit library module profile');
|
|
3622
3640
|
assertEqual(eyePrologInteropAutoload['member/2'], 'lists', 'member/2 canonical autoload');
|
|
3623
3641
|
assertEqual(eyePrologInteropAutoload['between/3'], 'prologue', 'between/3 canonical internal autoload');
|
|
3624
|
-
assertEqual(eyePrologInteropAutoload['call_nth/2'], '
|
|
3642
|
+
assertEqual(eyePrologInteropAutoload['call_nth/2'], 'iso_ext', 'call_nth/2 canonical interop autoload');
|
|
3625
3643
|
assertEqual(eyePrologInteropAutoload['set_nth0/4'] ?? null, null, 'EyeProlog-only set_nth0/4 is not autoloadable');
|
|
3626
3644
|
assertEqual(eyePrologNativeLibraryIndicators.length, 40, 'native host library count');
|
|
3627
3645
|
assertEqual(eyePrologNativeLibraryIndicators.slice(0, 2).join(','), 'call_nth/2,freeze/2', 'control predicates requiring host support');
|
|
@@ -3671,6 +3689,28 @@ check(A, B, C, D, E, F) :-
|
|
|
3671
3689
|
assertEqual(program.findGroup('random', 3)?.module, 'random', 'random/3 is imported from library(random)');
|
|
3672
3690
|
},
|
|
3673
3691
|
},
|
|
3692
|
+
{
|
|
3693
|
+
name: 'aligned bundled libraries have no overlapping full-module exports',
|
|
3694
|
+
run: () => {
|
|
3695
|
+
const owners = new Map();
|
|
3696
|
+
for (const [moduleName, entry] of standardLibrarySources) {
|
|
3697
|
+
// library(prologue) is the documented legacy compatibility umbrella;
|
|
3698
|
+
// aligned libraries must remain pairwise collision-free so full
|
|
3699
|
+
// use_module/1 imports can be combined safely.
|
|
3700
|
+
if (moduleName === 'prologue') continue;
|
|
3701
|
+
const parsed = Program.parse(entry.source);
|
|
3702
|
+
const definition = parsed.modules.get(moduleName);
|
|
3703
|
+
if (!definition) throw new Error(`missing module declaration for ${moduleName}`);
|
|
3704
|
+
for (const indicator of definition.exports.keys()) {
|
|
3705
|
+
const previous = owners.get(indicator);
|
|
3706
|
+
if (previous != null) throw new Error(`duplicate export ${indicator}: ${previous}, ${moduleName}`);
|
|
3707
|
+
owners.set(indicator, moduleName);
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3710
|
+
assertEqual(owners.get('countall/2'), 'iso_ext', 'countall/2 has one aligned owner');
|
|
3711
|
+
assertEqual(owners.get('call_nth/2'), 'iso_ext', 'call_nth/2 has one aligned owner');
|
|
3712
|
+
},
|
|
3713
|
+
},
|
|
3674
3714
|
{
|
|
3675
3715
|
name: 'portable library executes against the ISO-only registry',
|
|
3676
3716
|
run: () => {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -1155,6 +1155,7 @@ Finite aggregation asks about a solution set:
|
|
|
1155
1155
|
```eyeprolog
|
|
1156
1156
|
:- use_module(library(aggregate)).
|
|
1157
1157
|
:- use_module(library(lists)).
|
|
1158
|
+
:- use_module(library(iso_ext)).
|
|
1158
1159
|
|
|
1159
1160
|
findall(Template, Goal, List).
|
|
1160
1161
|
countall(Goal, Count).
|
|
@@ -6019,8 +6020,8 @@ between solution branches.
|
|
|
6019
6020
|
| `library(clpz)` | `#>/2`, `#</2`, `#>=/2`, `#=</2`, `#=/2`, `#\=/2`, `#\/1`, `#<==>/2`, `#==>/2`, `#<==/2`, `#\//2`, `#\/2`, `#/\/2`, `in/2`, `ins/2`, `all_different/1`, `all_distinct/1`, `nvalue/2`, `sum/3`, `scalar_product/4`, `tuples_in/2`, `labeling/2`, `label/1`, `indomain/1`, `lex_chain/1`, `serialized/2`, `global_cardinality/2`, `global_cardinality/3`, `circuit/1`, `chain/2`, `element/3`, `zcompare/3`, `fd_var/1`, `fd_inf/2`, `fd_sup/2`, `fd_size/2`, `fd_dom/2` |
|
|
6020
6021
|
| `library(comparison)` | `lt/2`, `gt/2`, `le/2`, `ge/2` |
|
|
6021
6022
|
| `library(dates)` | `difference/3` |
|
|
6022
|
-
| `library(iso_ext)` | `countall/2`, `forall/2`, `succ/2`, `cfor/3`, `findall/4`, `variant/2` |
|
|
6023
|
-
| `library(lists)` | `member/2`, `memberchk/2`, `select/3`, `append/2`, `append/3`, `last/2`, `same_length/2`, `nth0/3`, `nth0/4`, `nth1/3`, `nth1/4`, `reverse/2`, `length/2`, `maplist/2`, `maplist/3`, `maplist/4`, `maplist/5`, `maplist/6`, `maplist/7`, `maplist/8`, `foldl/4`, `foldl/5`, `foldl/6`, `sum_list/2`, `min_list/2`, `max_list/2`, `list_to_set/2`, `
|
|
6023
|
+
| `library(iso_ext)` | `call_nth/2`, `countall/2`, `forall/2`, `succ/2`, `cfor/3`, `findall/4`, `variant/2` |
|
|
6024
|
+
| `library(lists)` | `member/2`, `memberchk/2`, `select/3`, `append/2`, `append/3`, `last/2`, `same_length/2`, `nth0/3`, `nth0/4`, `nth1/3`, `nth1/4`, `reverse/2`, `length/2`, `maplist/2`, `maplist/3`, `maplist/4`, `maplist/5`, `maplist/6`, `maplist/7`, `maplist/8`, `foldl/4`, `foldl/5`, `foldl/6`, `sum_list/2`, `min_list/2`, `max_list/2`, `list_to_set/2`, `set_nth0/4`, `take/3`, `drop/3`, `slice/4` |
|
|
6024
6025
|
| `library(primes)` | `smallest_divisor_from/3` |
|
|
6025
6026
|
| `library(prologue)` | `member/2`, `append/3`, `length/2`, `between/3`, `select/3`, `succ/2`, `maplist/2`, `maplist/3`, `maplist/4`, `maplist/5`, `maplist/6`, `maplist/7`, `maplist/8`, `nth0/3`, `nth0/4`, `nth1/3`, `nth1/4`, `call_nth/2`, `freeze/2`, `foldl/4`, `foldl/5`, `foldl/6`, `countall/2` |
|
|
6026
6027
|
| `library(random)` | `random/3` |
|
|
@@ -6046,14 +6047,21 @@ This generator mode is important for portable stress and enumeration programs.
|
|
|
6046
6047
|
EyeProlog-only helpers such as `set_nth0/4`, `take/3`, `drop/3`, and `slice/4`
|
|
6047
6048
|
remain available for compatibility but are outside this profile.
|
|
6048
6049
|
|
|
6050
|
+
`library(iso_ext)` is also recognized as a common interop module name.
|
|
6051
|
+
EyeProlog exports `call_nth/2` there, matching Scryer's explicit import
|
|
6052
|
+
organization while still permitting unqualified autoloaded source. The aligned
|
|
6053
|
+
`library(lists)` and `library(iso_ext)` export sets are intentionally disjoint,
|
|
6054
|
+
so a source file may import both without an accidental predicate collision.
|
|
6055
|
+
`library(prologue)` is retained as an EyeProlog compatibility umbrella and may
|
|
6056
|
+
overlap these modules; use selective imports when legacy code combines it with
|
|
6057
|
+
the aligned libraries.
|
|
6058
|
+
|
|
6049
6059
|
Normal EyeProlog execution can autoload an otherwise undefined unqualified call
|
|
6050
6060
|
only when the interop table assigns it one canonical provider. Thus `member/2`
|
|
6051
|
-
autoloads from `library(lists)
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
`--no-autoload`, by the JavaScript option `autoload: false`, and always by
|
|
6056
|
-
`--iso-strict`.
|
|
6061
|
+
autoloads from `library(lists)`, `call_nth/2` from `library(iso_ext)`, and
|
|
6062
|
+
`between/3` from the internal `library(prologue)` implementation. Autoloading is
|
|
6063
|
+
disabled by `--no-autoload`, by the JavaScript option `autoload: false`, and
|
|
6064
|
+
always by `--iso-strict`.
|
|
6057
6065
|
|
|
6058
6066
|
`-w` / `--warnings` reports explicit non-profile library dependencies and calls
|
|
6059
6067
|
to non-profile predicates from common libraries. `--portable` turns those
|
|
@@ -6075,11 +6083,14 @@ cumulative and two-dimensional scheduling constraints, and unbounded-domain
|
|
|
6075
6083
|
propagation that are not yet exported here.
|
|
6076
6084
|
|
|
6077
6085
|
`library(iso_ext)` collects extensions commonly found in mature Prolog
|
|
6078
|
-
systems. `
|
|
6079
|
-
|
|
6080
|
-
|
|
6081
|
-
|
|
6082
|
-
`
|
|
6086
|
+
systems. `call_nth/2` exposes the ordinal number of each solution and supports
|
|
6087
|
+
the explicit import used by Scryer-style source; `forall/2` checks an action for
|
|
6088
|
+
every solution of a condition; `cfor/3` enumerates an inclusive evaluated
|
|
6089
|
+
integer range; `succ/2` relates adjacent nonnegative integers; `findall/4`
|
|
6090
|
+
collects into a difference list; and `variant/2` recognizes terms equal up to
|
|
6091
|
+
variable renaming. Its portable `countall/2` counts solutions without exposing
|
|
6092
|
+
a template. `countall/2` is not exported by `library(lists)`, avoiding a
|
|
6093
|
+
full-module import collision between the two libraries.
|
|
6083
6094
|
|
|
6084
6095
|
`uuid(+Seed0,-UUID,-Seed)` creates a version 4 UUID atom using `random/3`.
|
|
6085
6096
|
Passing the returned seed to the next call produces the next UUID; restarting
|
|
@@ -6272,6 +6283,7 @@ There is no `not/1` alias; use ISO `\+/1`. `forall/2` is available from
|
|
|
6272
6283
|
```eyeprolog
|
|
6273
6284
|
:- use_module(library(aggregate)).
|
|
6274
6285
|
:- use_module(library(lists)).
|
|
6286
|
+
:- use_module(library(iso_ext)).
|
|
6275
6287
|
|
|
6276
6288
|
cost(a, 8).
|
|
6277
6289
|
cost(b, 3).
|