eyeprolog 1.3.78 → 1.3.80
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 +20 -346
- package/examples/output/portable-library-overlap.pl +1 -0
- package/examples/portable-library-overlap.pl +46 -0
- package/package.json +1 -1
- package/playground.html +2 -1
- package/src/iso.js +5 -2
- package/src/lib/assoc.pl +472 -31
- package/src/lib/charsio.pl +49 -0
- package/src/lib/clpb.pl +1975 -0
- package/src/lib/debug.pl +32 -6
- package/src/lib/dif.pl +7 -0
- package/src/lib/error.pl +2 -2
- package/src/lib/format.pl +60 -26
- package/src/lib/gensym.pl +33 -0
- package/src/lib/lists.pl +30 -0
- package/src/lib/ordsets.pl +619 -0
- package/src/lib/pio.pl +61 -0
- package/src/lib/random.pl +44 -2
- package/src/lib/reif.pl +94 -0
- package/src/lib/tabling.pl +16 -0
- package/src/lib/time.pl +26 -0
- package/src/lib/ugraphs.pl +633 -0
- package/src/lib/uuid.pl +66 -3
- package/src/lib/when.pl +103 -0
- package/src/parser.js +7 -1
- package/src/playground-worker.js +1 -1
- package/src/program.js +3 -2
- package/src/scryer-compat.js +181 -1
- package/src/solver.js +4 -0
- package/src/standard-library.js +117 -17
- package/test/run-regression.mjs +137 -14
- package/the-art-of-eyeprolog.md +113 -54
package/src/lib/when.pl
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
Provides the predicate `when/2`.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
:- module(when, [when/2]).
|
|
6
|
+
|
|
7
|
+
:- use_module(library(atts)).
|
|
8
|
+
:- use_module(library(dcgs)).
|
|
9
|
+
:- use_module(library(lists)).
|
|
10
|
+
:- use_module(library(format)).
|
|
11
|
+
:- use_module(library(debug)).
|
|
12
|
+
|
|
13
|
+
:- attribute when_list/1.
|
|
14
|
+
|
|
15
|
+
:- meta_predicate(when(+, 0)).
|
|
16
|
+
|
|
17
|
+
%% when(Condition, Goal).
|
|
18
|
+
%
|
|
19
|
+
% Executes Goal when Condition becomes true.
|
|
20
|
+
% Condition may consist of `ground(T)`, `nonvar(T)`, `C1,C2`, `C1;C2`.
|
|
21
|
+
when(Condition, Goal) :-
|
|
22
|
+
( when_condition(Condition) ->
|
|
23
|
+
( Condition ->
|
|
24
|
+
Goal
|
|
25
|
+
; term_variables(Condition, Vars),
|
|
26
|
+
maplist(when_add_goal(Goal, Condition), Vars)
|
|
27
|
+
)
|
|
28
|
+
; throw(error(domain_error(when_condition, Condition),_))
|
|
29
|
+
).
|
|
30
|
+
|
|
31
|
+
when_add_goal(Goal, Condition, Var) :-
|
|
32
|
+
( get_atts(Var, when_list(Whens0)) ->
|
|
33
|
+
Whens = [when(Condition, Goal) | Whens0],
|
|
34
|
+
put_atts(Var, when_list(Whens))
|
|
35
|
+
; put_atts(Var, when_list([when(Condition, Goal)]))
|
|
36
|
+
).
|
|
37
|
+
|
|
38
|
+
when_condition(Cond) :-
|
|
39
|
+
% Should this be delayed?
|
|
40
|
+
var(Cond), !, throw(error(instantiation_error,when_condition/1)).
|
|
41
|
+
when_condition(ground(_)).
|
|
42
|
+
when_condition(nonvar(_)).
|
|
43
|
+
when_condition((A, B)) :-
|
|
44
|
+
when_condition(A),
|
|
45
|
+
when_condition(B).
|
|
46
|
+
when_condition((A ; B)) :-
|
|
47
|
+
when_condition(A),
|
|
48
|
+
when_condition(B).
|
|
49
|
+
|
|
50
|
+
remove_goal([], _, []).
|
|
51
|
+
remove_goal([G0|G0s], Goal, Goals) :-
|
|
52
|
+
( G0 == Goal ->
|
|
53
|
+
remove_goal(G0s, Goal, Goals)
|
|
54
|
+
; Goals = [G0|Goals1],
|
|
55
|
+
remove_goal(G0s, Goal, Goals1)
|
|
56
|
+
).
|
|
57
|
+
|
|
58
|
+
vars_remove_goal(Vars, Goal) :-
|
|
59
|
+
maplist(when_remove_goal(Goal), Vars).
|
|
60
|
+
|
|
61
|
+
when_remove_goal(Goal, Var) :-
|
|
62
|
+
( get_atts(Var, when_list(Whens0)) ->
|
|
63
|
+
remove_goal(Whens0, Goal, Whens),
|
|
64
|
+
( Whens = [] ->
|
|
65
|
+
put_atts(Var, -when_list(_))
|
|
66
|
+
; put_atts(Var, when_list(Whens))
|
|
67
|
+
)
|
|
68
|
+
; true
|
|
69
|
+
).
|
|
70
|
+
|
|
71
|
+
reinforce_goal(Goal0, Goal) :-
|
|
72
|
+
Goal = (
|
|
73
|
+
term_variables(Goal0, Vars),
|
|
74
|
+
when:vars_remove_goal(Vars, Goal0),
|
|
75
|
+
Goal0
|
|
76
|
+
).
|
|
77
|
+
|
|
78
|
+
verify_attributes(Var, Value, Goals) :-
|
|
79
|
+
( get_atts(Var, when_list(Whens)) ->
|
|
80
|
+
( var(Value) ->
|
|
81
|
+
( get_atts(Value, when_list(WhensValue)) ->
|
|
82
|
+
append(Whens, WhensValue, WhensNew),
|
|
83
|
+
put_atts(Value, when_list(WhensNew))
|
|
84
|
+
; put_atts(Value, when_list(Whens))
|
|
85
|
+
),
|
|
86
|
+
Goals = []
|
|
87
|
+
; maplist(reinforce_goal, Whens, Goals)
|
|
88
|
+
)
|
|
89
|
+
; Goals = []
|
|
90
|
+
).
|
|
91
|
+
|
|
92
|
+
gather_when_goals([], _) --> [].
|
|
93
|
+
gather_when_goals([When|Whens], Var) -->
|
|
94
|
+
( { term_variables(When, [V0|_]), Var == V0 } ->
|
|
95
|
+
[when:When]
|
|
96
|
+
; []
|
|
97
|
+
),
|
|
98
|
+
gather_when_goals(Whens, Var).
|
|
99
|
+
|
|
100
|
+
attribute_goals(Var) -->
|
|
101
|
+
{ get_atts(Var, when_list(Whens)) },
|
|
102
|
+
gather_when_goals(Whens, Var),
|
|
103
|
+
{ put_atts(Var, -when_list(_)) }.
|
package/src/parser.js
CHANGED
|
@@ -381,6 +381,12 @@ class Parser {
|
|
|
381
381
|
// Scryer library(atts) exports this declaration operator. EyeProlog
|
|
382
382
|
// handles the directive directly instead of relying on term expansion.
|
|
383
383
|
this.defineOperator(1199, 'fx', 'attribute');
|
|
384
|
+
} else if (designation.args[0].name === 'tabling') {
|
|
385
|
+
this.defineOperator(1150, 'fx', 'table');
|
|
386
|
+
} else if (designation.args[0].name === 'debug') {
|
|
387
|
+
this.defineOperator(900, 'fx', '$');
|
|
388
|
+
this.defineOperator(900, 'fx', '$-');
|
|
389
|
+
this.defineOperator(950, 'fy', '*');
|
|
384
390
|
}
|
|
385
391
|
}
|
|
386
392
|
operatorTokenName(token = this.token) {
|
|
@@ -1041,7 +1047,7 @@ class Parser {
|
|
|
1041
1047
|
(['char_conversion', 'set_prolog_flag'].includes(directive.name) && directive.arity === 2)
|
|
1042
1048
|
);
|
|
1043
1049
|
const extensionDirective = directive.type === 'compound' && (
|
|
1044
|
-
(['use_module', 'meta_predicate', 'attribute'].includes(directive.name) && directive.arity === 1) ||
|
|
1050
|
+
(['use_module', 'meta_predicate', 'attribute', 'table'].includes(directive.name) && directive.arity === 1) ||
|
|
1045
1051
|
(['module', 'use_module'].includes(directive.name) && directive.arity === 2)
|
|
1046
1052
|
);
|
|
1047
1053
|
if (this.strictIso && extensionDirective) {
|
package/src/playground-worker.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Browser worker entry used by playground.html.
|
|
2
2
|
// Keep this module free of Node-only imports: it is fetched directly by the
|
|
3
3
|
// browser and is also exercised by test/run-playground.mjs.
|
|
4
|
-
import { createEyePrologRegistry, run } from './index.js?playground=
|
|
4
|
+
import { createEyePrologRegistry, run } from './index.js?playground=20260825a';
|
|
5
5
|
|
|
6
6
|
const registry = createEyePrologRegistry();
|
|
7
7
|
|
package/src/program.js
CHANGED
|
@@ -1412,8 +1412,9 @@ function annotateGoalModule(term, module) {
|
|
|
1412
1412
|
if (!term || (term.type !== ATOM && term.type !== COMPOUND)) return term;
|
|
1413
1413
|
term.module = module;
|
|
1414
1414
|
const callableArguments = (term.name === ',' || term.name === ';' || term.name === '->') ? term.args
|
|
1415
|
-
: (['call', 'once', '\\+', 'not', 'catch', '
|
|
1416
|
-
'
|
|
1415
|
+
: (['call', 'once', '\\+', 'not', 'catch', 'call_cleanup', 'setup_call_cleanup',
|
|
1416
|
+
'forall', 'findall', 'bagof', 'setof', 'countall', 'sumall',
|
|
1417
|
+
'aggregate_min', 'aggregate_max', 'maplist', 'phrase'].includes(term.name)
|
|
1417
1418
|
? term.args
|
|
1418
1419
|
: []);
|
|
1419
1420
|
for (const arg of callableArguments) annotateGoalModule(arg, module);
|
package/src/scryer-compat.js
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// backtrackable blackboard lives in Env so ordinary Prolog choice points undo
|
|
5
5
|
// writes automatically.
|
|
6
6
|
|
|
7
|
-
import { ATOM, NUMBER, STRING, deref, unify } from './term.js';
|
|
7
|
+
import { ATOM, COMPOUND, NUMBER, STRING, VAR, atom, compound, deref, listFromItems, unify } from './term.js';
|
|
8
8
|
import { PrologError } from './errors.js';
|
|
9
|
+
import { formatTermForWrite } from './write.js';
|
|
9
10
|
|
|
10
11
|
function blackboardKey(term, env) {
|
|
11
12
|
const value = deref(term, env);
|
|
@@ -31,9 +32,188 @@ function* bbPutBuiltin({ goal, env }) {
|
|
|
31
32
|
yield next;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
function* bbGlobalGetBuiltin({ solver, goal, env }) {
|
|
36
|
+
const key = blackboardKey(goal.args[0], env);
|
|
37
|
+
const stored = solver.nonBacktrackableBlackboard.get(key);
|
|
38
|
+
if (stored === undefined) return;
|
|
39
|
+
const next = env.clone();
|
|
40
|
+
if (unify(goal.args[1], stored, next)) yield next;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function* bbGlobalPutBuiltin({ solver, goal, env }) {
|
|
44
|
+
const key = blackboardKey(goal.args[0], env);
|
|
45
|
+
solver.nonBacktrackableBlackboard.set(key, deref(goal.args[1], env));
|
|
46
|
+
yield env;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const charTypeNames = new Set([
|
|
50
|
+
'alnum', 'alpha', 'alphabetic', 'alphanumeric', 'ascii', 'ascii_graphic',
|
|
51
|
+
'ascii_punctuation', 'binary_digit', 'control', 'decimal_digit', 'exponent',
|
|
52
|
+
'graphic', 'graphic_token', 'hexadecimal_digit', 'layout', 'lower', 'meta',
|
|
53
|
+
'numeric', 'octal_digit', 'octet', 'prolog', 'sign', 'solo',
|
|
54
|
+
'symbolic_control', 'symbolic_hexadecimal', 'upper', 'whitespace',
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
function charTypeCandidates(ch) {
|
|
58
|
+
const code = ch.codePointAt(0);
|
|
59
|
+
const letter = /\p{L}/u.test(ch);
|
|
60
|
+
const decimal = /\p{Nd}/u.test(ch);
|
|
61
|
+
const numeric = /\p{N}/u.test(ch);
|
|
62
|
+
const whitespace = /\s/u.test(ch);
|
|
63
|
+
const control = /\p{Cc}/u.test(ch);
|
|
64
|
+
const lower = /\p{Ll}/u.test(ch);
|
|
65
|
+
const upper = /\p{Lu}/u.test(ch);
|
|
66
|
+
const asciiGraphic = code >= 0x21 && code <= 0x7e;
|
|
67
|
+
const out = [];
|
|
68
|
+
const add = (name, yes) => { if (yes) out.push(atom(name)); };
|
|
69
|
+
add('alnum', letter || decimal);
|
|
70
|
+
add('alpha', letter);
|
|
71
|
+
add('alphabetic', letter);
|
|
72
|
+
add('alphanumeric', letter || decimal);
|
|
73
|
+
add('ascii', code <= 0x7f);
|
|
74
|
+
add('ascii_graphic', asciiGraphic);
|
|
75
|
+
add('ascii_punctuation', asciiGraphic && !letter && !decimal);
|
|
76
|
+
add('binary_digit', ch === '0' || ch === '1');
|
|
77
|
+
add('control', control);
|
|
78
|
+
add('decimal_digit', decimal);
|
|
79
|
+
add('exponent', ch === 'e' || ch === 'E');
|
|
80
|
+
add('graphic', !whitespace && !control);
|
|
81
|
+
add('graphic_token', '#$&*+-./:<=>?@\\^~'.includes(ch));
|
|
82
|
+
add('hexadecimal_digit', /^[0-9A-Fa-f]$/.test(ch));
|
|
83
|
+
add('layout', whitespace);
|
|
84
|
+
add('lower', lower);
|
|
85
|
+
add('meta', "\\'\"`".includes(ch));
|
|
86
|
+
add('numeric', numeric);
|
|
87
|
+
add('octal_digit', /^[0-7]$/.test(ch));
|
|
88
|
+
add('octet', code <= 0xff);
|
|
89
|
+
add('prolog', true);
|
|
90
|
+
add('sign', ch === '+' || ch === '-');
|
|
91
|
+
add('solo', '!,;[]{}()|'.includes(ch));
|
|
92
|
+
add('symbolic_control', '#$&*+-./:<=>?@\\^~'.includes(ch));
|
|
93
|
+
add('symbolic_hexadecimal', /^[A-Fa-f]$/.test(ch));
|
|
94
|
+
add('upper', upper);
|
|
95
|
+
add('whitespace', whitespace);
|
|
96
|
+
out.push(compound('lower', [listFromItems([...ch.toLowerCase()].map(atom))]));
|
|
97
|
+
out.push(compound('upper', [listFromItems([...ch.toUpperCase()].map(atom))]));
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function validCharType(term) {
|
|
102
|
+
return (term.type === ATOM && charTypeNames.has(term.name)) ||
|
|
103
|
+
(term.type === COMPOUND && ['lower', 'upper'].includes(term.name) && term.arity === 1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function* charTypeBuiltin({ goal, env }) {
|
|
107
|
+
const char = deref(goal.args[0], env);
|
|
108
|
+
const type = deref(goal.args[1], env);
|
|
109
|
+
if (char.type === VAR && type.type === VAR) throw new PrologError('instantiation_error');
|
|
110
|
+
if (char.type !== VAR && (char.type !== ATOM || [...char.name].length !== 1)) {
|
|
111
|
+
throw new PrologError('type_error(character)', char);
|
|
112
|
+
}
|
|
113
|
+
if (type.type !== VAR && !validCharType(type)) throw new PrologError('domain_error(char_type)', type);
|
|
114
|
+
|
|
115
|
+
const chars = char.type === VAR
|
|
116
|
+
? (function* unicodeScalars() {
|
|
117
|
+
for (let code = 0; code <= 0x10ffff; code++) {
|
|
118
|
+
if (code >= 0xd800 && code <= 0xdfff) continue;
|
|
119
|
+
yield String.fromCodePoint(code);
|
|
120
|
+
}
|
|
121
|
+
})()
|
|
122
|
+
: [char.name];
|
|
123
|
+
for (const ch of chars) {
|
|
124
|
+
for (const candidate of charTypeCandidates(ch)) {
|
|
125
|
+
const next = env.clone();
|
|
126
|
+
if (unify(goal.args[0], atom(ch), next) && unify(goal.args[1], candidate, next)) yield next;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const shortMonths = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
|
|
132
|
+
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
|
|
133
|
+
const longMonths = ['January', 'February', 'March', 'April', 'May', 'June',
|
|
134
|
+
'July', 'August', 'September', 'October', 'November', 'December'];
|
|
135
|
+
const shortWeekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
|
136
|
+
const longWeekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
137
|
+
|
|
138
|
+
function chars(value) {
|
|
139
|
+
return listFromItems([...String(value)].map(atom));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function* currentTimeBuiltin({ goal, env }) {
|
|
143
|
+
const now = new Date();
|
|
144
|
+
const pad = (value, width = 2) => String(value).padStart(width, '0');
|
|
145
|
+
const dayOfYear = Math.floor((
|
|
146
|
+
Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) -
|
|
147
|
+
Date.UTC(now.getFullYear(), 0, 1)
|
|
148
|
+
) / 86400000) + 1;
|
|
149
|
+
const entries = [
|
|
150
|
+
['Y', String(now.getFullYear())],
|
|
151
|
+
['m', pad(now.getMonth() + 1)],
|
|
152
|
+
['d', pad(now.getDate())],
|
|
153
|
+
['H', pad(now.getHours())],
|
|
154
|
+
['M', pad(now.getMinutes())],
|
|
155
|
+
['S', pad(now.getSeconds())],
|
|
156
|
+
['y', pad(now.getFullYear() % 100)],
|
|
157
|
+
['b', shortMonths[now.getMonth()]],
|
|
158
|
+
['B', longMonths[now.getMonth()]],
|
|
159
|
+
['a', shortWeekdays[now.getDay()]],
|
|
160
|
+
['A', longWeekdays[now.getDay()]],
|
|
161
|
+
['w', String(now.getDay())],
|
|
162
|
+
['u', String(now.getDay() === 0 ? 7 : now.getDay())],
|
|
163
|
+
['j', pad(dayOfYear, 3)],
|
|
164
|
+
].map(([key, value]) => compound('=', [atom(key), chars(value)]));
|
|
165
|
+
const next = env.clone();
|
|
166
|
+
if (unify(goal.args[0], listFromItems(entries), next)) yield next;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function* abolishAllTablesBuiltin({ solver, env }) {
|
|
170
|
+
solver.memo.clear();
|
|
171
|
+
solver.subsumptiveMemo.clear();
|
|
172
|
+
solver.wfsModels.clear();
|
|
173
|
+
solver.datalogModels.clear();
|
|
174
|
+
solver.tableCoordinator = null;
|
|
175
|
+
solver.groundChainSuccess.clear();
|
|
176
|
+
solver.compactChainSuccess.clear();
|
|
177
|
+
for (const scope of solver.innerTableScopes.values()) {
|
|
178
|
+
scope.memo.clear();
|
|
179
|
+
scope.subsumptiveMemo.clear();
|
|
180
|
+
}
|
|
181
|
+
yield env;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function* termCharsBuiltin({ solver, goal, env }) {
|
|
185
|
+
const mode = deref(goal.args[0], env);
|
|
186
|
+
if (mode.type !== ATOM || !['a', 'd', 'q', 'w'].includes(mode.name)) {
|
|
187
|
+
throw new PrologError('domain_error(format_control)', mode);
|
|
188
|
+
}
|
|
189
|
+
const value = deref(goal.args[1], env);
|
|
190
|
+
if (mode.name === 'd' && value.type !== NUMBER) throw new PrologError('type_error(integer)', value);
|
|
191
|
+
if (mode.name === 'a' && ![ATOM, NUMBER, STRING].includes(value.type)) {
|
|
192
|
+
throw new PrologError('type_error(atomic)', value);
|
|
193
|
+
}
|
|
194
|
+
const text = formatTermForWrite(goal.args[1], env, {
|
|
195
|
+
quoted: mode.name === 'q',
|
|
196
|
+
numbervars: true,
|
|
197
|
+
compact: true,
|
|
198
|
+
minimalOperatorSpacing: true,
|
|
199
|
+
operatorAtomsAsArgs: true,
|
|
200
|
+
generateVariableNames: true,
|
|
201
|
+
variableNameState: solver.writeVariableState,
|
|
202
|
+
operators: solver.program.operators.values(),
|
|
203
|
+
});
|
|
204
|
+
const next = env.clone();
|
|
205
|
+
if (unify(goal.args[2], chars(text), next)) yield next;
|
|
206
|
+
}
|
|
207
|
+
|
|
34
208
|
export const scryerCompatibilityBuiltins = {
|
|
35
209
|
register(registry) {
|
|
36
210
|
registry.add('eyeprolog__bb_get', 2, bbGetBuiltin, { eyePrologLibrary: true });
|
|
37
211
|
registry.add('eyeprolog__bb_b_put', 2, bbPutBuiltin, { deterministic: true, eyePrologLibrary: true });
|
|
212
|
+
registry.add('eyeprolog__bb_global_get', 2, bbGlobalGetBuiltin, { eyePrologLibrary: true });
|
|
213
|
+
registry.add('eyeprolog__bb_global_put', 2, bbGlobalPutBuiltin, { deterministic: true, eyePrologLibrary: true });
|
|
214
|
+
registry.add('eyeprolog__char_type', 2, charTypeBuiltin, { eyePrologLibrary: true });
|
|
215
|
+
registry.add('eyeprolog__current_time', 1, currentTimeBuiltin, { deterministic: true, eyePrologLibrary: true });
|
|
216
|
+
registry.add('eyeprolog__abolish_all_tables', 0, abolishAllTablesBuiltin, { deterministic: true, eyePrologLibrary: true });
|
|
217
|
+
registry.add('eyeprolog__term_chars', 3, termCharsBuiltin, { deterministic: true, eyePrologLibrary: true });
|
|
38
218
|
},
|
|
39
219
|
};
|
package/src/solver.js
CHANGED
|
@@ -185,6 +185,9 @@ export class Solver {
|
|
|
185
185
|
// distinct meta-call inputs must not turn completed table variants into
|
|
186
186
|
// process-lifetime roots.
|
|
187
187
|
this.innerTableScopes = options.innerTableScopes ?? new Map();
|
|
188
|
+
// Non-backtrackable library state (for example gensym/2 and CLP(B) node
|
|
189
|
+
// identifiers) is shared by nested solvers for the lifetime of this run.
|
|
190
|
+
this.nonBacktrackableBlackboard = options.nonBacktrackableBlackboard ?? new Map();
|
|
188
191
|
this.stats = {
|
|
189
192
|
completed_goal_lists: 0,
|
|
190
193
|
solve_goals_calls: 0,
|
|
@@ -216,6 +219,7 @@ export class Solver {
|
|
|
216
219
|
charConversions: this.charConversions,
|
|
217
220
|
io: this.io,
|
|
218
221
|
innerTableScopes: this.innerTableScopes,
|
|
222
|
+
nonBacktrackableBlackboard: this.nonBacktrackableBlackboard,
|
|
219
223
|
inferenceObservation: this.inferenceObservation,
|
|
220
224
|
writeVariableState: this.writeVariableState,
|
|
221
225
|
skipListTailTabling: options.skipListTailTabling ?? this.skipListTailTabling,
|
package/src/standard-library.js
CHANGED
|
@@ -16,30 +16,41 @@ const moduleFiles = Object.freeze({
|
|
|
16
16
|
assoc: 'assoc.pl',
|
|
17
17
|
atts: 'atts.pl',
|
|
18
18
|
between: 'between.pl',
|
|
19
|
+
charsio: 'charsio.pl',
|
|
20
|
+
clpb: 'clpb.pl',
|
|
19
21
|
clpz: 'clpz.pl',
|
|
20
22
|
comparison: 'comparison.pl',
|
|
21
23
|
dates: 'dates.pl',
|
|
22
24
|
dcgs: 'dcgs.pl',
|
|
23
25
|
debug: 'debug.pl',
|
|
26
|
+
dif: 'dif.pl',
|
|
24
27
|
error: 'error.pl',
|
|
25
28
|
format: 'format.pl',
|
|
26
29
|
freeze: 'freeze.pl',
|
|
30
|
+
gensym: 'gensym.pl',
|
|
27
31
|
iso_ext: 'iso_ext.pl',
|
|
28
32
|
lambda: 'lambda.pl',
|
|
29
33
|
lists: 'lists.pl',
|
|
34
|
+
ordsets: 'ordsets.pl',
|
|
30
35
|
pairs: 'pairs.pl',
|
|
36
|
+
pio: 'pio.pl',
|
|
31
37
|
primes: 'primes.pl',
|
|
32
38
|
prologue: 'prologue.pl',
|
|
33
39
|
random: 'random.pl',
|
|
40
|
+
reif: 'reif.pl',
|
|
34
41
|
si: 'si.pl',
|
|
35
42
|
strings: 'strings.pl',
|
|
36
43
|
terms: 'terms.pl',
|
|
44
|
+
tabling: 'tabling.pl',
|
|
45
|
+
time: 'time.pl',
|
|
46
|
+
ugraphs: 'ugraphs.pl',
|
|
37
47
|
uuid: 'uuid.pl',
|
|
48
|
+
when: 'when.pl',
|
|
38
49
|
});
|
|
39
50
|
|
|
40
51
|
const cacheKey = isNode
|
|
41
52
|
? null
|
|
42
|
-
: (new URL(import.meta.url).searchParams.get('playground') ?? '
|
|
53
|
+
: (new URL(import.meta.url).searchParams.get('playground') ?? '20260825a');
|
|
43
54
|
|
|
44
55
|
export const standardLibrarySources = new Map(await Promise.all(
|
|
45
56
|
Object.entries(moduleFiles).map(async ([name, filename]) => [name, {
|
|
@@ -69,25 +80,70 @@ export const eyePrologNativeLibraryIndicators = Object.freeze([
|
|
|
69
80
|
'in/2', 'ins/2', 'all_different/1', 'all_distinct/1', 'nvalue/2', 'sum/3',
|
|
70
81
|
'scalar_product/4', 'tuples_in/2', 'labeling/2', 'label/1',
|
|
71
82
|
'indomain/1', 'lex_chain/1', 'serialized/2', 'global_cardinality/2',
|
|
72
|
-
'global_cardinality/3', 'circuit/1', '
|
|
83
|
+
'global_cardinality/3', 'circuit/1', 'cumulative/1', 'cumulative/2',
|
|
84
|
+
'disjoint2/1', 'automaton/3', 'automaton/8', 'chain/2', 'element/3', 'zcompare/3',
|
|
73
85
|
'fd_var/1', 'fd_inf/2', 'fd_sup/2', 'fd_size/2', 'fd_dom/2',
|
|
86
|
+
'clpz_t/2', '#=/3', '#</3',
|
|
74
87
|
]);
|
|
75
88
|
export const eyePrologPortableLibraryIndicators = Object.freeze([
|
|
76
89
|
'sumall/3', 'aggregate_min/5', 'aggregate_max/5',
|
|
77
|
-
'
|
|
78
|
-
'
|
|
79
|
-
'
|
|
80
|
-
'
|
|
81
|
-
'
|
|
82
|
-
'
|
|
83
|
-
'
|
|
84
|
-
'
|
|
85
|
-
'
|
|
86
|
-
'
|
|
87
|
-
'
|
|
90
|
+
'lsb/2', 'msb/2', 'popcount/2',
|
|
91
|
+
'empty_assoc/1', 'assoc_to_list/2', 'get_assoc/3', 'put_assoc/4',
|
|
92
|
+
'assoc_to_keys/2', 'assoc_to_values/2', 'del_assoc/4', 'del_max_assoc/4',
|
|
93
|
+
'del_min_assoc/4', 'gen_assoc/3', 'get_assoc/5', 'is_assoc/1',
|
|
94
|
+
'list_to_assoc/2', 'map_assoc/2', 'map_assoc/3', 'max_assoc/3',
|
|
95
|
+
'min_assoc/3', 'ord_list_to_assoc/2',
|
|
96
|
+
'between/3', 'gen_int/1', 'gen_nat/1', 'numlist/2', 'numlist/3', 'repeat/1',
|
|
97
|
+
'char_type/2', 'get_line_to_chars/3', 'get_n_chars/3', 'get_single_char/1',
|
|
98
|
+
'sat/1', 'taut/2', 'labeling/1', 'sat_count/2', 'random_labeling/2', 'weighted_maximum/3',
|
|
99
|
+
'lt/2', 'gt/2', 'le/2', 'ge/2',
|
|
100
|
+
'difference/3',
|
|
101
|
+
'seq/3', 'seqq/3',
|
|
102
|
+
'debug/1', 'debug/3', 'nodebug/1', 'bb_get/2', 'bb_put/2', 'bb_b_put/2', 'bb_global_get/2',
|
|
103
|
+
'*/1', '$/1', '$-/1',
|
|
104
|
+
'must_be/2', 'can_be/2', 'instantiation_error/0', 'instantiation_error/1',
|
|
105
|
+
'domain_error/2', 'domain_error/3', 'type_error/2', 'type_error/3',
|
|
106
|
+
'representation_error/1', 'resource_error/1', 'call_with_error_context/2',
|
|
107
|
+
'format_/4', 'format/2', 'format/3', 'portray_clause_/3',
|
|
108
|
+
'portray_clause/1', 'portray_clause/2', 'listing/1',
|
|
109
|
+
'gensym/2', 'reset_gensym/1',
|
|
110
|
+
'forall/2', 'succ/2', 'cfor/3', 'findall/4', 'variant/2', '.../2',
|
|
88
111
|
'^/3', '^/4', '^/5', '^/6', '^/7', '^/8', '^/9', '^/10',
|
|
89
112
|
'\\/1', '\\/2', '\\/3', '\\/4', '\\/5', '\\/6', '\\/7', '\\/8',
|
|
90
113
|
'+\\/2', '+\\/3', '+\\/4', '+\\/5', '+\\/6', '+\\/7', '+\\/8', '+\\/9',
|
|
114
|
+
'member/2', 'memberchk/2', 'select/3', 'append/2', 'append/3', 'last/2', 'same_length/2',
|
|
115
|
+
'nth0/3', 'nth0/4', 'nth1/3', 'nth1/4', 'set_nth0/4', 'take/3', 'drop/3', 'slice/4', 'reverse/2',
|
|
116
|
+
'length/2', 'maplist/2', 'maplist/3', 'maplist/4', 'maplist/5',
|
|
117
|
+
'maplist/6', 'maplist/7', 'maplist/8', 'foldl/4', 'foldl/5', 'foldl/6',
|
|
118
|
+
'sum_list/2', 'min_list/2', 'max_list/2', 'list_to_set/2',
|
|
119
|
+
'transpose/2', 'list_max/2', 'list_min/2', 'permutation/2',
|
|
120
|
+
'is_ordset/1', 'list_to_ord_set/2', 'ord_add_element/3', 'ord_del_element/3',
|
|
121
|
+
'ord_disjoint/2', 'ord_empty/1', 'ord_intersect/2', 'ord_intersect/3',
|
|
122
|
+
'ord_intersection/2', 'ord_intersection/3', 'ord_intersection/4',
|
|
123
|
+
'ord_memberchk/2', 'ord_selectchk/3', 'ord_seteq/2', 'ord_subset/2',
|
|
124
|
+
'ord_subtract/3', 'ord_symdiff/3', 'ord_union/2', 'ord_union/3', 'ord_union/4',
|
|
125
|
+
'pairs_keys_values/3', 'pairs_keys/2', 'pairs_values/2',
|
|
126
|
+
'group_pairs_by_key/2', 'map_list_to_pairs/3',
|
|
127
|
+
'phrase_from_file/2', 'phrase_from_file/3', 'phrase_to_file/2',
|
|
128
|
+
'phrase_to_file/3', 'phrase_to_stream/2',
|
|
129
|
+
'smallest_divisor_from/3',
|
|
130
|
+
'maybe/0', 'random/3', 'random_integer/3', 'set_random/1',
|
|
131
|
+
',/3', ';/3', '=/3', 'cond_t/3', 'dif/3', 'if_/3', 'memberd_t/3',
|
|
132
|
+
'tfilter/3', 'tmember/2', 'tmember_t/3', 'tpartition/4',
|
|
133
|
+
'atom_si/1', 'integer_si/1', 'atomic_si/1', 'list_si/1', 'character_si/1',
|
|
134
|
+
'term_si/1', 'chars_si/1', 'dif_si/2', 'not_si/1', 'when_si/2',
|
|
135
|
+
'matches/3', 'split/3', 'replace/4', 'lowercase/2', 'uppercase/2', 'trim/2',
|
|
136
|
+
'number_string/2', 'atom_string/2', 'term_string/2', 'string_concat/3',
|
|
137
|
+
'contains/2', 'matches/2', 'join/3', 'substring/4',
|
|
138
|
+
'numbervars/3', 'copy_term_nat/2',
|
|
139
|
+
'start_tabling/2', 'abolish_all_tables/0',
|
|
140
|
+
'current_time/1', 'format_time/4',
|
|
141
|
+
'add_edges/3', 'add_vertices/3', 'complement/2', 'compose/3', 'connect_ugraph/3',
|
|
142
|
+
'del_edges/3', 'del_vertices/3', 'edges/2', 'neighbors/3', 'neighbours/3',
|
|
143
|
+
'reachable/3', 'top_sort/2', 'top_sort/3', 'transitive_closure/2',
|
|
144
|
+
'transpose_ugraph/2', 'ugraph_union/3', 'vertices/2', 'vertices_edges_to_ugraph/3',
|
|
145
|
+
'uuid/3', 'uuid_string/2', 'uuidv4/1', 'uuidv4_string/1',
|
|
146
|
+
'when/2',
|
|
91
147
|
]);
|
|
92
148
|
export const eyePrologLibraryIndicators = Object.freeze([
|
|
93
149
|
...eyePrologPortableLibraryIndicators,
|
|
@@ -147,14 +203,58 @@ export const eyePrologInteropAutoload = Object.freeze({
|
|
|
147
203
|
'between/3': 'between',
|
|
148
204
|
});
|
|
149
205
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
206
|
+
const eyePrologSharedLibraryIndicators = [
|
|
207
|
+
'lsb/2', 'msb/2', 'popcount/2',
|
|
208
|
+
'empty_assoc/1', 'assoc_to_keys/2', 'assoc_to_list/2', 'assoc_to_values/2',
|
|
209
|
+
'del_assoc/4', 'del_max_assoc/4', 'del_min_assoc/4', 'gen_assoc/3',
|
|
210
|
+
'get_assoc/3', 'get_assoc/5', 'is_assoc/1', 'list_to_assoc/2',
|
|
211
|
+
'map_assoc/2', 'map_assoc/3', 'max_assoc/3', 'min_assoc/3',
|
|
212
|
+
'ord_list_to_assoc/2', 'put_assoc/4',
|
|
213
|
+
'char_type/2', 'get_line_to_chars/3', 'get_n_chars/3', 'get_single_char/1',
|
|
214
|
+
'sat/1', 'taut/2', 'labeling/1', 'sat_count/2', 'random_labeling/2', 'weighted_maximum/3',
|
|
215
|
+
'#>/2', '#</2', '#>=/2', '#=</2', '#=/2', '#\\=/2', '#\\/1',
|
|
216
|
+
'#<==>/2', '#==>/2', '#<==/2', '#\\//2', '#\\/2', '#/\\/2',
|
|
217
|
+
'in/2', 'ins/2', 'all_different/1', 'all_distinct/1', 'nvalue/2', 'sum/3',
|
|
218
|
+
'scalar_product/4', 'tuples_in/2', 'labeling/2', 'label/1', 'indomain/1',
|
|
219
|
+
'lex_chain/1', 'serialized/2', 'global_cardinality/2', 'global_cardinality/3',
|
|
220
|
+
'circuit/1', 'cumulative/1', 'cumulative/2', 'disjoint2/1', 'automaton/3',
|
|
221
|
+
'automaton/8', 'chain/2', 'element/3', 'zcompare/3', 'fd_var/1', 'fd_inf/2',
|
|
222
|
+
'fd_sup/2', 'fd_size/2', 'fd_dom/2', 'clpz_t/2', '#=/3', '#</3',
|
|
223
|
+
'*/1', '$/1', '$-/1', 'dif/2',
|
|
224
|
+
'format_/4', 'format/2', 'format/3', 'portray_clause_/3',
|
|
225
|
+
'portray_clause/1', 'portray_clause/2', 'listing/1',
|
|
226
|
+
'gensym/2', 'reset_gensym/1',
|
|
227
|
+
'transpose/2', 'list_max/2', 'list_min/2', 'permutation/2',
|
|
228
|
+
'is_ordset/1', 'list_to_ord_set/2', 'ord_add_element/3', 'ord_del_element/3',
|
|
229
|
+
'ord_disjoint/2', 'ord_empty/1', 'ord_intersect/2', 'ord_intersect/3',
|
|
230
|
+
'ord_intersection/2', 'ord_intersection/3', 'ord_intersection/4',
|
|
231
|
+
'ord_memberchk/2', 'ord_selectchk/3', 'ord_seteq/2', 'ord_subset/2',
|
|
232
|
+
'ord_subtract/3', 'ord_symdiff/3', 'ord_union/2', 'ord_union/3', 'ord_union/4',
|
|
233
|
+
'phrase_from_file/2', 'phrase_from_file/3', 'phrase_to_file/2',
|
|
234
|
+
'phrase_to_file/3', 'phrase_to_stream/2',
|
|
235
|
+
'maybe/0', 'random_integer/3', 'set_random/1',
|
|
236
|
+
',/3', ';/3', '=/3', 'cond_t/3', 'dif/3', 'if_/3', 'memberd_t/3',
|
|
237
|
+
'tfilter/3', 'tmember/2', 'tmember_t/3', 'tpartition/4',
|
|
238
|
+
'start_tabling/2', 'abolish_all_tables/0', 'current_time/1', 'format_time/4',
|
|
239
|
+
'add_edges/3', 'add_vertices/3', 'complement/2', 'compose/3', 'connect_ugraph/3',
|
|
240
|
+
'del_edges/3', 'del_vertices/3', 'edges/2', 'neighbors/3', 'neighbours/3',
|
|
241
|
+
'reachable/3', 'top_sort/2', 'top_sort/3', 'transitive_closure/2',
|
|
242
|
+
'transpose_ugraph/2', 'ugraph_union/3', 'vertices/2', 'vertices_edges_to_ugraph/3',
|
|
243
|
+
'uuid_string/2', 'uuidv4/1', 'uuidv4_string/1', 'when/2',
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
export const eyePrologInteropLibraryIndicators = Object.freeze([
|
|
247
|
+
...new Set([...Object.keys(eyePrologInteropAutoload), ...eyePrologSharedLibraryIndicators]),
|
|
248
|
+
]);
|
|
153
249
|
|
|
154
250
|
// Libraries whose *name* is part of the current interop profile. A program
|
|
155
251
|
// may freely use_module/1 with these common module names; predicates in those
|
|
156
252
|
// modules outside eyePrologInteropLibraryIndicators are still diagnosed when used.
|
|
157
|
-
export const eyePrologInteropLibraryModules = Object.freeze([
|
|
253
|
+
export const eyePrologInteropLibraryModules = Object.freeze([
|
|
254
|
+
'arithmetic', 'assoc', 'atts', 'charsio', 'clpb', 'clpz', 'debug', 'dif',
|
|
255
|
+
'format', 'freeze', 'gensym', 'iso_ext', 'lambda', 'lists', 'ordsets', 'pio',
|
|
256
|
+
'random', 'reif', 'tabling', 'time', 'ugraphs', 'uuid', 'when',
|
|
257
|
+
]);
|
|
158
258
|
|
|
159
259
|
function* tabledNegationBuiltin({ solver, goal, env }) {
|
|
160
260
|
yield* solver.solveTabledNegation(goal.args[0], env);
|