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/test/run-regression.mjs
CHANGED
|
@@ -3987,7 +3987,15 @@ function documentationSyncCases() {
|
|
|
3987
3987
|
},
|
|
3988
3988
|
{
|
|
3989
3989
|
name: 'book EyeProlog library matches runtime registry',
|
|
3990
|
-
run: () =>
|
|
3990
|
+
run: () => {
|
|
3991
|
+
assertArrayEqual(bookEyePrologLibraryNames(), registeredEyePrologLibraryNames(), 'EyeProlog library predicates');
|
|
3992
|
+
assertArrayEqual(bookLibraryModuleIssues(), [], 'library module export catalog');
|
|
3993
|
+
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
3994
|
+
assertIncludes(book, `**${eyePrologLibraryIndicators.length} distinct non-ISO library and normal-extension predicate`, 'library predicate count');
|
|
3995
|
+
assertIncludes(book, `**${eyePrologPortableLibraryIndicators.length} are defined entirely as ordinary Prolog clauses**`, 'portable library count');
|
|
3996
|
+
assertIncludes(book, `**${eyePrologNativeLibraryIndicators.length} use host support**`, 'host-supported library count');
|
|
3997
|
+
assertIncludes(book, `**${createDefaultRegistry().defs.size + eyePrologLibraryIndicators.length} distinct predicate indicators**`, 'combined catalog count');
|
|
3998
|
+
},
|
|
3991
3999
|
},
|
|
3992
4000
|
{
|
|
3993
4001
|
name: 'README cover links to the book and the book documents runtime boundaries',
|
|
@@ -3999,11 +4007,10 @@ function documentationSyncCases() {
|
|
|
3999
4007
|
'<a href="https://eyereasoner.github.io/eyeprolog/the-art-of-eyeprolog">\n <img src="book-assets/title-page.svg" alt="Read The Art of EyeProlog"',
|
|
4000
4008
|
'README cover links to the book',
|
|
4001
4009
|
);
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
'src/
|
|
4005
|
-
|
|
4006
|
-
'src/playground-worker.js']) {
|
|
4010
|
+
const documentedSources = ['src/iso.js', 'src/dcg.js', 'src/atts.js', 'src/standard-library.js',
|
|
4011
|
+
...[...standardLibrarySources.values()].map((entry) => entry.filename),
|
|
4012
|
+
'src/playground-worker.js'];
|
|
4013
|
+
for (const filename of documentedSources) {
|
|
4007
4014
|
assertEqual(fs.existsSync(path.join(packageRoot, filename)), true, `${filename} exists`);
|
|
4008
4015
|
assertIncludes(book, filename, `book documents ${filename}`);
|
|
4009
4016
|
}
|
|
@@ -4161,6 +4168,11 @@ function documentationSyncCases() {
|
|
|
4161
4168
|
]) assertIncludes(book, name, `book ${name}`);
|
|
4162
4169
|
assertIncludes(readme, 'implementation reference is [*The Art of EyeProlog*]', 'README book hand-off');
|
|
4163
4170
|
assertIncludes(readme, 'test/conformance/ISO-COMPLIANCE.md', 'README concise audit link');
|
|
4171
|
+
assertEqual(readme.split('\n').length <= 100, true, 'README remains a compact entry point');
|
|
4172
|
+
for (const heading of ['## Tabling', '## Cleanup-aware control', '## Strict ISO',
|
|
4173
|
+
'## Module and definite clause grammar', '## Trealla and Scryer interoperability']) {
|
|
4174
|
+
assertNotIncludes(readme, heading, `README delegates ${heading} to the book`);
|
|
4175
|
+
}
|
|
4164
4176
|
assertEqual(readme.includes('2026-08-23 draft items #73-#76'), false, 'README omits audit-history detail');
|
|
4165
4177
|
assertIncludes(profile, 'Part 1 processor, syntax, semantic, built-in, and arithmetic', 'Why EyeProlog audit state');
|
|
4166
4178
|
},
|
|
@@ -4570,6 +4582,79 @@ check(A, B, C, D, E, F) :-
|
|
|
4570
4582
|
assertIncludes(result.stdout, 'check("ab", "a", "ab", [a - 1, b - 2], 6, "a").\n', 'stdout');
|
|
4571
4583
|
},
|
|
4572
4584
|
},
|
|
4585
|
+
{
|
|
4586
|
+
name: 'shared Scryer/Trealla libraries compose through their common source interfaces',
|
|
4587
|
+
run: () => {
|
|
4588
|
+
const source = `:- use_module(library(charsio), [char_type/2]).
|
|
4589
|
+
:- use_module(library(clpb), [sat/1, labeling/1]).
|
|
4590
|
+
:- use_module(library(gensym), [gensym/2, reset_gensym/1]).
|
|
4591
|
+
:- use_module(library(lists), [transpose/2]).
|
|
4592
|
+
:- use_module(library(ordsets), [ord_union/3]).
|
|
4593
|
+
:- use_module(library(reif), [tfilter/3, (=)/3]).
|
|
4594
|
+
:- use_module(library(ugraphs), [vertices_edges_to_ugraph/3, reachable/3]).
|
|
4595
|
+
:- use_module(library(when), [when/2]).
|
|
4596
|
+
answer(X,Y,U,R,F,W,G,C,T) :-
|
|
4597
|
+
sat(X * ~Y), labeling([X,Y]),
|
|
4598
|
+
ord_union([a,c], [b,c], U),
|
|
4599
|
+
vertices_edges_to_ugraph([a,b,c], [a-b,b-c], Graph), reachable(a, Graph, R),
|
|
4600
|
+
tfilter(=(a), [a,b,a], F),
|
|
4601
|
+
when(nonvar(Ready), W=yes), Ready=now,
|
|
4602
|
+
reset_gensym(shared), gensym(shared, G),
|
|
4603
|
+
char_type(a, upper(C)),
|
|
4604
|
+
transpose([[1,2],[3,4]], T).
|
|
4605
|
+
`;
|
|
4606
|
+
const result = run(source, { goal: 'answer(X,Y,U,R,F,W,G,C,T)' });
|
|
4607
|
+
assertEqual(result.stdout,
|
|
4608
|
+
'answer(1, 0, "abc", "abc", "aa", yes, shared1, "A", [[1, 3], [2, 4]]).\n',
|
|
4609
|
+
'composed common-library answer');
|
|
4610
|
+
},
|
|
4611
|
+
},
|
|
4612
|
+
{
|
|
4613
|
+
name: 'library(format), library(time), random, and UUID compatibility adapters retain reusable Prolog APIs',
|
|
4614
|
+
run: () => {
|
|
4615
|
+
const source = `:- use_module(library(format)).
|
|
4616
|
+
:- use_module(library(random)).
|
|
4617
|
+
:- use_module(library(time)).
|
|
4618
|
+
:- use_module(library(uuid)).
|
|
4619
|
+
answer(A,B,Text,Bytes,Date) :-
|
|
4620
|
+
set_random(seed(7)),
|
|
4621
|
+
random_integer(10,20,A), random_integer(10,20,B),
|
|
4622
|
+
phrase(format_('~w ~q ~d', [f(a),'two words',3]), Text),
|
|
4623
|
+
uuid_string(Bytes, "61ae692e-eaf6-4199-8dd3-9f01db70a20b"),
|
|
4624
|
+
current_time(T), phrase(format_time("%Y-%m-%d", T), Date).
|
|
4625
|
+
`;
|
|
4626
|
+
const result = run(source, { goal: 'answer(A,B,Text,Bytes,Date)' });
|
|
4627
|
+
assertIncludes(result.stdout, 'answer(17, 18, "f(a) \'two words\' 3", [97, 174, 105, 46, 234, 246, 65, 153, 141, 211, 159, 1, 219, 112, 162, 11], "', 'state and conversion output');
|
|
4628
|
+
},
|
|
4629
|
+
},
|
|
4630
|
+
{
|
|
4631
|
+
name: 'library(tabling) accepts the common table directive over automatic tabling',
|
|
4632
|
+
run: () => {
|
|
4633
|
+
const source = `:- use_module(library(tabling)).
|
|
4634
|
+
:- table path/2.
|
|
4635
|
+
edge(a,b). edge(b,c).
|
|
4636
|
+
path(X,Y) :- path(X,Z), edge(Z,Y).
|
|
4637
|
+
path(X,Y) :- edge(X,Y).
|
|
4638
|
+
`;
|
|
4639
|
+
const result = run(source, { goal: 'path(a,Y)' });
|
|
4640
|
+
assertEqual(result.stdout, 'path(a, b).\npath(a, c).\n', 'tabled closure');
|
|
4641
|
+
},
|
|
4642
|
+
},
|
|
4643
|
+
{
|
|
4644
|
+
name: 'library(pio) reads and writes DCG character streams',
|
|
4645
|
+
run: () => {
|
|
4646
|
+
const file = path.join(tmp, 'pio-common.txt');
|
|
4647
|
+
const source = `:- use_module(library(pio)).
|
|
4648
|
+
letters --> [a,b,c].
|
|
4649
|
+
all([C|Cs]) --> [C], !, all(Cs).
|
|
4650
|
+
all([]) --> [].
|
|
4651
|
+
write_file :- phrase_to_file(letters, ${sourceAtom(file)}).
|
|
4652
|
+
read_file(Cs) :- phrase_from_file(all(Cs), ${sourceAtom(file)}).
|
|
4653
|
+
`;
|
|
4654
|
+
assertEqual(run(source, { goal: 'write_file' }).stdout, 'write_file.\n', 'DCG write');
|
|
4655
|
+
assertEqual(run(source, { goal: 'read_file(Cs)' }).stdout, 'read_file("abc").\n', 'DCG read');
|
|
4656
|
+
},
|
|
4657
|
+
},
|
|
4573
4658
|
{
|
|
4574
4659
|
name: 'library(lambda) supports Scryer-style maplist lambdas',
|
|
4575
4660
|
run: () => {
|
|
@@ -5102,7 +5187,7 @@ answer(ok) :-
|
|
|
5102
5187
|
assertEqual(Boolean(registry.get('is', 2)), true, 'ISO is/2 exists');
|
|
5103
5188
|
assertEqual(Boolean(registry.get('append', 3)), false, 'append/3 is not ISO core');
|
|
5104
5189
|
assertEqual(library.eyePrologLibrary, true, 'complete registry marker');
|
|
5105
|
-
assertEqual(library.defs.size,
|
|
5190
|
+
assertEqual(library.defs.size, 161, 'EyeProlog registry contains ISO definitions, cleanup controls, observability extensions, WFS tnot/1, and generic library adapters');
|
|
5106
5191
|
assertEqual(Boolean(registry.get('phrase', 2)), true, 'Part 3 phrase/2 exists');
|
|
5107
5192
|
assertEqual(Boolean(registry.get('phrase', 3)), true, 'Part 3 phrase/3 exists');
|
|
5108
5193
|
assertEqual(registry.get('statistics', 0), null, 'statistics/0 is absent from the ISO registry');
|
|
@@ -5119,10 +5204,10 @@ answer(ok) :-
|
|
|
5119
5204
|
assertEqual(Boolean(library.get('call_cleanup', 2)), true, 'call_cleanup/2 is an EyeProlog cleanup control');
|
|
5120
5205
|
assertEqual(registry.get('setup_call_cleanup', 3), null, 'setup_call_cleanup/3 is absent from the ISO registry');
|
|
5121
5206
|
assertEqual(Boolean(library.get('setup_call_cleanup', 3)), true, 'setup_call_cleanup/3 is an EyeProlog cleanup control');
|
|
5122
|
-
assertEqual(registeredNativeEyePrologLibraryNames().length,
|
|
5123
|
-
assertEqual(eyePrologPortableLibraryIndicators.length,
|
|
5124
|
-
assertEqual(eyePrologInteropLibraryIndicators.length,
|
|
5125
|
-
assertEqual(eyePrologInteropLibraryModules.
|
|
5207
|
+
assertEqual(registeredNativeEyePrologLibraryNames().length, 57, 'public host-supported EyeProlog library count');
|
|
5208
|
+
assertEqual(eyePrologPortableLibraryIndicators.length, 241, 'portable Prolog library count');
|
|
5209
|
+
assertEqual(eyePrologInteropLibraryIndicators.length, 188, 'cross-implementation interop profile count');
|
|
5210
|
+
assertEqual(eyePrologInteropLibraryModules.length, 23, 'common explicit library module profile count');
|
|
5126
5211
|
assertEqual(eyePrologInteropAutoload['member/2'], 'lists', 'member/2 canonical autoload');
|
|
5127
5212
|
assertEqual(eyePrologInteropAutoload['between/3'], 'between', 'between/3 canonical internal autoload');
|
|
5128
5213
|
assertEqual(eyePrologInteropAutoload['call_nth/2'], 'iso_ext', 'call_nth/2 canonical interop autoload');
|
|
@@ -5130,9 +5215,9 @@ answer(ok) :-
|
|
|
5130
5215
|
assertEqual(eyePrologInteropAutoload['time/1'], 'iso_ext', 'time/1 canonical interop autoload');
|
|
5131
5216
|
assertEqual(eyePrologInteropAutoload['.../2'], 'iso_ext', '.../2 canonical interop autoload');
|
|
5132
5217
|
assertEqual(eyePrologInteropAutoload['set_nth0/4'] ?? null, null, 'EyeProlog-only set_nth0/4 is not autoloadable');
|
|
5133
|
-
assertEqual(eyePrologNativeLibraryIndicators.length,
|
|
5218
|
+
assertEqual(eyePrologNativeLibraryIndicators.length, 57, 'host-supported library count');
|
|
5134
5219
|
assertEqual(eyePrologNativeLibraryIndicators.slice(0, 3).join(','), 'call_nth/2,freeze/2,dif/2', 'control and constraint predicates requiring host support');
|
|
5135
|
-
assertEqual(eyePrologLibraryIndicators.length,
|
|
5220
|
+
assertEqual(eyePrologLibraryIndicators.length, 298, 'complete non-ISO EyeProlog library surface');
|
|
5136
5221
|
assertEqual(registry.get('eyeprolog__call_nth', 2), null, 'private call_nth adapter is absent from ISO registry');
|
|
5137
5222
|
assertEqual(Boolean(library.get('eyeprolog__call_nth', 2)), true, 'private call_nth adapter is registered for EyeProlog');
|
|
5138
5223
|
assertEqual(Boolean(library.get('eyeprolog__call_residue_vars', 2)), true, 'private call_residue_vars adapter is registered for EyeProlog');
|
|
@@ -6292,7 +6377,45 @@ function bookBuiltinNames() {
|
|
|
6292
6377
|
|
|
6293
6378
|
function bookEyePrologLibraryNames() {
|
|
6294
6379
|
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
6295
|
-
|
|
6380
|
+
const iso = new Set(registeredBuiltinNames());
|
|
6381
|
+
return documentedBuiltinNames(
|
|
6382
|
+
between(book, '<!-- eyeprolog-library-catalog:start -->', '<!-- eyeprolog-library-catalog:end -->'),
|
|
6383
|
+
2,
|
|
6384
|
+
).filter((indicator) => !iso.has(indicator));
|
|
6385
|
+
}
|
|
6386
|
+
|
|
6387
|
+
function bookLibraryModuleIssues() {
|
|
6388
|
+
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
6389
|
+
const section = between(book, '<!-- eyeprolog-library-catalog:start -->', '<!-- eyeprolog-library-catalog:end -->');
|
|
6390
|
+
const documented = new Map();
|
|
6391
|
+
for (const line of section.split('\n')) {
|
|
6392
|
+
const match = line.match(/^\|\s*`library\(([^)`]+)\)`\s*\|/);
|
|
6393
|
+
if (match == null) continue;
|
|
6394
|
+
documented.set(match[1], documentedBuiltinNames(line, 2));
|
|
6395
|
+
}
|
|
6396
|
+
|
|
6397
|
+
const issues = [];
|
|
6398
|
+
for (const [moduleName, entry] of standardLibrarySources) {
|
|
6399
|
+
const parsed = Program.parse(entry.source);
|
|
6400
|
+
const definition = parsed.modules.get(moduleName);
|
|
6401
|
+
if (definition == null) {
|
|
6402
|
+
issues.push(`missing module declaration for ${moduleName}`);
|
|
6403
|
+
continue;
|
|
6404
|
+
}
|
|
6405
|
+
const actual = [...definition.exports.keys()].sort();
|
|
6406
|
+
const expected = documented.get(moduleName);
|
|
6407
|
+
if (expected == null) {
|
|
6408
|
+
issues.push(`book catalog omits library(${moduleName})`);
|
|
6409
|
+
continue;
|
|
6410
|
+
}
|
|
6411
|
+
if (JSON.stringify(expected) !== JSON.stringify(actual)) {
|
|
6412
|
+
issues.push(`library(${moduleName}) exports: expected ${actual.join(', ')}, documented ${expected.join(', ')}`);
|
|
6413
|
+
}
|
|
6414
|
+
}
|
|
6415
|
+
for (const moduleName of documented.keys()) {
|
|
6416
|
+
if (!standardLibrarySources.has(moduleName)) issues.push(`book catalogs unknown library(${moduleName})`);
|
|
6417
|
+
}
|
|
6418
|
+
return issues.sort();
|
|
6296
6419
|
}
|
|
6297
6420
|
|
|
6298
6421
|
function bookBuiltinSummary() {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -6211,26 +6211,31 @@ so side effects occur in Prolog execution order.
|
|
|
6211
6211
|
|
|
6212
6212
|
### The EyeProlog library
|
|
6213
6213
|
|
|
6214
|
-
EyeProlog exposes **
|
|
6215
|
-
indicators in
|
|
6216
|
-
Prolog clauses** in focused modules under
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6222
|
-
|
|
6223
|
-
|
|
6214
|
+
EyeProlog exposes **298 distinct non-ISO library and normal-extension predicate
|
|
6215
|
+
indicators** in addition to the 129 indicators in its isolated ISO profile.
|
|
6216
|
+
**241 are defined entirely as ordinary Prolog clauses** in focused modules under
|
|
6217
|
+
`src/lib/`; **57 use host support** for control, attributed variables,
|
|
6218
|
+
constraints, or observability. The ISO and library catalogs therefore cover
|
|
6219
|
+
**427 distinct predicate indicators**. Normal-mode controls and observability
|
|
6220
|
+
relations that do not belong to a library, such as `call_cleanup/2`,
|
|
6221
|
+
`setup_call_cleanup/3`, `statistics/0,2`, and `tnot/1`, are documented in their
|
|
6222
|
+
own sections rather than counted as library predicates. `time/1` is additionally
|
|
6223
|
+
registered directly in the normal runtime so Trealla-style timing works at the
|
|
6224
|
+
interactive top level without an import; it is absent from the strict ISO
|
|
6225
|
+
registry.
|
|
6224
6226
|
|
|
6225
6227
|
The sources are `src/lib/aggregate.pl`, `src/lib/arithmetic.pl`,
|
|
6226
6228
|
`src/lib/assoc.pl`, `src/lib/atts.pl`, `src/lib/between.pl`,
|
|
6227
|
-
`src/lib/
|
|
6228
|
-
`src/lib/
|
|
6229
|
-
`src/lib/
|
|
6230
|
-
`src/lib/
|
|
6229
|
+
`src/lib/charsio.pl`, `src/lib/clpb.pl`, `src/lib/clpz.pl`,
|
|
6230
|
+
`src/lib/comparison.pl`, `src/lib/dates.pl`, `src/lib/dcgs.pl`,
|
|
6231
|
+
`src/lib/debug.pl`, `src/lib/dif.pl`, `src/lib/error.pl`,
|
|
6232
|
+
`src/lib/format.pl`, `src/lib/freeze.pl`, `src/lib/gensym.pl`,
|
|
6233
|
+
`src/lib/iso_ext.pl`, `src/lib/lambda.pl`, `src/lib/lists.pl`,
|
|
6234
|
+
`src/lib/ordsets.pl`, `src/lib/pairs.pl`, `src/lib/pio.pl`,
|
|
6231
6235
|
`src/lib/primes.pl`, `src/lib/prologue.pl`, `src/lib/random.pl`,
|
|
6232
|
-
`src/lib/
|
|
6233
|
-
`src/lib/
|
|
6236
|
+
`src/lib/reif.pl`, `src/lib/si.pl`, `src/lib/strings.pl`,
|
|
6237
|
+
`src/lib/tabling.pl`, `src/lib/terms.pl`, `src/lib/time.pl`,
|
|
6238
|
+
`src/lib/ugraphs.pl`, `src/lib/uuid.pl`, and `src/lib/when.pl`. Each declares a same-named module
|
|
6234
6239
|
with `module/2`; there is no catch-all `library(eyeprolog)`. A program imports
|
|
6235
6240
|
only the modules it needs, and
|
|
6236
6241
|
`use_module/2` can select an even smaller indicator list. The Prologue
|
|
@@ -6256,22 +6261,43 @@ between solution branches.
|
|
|
6256
6261
|
|
|
6257
6262
|
<!-- eyeprolog-library-catalog:start -->
|
|
6258
6263
|
|
|
6259
|
-
| Module | Exported predicate indicators |
|
|
6260
|
-
| --- | --- |
|
|
6261
|
-
| `library(aggregate)` | `sumall/3`, `aggregate_min/5`, `aggregate_max/5` |
|
|
6262
|
-
| `library(
|
|
6263
|
-
| `library(
|
|
6264
|
-
| `library(
|
|
6265
|
-
| `library(
|
|
6266
|
-
| `library(
|
|
6267
|
-
|
|
|
6268
|
-
| `library(
|
|
6269
|
-
| `library(
|
|
6270
|
-
| `library(
|
|
6271
|
-
| `library(
|
|
6272
|
-
| `library(
|
|
6273
|
-
| `library(
|
|
6274
|
-
| `library(
|
|
6264
|
+
| Module | Exported predicate indicators | Primary role |
|
|
6265
|
+
| --- | --- | --- |
|
|
6266
|
+
| `library(aggregate)` | `sumall/3`, `aggregate_min/5`, `aggregate_max/5` | Aggregation |
|
|
6267
|
+
| `library(arithmetic)` | `lsb/2`, `msb/2`, `popcount/2` | CLP(Z) arithmetic support |
|
|
6268
|
+
| `library(assoc)` | `empty_assoc/1`, `assoc_to_keys/2`, `assoc_to_list/2`, `assoc_to_values/2`, `del_assoc/4`, `del_max_assoc/4`, `del_min_assoc/4`, `gen_assoc/3`, `get_assoc/3`, `get_assoc/5`, `is_assoc/1`, `list_to_assoc/2`, `map_assoc/2`, `map_assoc/3`, `max_assoc/3`, `min_assoc/3`, `ord_list_to_assoc/2`, `put_assoc/4` | AVL association trees; reused from the shared portable source |
|
|
6269
|
+
| `library(atts)` | `put_atts/2`, `get_atts/2`, `put_attr/3`, `get_attr/3`, `del_attr/2`, `term_attributed_variables/2`, `call_residue_vars/2` | Attributed variables |
|
|
6270
|
+
| `library(between)` | `between/3`, `gen_int/1`, `gen_nat/1`, `numlist/2`, `numlist/3`, `repeat/1` | Integer generation |
|
|
6271
|
+
| `library(charsio)` | `char_type/2`, `get_line_to_chars/3`, `get_n_chars/3`, `get_single_char/1` | Character classification and stream reads |
|
|
6272
|
+
| `library(clpb)` | `labeling/1`, `random_labeling/2`, `sat/1`, `sat_count/2`, `taut/2`, `weighted_maximum/3` | Boolean constraints and BDD reasoning; upstream Prolog source with small state adapters |
|
|
6273
|
+
| `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`, `cumulative/1`, `cumulative/2`, `disjoint2/1`, `element/3`, `automaton/3`, `automaton/8`, `zcompare/3`, `chain/2`, `fd_var/1`, `fd_inf/2`, `fd_sup/2`, `fd_size/2`, `fd_dom/2`, `clpz_t/2`, `#=/3`, `#</3` | Constraint logic programming over integers; the final three indicators support reified compatibility libraries |
|
|
6274
|
+
| `library(comparison)` | `lt/2`, `gt/2`, `le/2`, `ge/2` | Generic comparison |
|
|
6275
|
+
| `library(dates)` | `difference/3` | ISO duration differences |
|
|
6276
|
+
| `library(dcgs)` | `phrase/2`, `phrase/3`, `seq/3`, `seqq/3` | DCG compatibility; `seq/3` and `seqq/3` are declared as `seq //1` and `seqq //1` |
|
|
6277
|
+
| `library(debug)` | `*/1`, `$/1`, `$-/1`, `debug/1`, `debug/3`, `nodebug/1`, `bb_get/2`, `bb_put/2`, `bb_b_put/2`, `bb_global_get/2` | Declarative debug operators and constraint-library blackboards |
|
|
6278
|
+
| `library(dif)` | `dif/2` | Common module facade over native delayed disequality |
|
|
6279
|
+
| `library(error)` | `must_be/2`, `can_be/2`, `instantiation_error/0`, `instantiation_error/1`, `domain_error/2`, `domain_error/3`, `type_error/2`, `type_error/3`, `representation_error/1`, `resource_error/1`, `call_with_error_context/2` | Error checking and construction |
|
|
6280
|
+
| `library(format)` | `format_/4`, `format/2`, `format/3`, `listing/1`, `portray_clause_/3`, `portray_clause/1`, `portray_clause/2` | Formatted DCG text and output; `format_/4` and `portray_clause_/3` are the expanded nonterminals |
|
|
6281
|
+
| `library(freeze)` | `freeze/2` | Delayed goals |
|
|
6282
|
+
| `library(gensym)` | `gensym/2`, `reset_gensym/1` | Process-local generated atoms |
|
|
6283
|
+
| `library(iso_ext)` | `call_nth/2`, `countall/2`, `forall/2`, `succ/2`, `cfor/3`, `findall/4`, `variant/2`, `time/1`, `.../2` | Common ISO extensions |
|
|
6284
|
+
| `library(lambda)` | `^/3`, `^/4`, `^/5`, `^/6`, `^/7`, `^/8`, `^/9`, `^/10`, `\/1`, `\/2`, `\/3`, `\/4`, `\/5`, `\/6`, `\/7`, `\/8`, `+\/2`, `+\/3`, `+\/4`, `+\/5`, `+\/6`, `+\/7`, `+\/8`, `+\/9` | Higher-order lambda notation |
|
|
6285
|
+
| `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`, `list_max/2`, `list_min/2`, `permutation/2`, `transpose/2`, `set_nth0/4`, `take/3`, `drop/3`, `slice/4` | List relations and shared matrix/permutation helpers |
|
|
6286
|
+
| `library(ordsets)` | `is_ordset/1`, `list_to_ord_set/2`, `ord_add_element/3`, `ord_del_element/3`, `ord_disjoint/2`, `ord_empty/1`, `ord_intersect/2`, `ord_intersect/3`, `ord_intersection/2`, `ord_intersection/3`, `ord_intersection/4`, `ord_memberchk/2`, `ord_selectchk/3`, `ord_seteq/2`, `ord_subset/2`, `ord_subtract/3`, `ord_symdiff/3`, `ord_union/2`, `ord_union/3`, `ord_union/4` | Ordered-set relations; reused upstream source |
|
|
6287
|
+
| `library(pairs)` | `pairs_keys_values/3`, `pairs_keys/2`, `pairs_values/2`, `group_pairs_by_key/2`, `map_list_to_pairs/3` | Key-value pair support |
|
|
6288
|
+
| `library(pio)` | `phrase_from_file/2`, `phrase_from_file/3`, `phrase_to_file/2`, `phrase_to_file/3`, `phrase_to_stream/2` | Eager portable DCG file and stream I/O |
|
|
6289
|
+
| `library(primes)` | `smallest_divisor_from/3` | Prime factor support |
|
|
6290
|
+
| `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` | Legacy facade over canonical focused modules |
|
|
6291
|
+
| `library(random)` | `maybe/0`, `random/3`, `random_integer/3`, `set_random/1` | Common mutable-seed interface plus EyeProlog's pure state-threaded generator |
|
|
6292
|
+
| `library(reif)` | `,/3`, `;/3`, `=/3`, `cond_t/3`, `dif/3`, `if_/3`, `memberd_t/3`, `tfilter/3`, `tmember/2`, `tmember_t/3`, `tpartition/4` | Reified conditions and list filtering; reused upstream source |
|
|
6293
|
+
| `library(si)` | `atom_si/1`, `integer_si/1`, `atomic_si/1`, `list_si/1`, `character_si/1`, `term_si/1`, `chars_si/1`, `dif_si/2`, `not_si/1`, `when_si/2` | Sufficient-instantiation checks used by CLP(Z) |
|
|
6294
|
+
| `library(strings)` | `matches/3`, `split/3`, `replace/4`, `lowercase/2`, `uppercase/2`, `trim/2`, `number_string/2`, `atom_string/2`, `term_string/2`, `string_concat/3`, `contains/2`, `matches/2`, `join/3`, `substring/4` | Text relations |
|
|
6295
|
+
| `library(tabling)` | `abolish_all_tables/0`, `start_tabling/2` | Common explicit syntax over automatic recursive tabling |
|
|
6296
|
+
| `library(terms)` | `numbervars/3`, `copy_term_nat/2` | Term operations used by bundled libraries |
|
|
6297
|
+
| `library(time)` | `current_time/1`, `format_time/4` | Clock timestamps and the expanded `format_time//2` nonterminal |
|
|
6298
|
+
| `library(ugraphs)` | `add_edges/3`, `add_vertices/3`, `complement/2`, `compose/3`, `connect_ugraph/3`, `del_edges/3`, `del_vertices/3`, `edges/2`, `neighbors/3`, `neighbours/3`, `reachable/3`, `top_sort/2`, `top_sort/3`, `transitive_closure/2`, `transpose_ugraph/2`, `ugraph_union/3`, `vertices/2`, `vertices_edges_to_ugraph/3` | Directed graph relations; reused upstream source |
|
|
6299
|
+
| `library(uuid)` | `uuid/3`, `uuid_string/2`, `uuidv4/1`, `uuidv4_string/1` | Common UUID byte/string conversion and generation plus pure state threading |
|
|
6300
|
+
| `library(when)` | `when/2` | Shared delayed-condition interface over attributed variables |
|
|
6275
6301
|
|
|
6276
6302
|
<!-- eyeprolog-library-catalog:end -->
|
|
6277
6303
|
|
|
@@ -6293,26 +6319,40 @@ adapter. In this section, **portable** refers to source portability between
|
|
|
6293
6319
|
Prolog systems, not merely to the language in which a predicate happens to be
|
|
6294
6320
|
implemented.
|
|
6295
6321
|
|
|
6296
|
-
The
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6322
|
+
The shared module-name profile is the overlap of the Scryer `src/lib` and
|
|
6323
|
+
Trealla `library` layouts that EyeProlog can implement without pretending an
|
|
6324
|
+
engine-specific service exists. It includes `arithmetic`, `assoc`, `atts`,
|
|
6325
|
+
`charsio`, `clpb`, `clpz`, `debug`, `dif`, `format`, `freeze`, `gensym`,
|
|
6326
|
+
`iso_ext`, `lambda`, `lists`, `ordsets`, `pio`, `random`, `reif`, `tabling`,
|
|
6327
|
+
`time`, `ugraphs`, `uuid`, and `when`. The predicate profile is narrower than
|
|
6328
|
+
the union of their exports: for example, EyeProlog's explicit-state `random/3`
|
|
6329
|
+
and `uuid/3` remain useful extensions rather than shared interfaces.
|
|
6330
|
+
|
|
6331
|
+
Source reuse is preferred over translation. `clpb.pl`, `ordsets.pl`,
|
|
6332
|
+
`reif.pl`, and `ugraphs.pl` retain the upstream Prolog algorithms and license
|
|
6333
|
+
headers; `assoc.pl` uses the complete upstream AVL implementation. `gensym.pl`
|
|
6334
|
+
and `when.pl` keep the same algorithms with small blackboard and parser-safe
|
|
6335
|
+
closure adaptations. `dif.pl`, `tabling.pl`, and the clock portion of
|
|
6336
|
+
`time.pl` are thin facades over EyeProlog runtime facilities. `charsio.pl` and
|
|
6337
|
+
`pio.pl` provide the common character and eager DCG I/O surfaces. The
|
|
6338
|
+
[portable library overlap example](https://github.com/eyereasoner/eyeprolog/blob/main/examples/portable-library-overlap.pl)
|
|
6339
|
+
composes Boolean constraints, ordered sets, graphs, reification, delayed goals,
|
|
6340
|
+
generated names, character conversion, transposition, and explicit table
|
|
6341
|
+
syntax in one checked program.
|
|
6342
|
+
|
|
6343
|
+
Two matching upstream basenames are intentionally not exposed as portable
|
|
6344
|
+
libraries. The two `builtins.pl` files are private engine facades and have no
|
|
6345
|
+
shared public predicate interface. `sockets.pl` requires a native networking
|
|
6346
|
+
event loop and host socket objects; EyeProlog does not provide a source-only
|
|
6347
|
+
facade that would accept calls and then fail at runtime. Rational-only
|
|
6348
|
+
`library(arithmetic)` predicates are likewise omitted until rational numbers
|
|
6349
|
+
are processor values.
|
|
6311
6350
|
|
|
6312
6351
|
For `library(lists)`, the current interop predicate set is `member/2`,
|
|
6313
6352
|
`memberchk/2`, `select/3`, `append/2-3`, `last/2`, `same_length/2`,
|
|
6314
6353
|
`nth0/3-4`, `nth1/3-4`, `reverse/2`, `length/2`, `maplist/2-8`,
|
|
6315
|
-
`foldl/4-6`, `sum_list/2`,
|
|
6354
|
+
`foldl/4-6`, `sum_list/2`, `list_to_set/2`, `list_max/2`, `list_min/2`,
|
|
6355
|
+
`permutation/2`, and `transpose/2`. Other exports from the same
|
|
6316
6356
|
module, such as `min_list/2`, `max_list/2`, `set_nth0/4`, `take/3`, `drop/3`,
|
|
6317
6357
|
and `slice/4`, remain available to EyeProlog programs but lie outside this
|
|
6318
6358
|
conservative cross-engine subset.
|
|
@@ -6450,11 +6490,29 @@ list; and `variant/2` recognizes terms equal up to variable renaming.
|
|
|
6450
6490
|
all belong to the conservative interop subset merely because they share the
|
|
6451
6491
|
`iso_ext` module.
|
|
6452
6492
|
|
|
6453
|
-
`
|
|
6454
|
-
|
|
6455
|
-
|
|
6456
|
-
|
|
6457
|
-
|
|
6493
|
+
`library(format)` accepts the common `format/[2,3]`, `format_//2`,
|
|
6494
|
+
`portray_clause/[1,2]`, `portray_clause_//1`, and `listing/1` interfaces. Its
|
|
6495
|
+
portable formatter currently implements literal text, `~~`, `~n`, `~w`, `~q`,
|
|
6496
|
+
`~a`, and `~d`; controls for field widths and floating-point presentation are
|
|
6497
|
+
not yet part of EyeProlog's compatibility subset. `library(pio)` eagerly reads
|
|
6498
|
+
or materializes a DCG character list around ISO streams. It preserves the
|
|
6499
|
+
declarative grammar interface, but unlike Scryer's lazy list implementation it
|
|
6500
|
+
does not defer file reads.
|
|
6501
|
+
|
|
6502
|
+
`library(tabling)` accepts `:- table Name/Arity.` and the common
|
|
6503
|
+
`start_tabling/2` and `abolish_all_tables/0` predicates. Recursive user
|
|
6504
|
+
predicates are already tabled by EyeProlog's program analysis, so the directive
|
|
6505
|
+
is a compatible declaration rather than a second tabling engine.
|
|
6506
|
+
`library(time)` returns a timestamp association list from the local clock;
|
|
6507
|
+
`format_time//2` supports the documented year, month, day, time, month-name,
|
|
6508
|
+
weekday-name, and day-of-year specifiers.
|
|
6509
|
+
|
|
6510
|
+
`uuidv4/1`, `uuidv4_string/1`, and `uuid_string/2` provide the common UUID byte
|
|
6511
|
+
list and character-list interface. `uuid(+Seed0,-UUID,-Seed)` remains an
|
|
6512
|
+
EyeProlog extension that creates a version 4 UUID atom using pure `random/3`.
|
|
6513
|
+
Passing the returned seed to the next call produces the next UUID; restarting
|
|
6514
|
+
with the same integer seed reproduces the same sequence. `set_random/1` controls
|
|
6515
|
+
the common stateful generator used by `uuidv4/1`.
|
|
6458
6516
|
|
|
6459
6517
|
On the command line, a program can state its library dependencies explicitly:
|
|
6460
6518
|
|
|
@@ -7157,7 +7215,7 @@ Review questions:
|
|
|
7157
7215
|
</figure>
|
|
7158
7216
|
|
|
7159
7217
|
The [examples directory](https://github.com/eyereasoner/eyeprolog/tree/main/examples/) is the book's executable companion. The
|
|
7160
|
-
top-level directory contains **
|
|
7218
|
+
top-level directory contains **214 self-contained runnable programs**. Every
|
|
7161
7219
|
source program has an exact answer file under
|
|
7162
7220
|
[examples/output](https://github.com/eyereasoner/eyeprolog/tree/main/examples/output/), and **61 selected programs** have a checked
|
|
7163
7221
|
explanation under [examples/proof](https://github.com/eyereasoner/eyeprolog/tree/main/examples/proof/). The thematic tables below link every top-level program and open the program
|
|
@@ -7222,6 +7280,7 @@ mode at a time.
|
|
|
7222
7280
|
| [ISO extension pipeline audit](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-extension-pipeline-audit.pl) | A bounded pipeline audit composing every `library(iso_ext)` relation: nested counting, universal validation, successor generation, difference-list collection, and schema comparison modulo variable names. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/iso-extension-pipeline-audit.pl) |
|
|
7223
7281
|
| [ISO extensions](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-extensions.pl) | Common control, collection, integer, and term-variant extensions from `library(iso_ext)`. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/iso-extensions.pl) |
|
|
7224
7282
|
| [Operators](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-operators.pl) | Custom syntax, standard term order, and operator-table inspection. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/iso-operators.pl) · [proof](https://github.com/eyereasoner/eyeprolog/blob/main/examples/proof/iso-operators.pl) |
|
|
7283
|
+
| [Portable library overlap](https://github.com/eyereasoner/eyeprolog/blob/main/examples/portable-library-overlap.pl) | Shared Scryer/Trealla interfaces for CLP(B), ordered sets, graphs, reification, delayed goals, generated names, character conversion, matrix transposition, and explicit table syntax. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/portable-library-overlap.pl) |
|
|
7225
7284
|
| [Reflective terms](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-reflective-terms.pl) | Term shape, construction, copying, variables, identity, and standard order. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/iso-reflective-terms.pl) |
|
|
7226
7285
|
| [Term I/O](https://github.com/eyereasoner/eyeprolog/blob/main/examples/iso-term-io.pl) | Text-stream lifecycle, canonical writing, reading, metadata, and end state. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/iso-term-io.pl) |
|
|
7227
7286
|
| [Term Tools](https://github.com/eyereasoner/eyeprolog/blob/main/examples/term-tools.pl) | Term-tool builtins for inspecting, constructing, rendering, and validating structured terms. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/term-tools.pl) · [proof](https://github.com/eyereasoner/eyeprolog/blob/main/examples/proof/term-tools.pl) |
|