eyeprolog 1.5.16 → 1.5.18
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/examples/book/README.md +9 -9
- package/examples/book/chapter-39/{02-answer.pl → 01-answer.pl} +1 -1
- package/examples/book/chapter-39/{01-program.pl → 07-program.pl} +1 -1
- package/package.json +1 -1
- package/test/run-regression.mjs +83 -26
- package/the-art-of-eyeprolog.md +2703 -2800
- package/tools/generate-predicate-reference.mjs +9 -13
- /package/examples/book/chapter-39/{03-answer-2.pl → 02-answer-2.pl} +0 -0
- /package/examples/book/chapter-39/{04-answer-3.pl → 03-answer-3.pl} +0 -0
- /package/examples/book/chapter-39/{05-cost.pl → 04-cost.pl} +0 -0
- /package/examples/book/chapter-39/{06-message.pl → 05-message.pl} +0 -0
- /package/examples/book/chapter-39/{07-task.pl → 06-task.pl} +0 -0
package/examples/book/README.md
CHANGED
|
@@ -236,15 +236,15 @@ npm run generate
|
|
|
236
236
|
- [01-city.pl](chapter-38/01-city.pl)
|
|
237
237
|
- [02-look_ahead.pl](chapter-38/02-look_ahead.pl) — Part 3-oriented definite clause grammars
|
|
238
238
|
|
|
239
|
-
## Chapter 39:
|
|
240
|
-
|
|
241
|
-
- [01-
|
|
242
|
-
- [02-answer.pl](chapter-39/02-answer.pl)
|
|
243
|
-
- [03-answer-
|
|
244
|
-
- [04-
|
|
245
|
-
- [05-
|
|
246
|
-
- [06-
|
|
247
|
-
- [07-
|
|
239
|
+
## Chapter 39: Predicate reference
|
|
240
|
+
|
|
241
|
+
- [01-answer.pl](chapter-39/01-answer.pl) — Library relations by programming role
|
|
242
|
+
- [02-answer-2.pl](chapter-39/02-answer-2.pl)
|
|
243
|
+
- [03-answer-3.pl](chapter-39/03-answer-3.pl)
|
|
244
|
+
- [04-cost.pl](chapter-39/04-cost.pl)
|
|
245
|
+
- [05-message.pl](chapter-39/05-message.pl)
|
|
246
|
+
- [06-task.pl](chapter-39/06-task.pl)
|
|
247
|
+
- [07-program.pl](chapter-39/07-program.pl) — Specialized library implementation notes
|
|
248
248
|
|
|
249
249
|
## Chapter 40: Running EyeProlog: command line and corpus
|
|
250
250
|
|
package/package.json
CHANGED
package/test/run-regression.mjs
CHANGED
|
@@ -4797,13 +4797,71 @@ function documentationSyncCases() {
|
|
|
4797
4797
|
|
|
4798
4798
|
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
4799
4799
|
const section = between(book, '<!-- eyeprolog-predicate-reference:start -->', '<!-- eyeprolog-predicate-reference:end -->');
|
|
4800
|
-
assertEqual(section.split('\n').some((line) => line.trimStart().startsWith('|')), false, 'predicate reference avoids
|
|
4801
|
-
assertEqual((section.match(/^- \*\*`/gm) ?? []).length, 518, 'one
|
|
4802
|
-
assertEqual((section.match(/<a id="predicate-reference-\d{4}"><\/a>/g) ?? []).length, 518, 'one explicit
|
|
4800
|
+
assertEqual(section.split('\n').some((line) => line.trimStart().startsWith('|')), false, 'predicate reference avoids wide table markup');
|
|
4801
|
+
assertEqual((section.match(/^- \*\*`/gm) ?? []).length, 518, 'one reference entry per predicate');
|
|
4802
|
+
assertEqual((section.match(/<a id="predicate-reference-\d{4}"><\/a>/g) ?? []).length, 518, 'one explicit anchor per predicate');
|
|
4803
4803
|
assertEqual((section.match(/\]\(#predicate-reference-\d{4}\)/g) ?? []).length, 518, 'one direct index link per predicate');
|
|
4804
4804
|
assertNotIncludes(section, '[Symbols](#predicate-reference-symbols)', 'predicate index does not rely on renderer-generated group anchors');
|
|
4805
|
-
|
|
4806
|
-
|
|
4805
|
+
|
|
4806
|
+
const chapter = between(book, '## 39. Predicate reference', '## 40. Running EyeProlog: command line and corpus');
|
|
4807
|
+
assertEqual(chapter.split('\n').some((line) => line.trimStart().startsWith('|')), false, 'Chapter 39 avoids wide table markup');
|
|
4808
|
+
for (const backstage of [
|
|
4809
|
+
'stacked layout',
|
|
4810
|
+
'Markdown tables',
|
|
4811
|
+
'horizontal scrollbars',
|
|
4812
|
+
'horizontal scrolling',
|
|
4813
|
+
'documentation test',
|
|
4814
|
+
'documentation regression',
|
|
4815
|
+
'stable numeric IDs',
|
|
4816
|
+
'generated reference',
|
|
4817
|
+
'Read the chapter in that order',
|
|
4818
|
+
'final generated section',
|
|
4819
|
+
]) assertNotIncludes(chapter, backstage, `Chapter 39 avoids editorial/process prose: ${backstage}`);
|
|
4820
|
+
const orderedHeadings = [
|
|
4821
|
+
'### Notation and conventions',
|
|
4822
|
+
'### Core registry',
|
|
4823
|
+
'### Normal-mode extensions',
|
|
4824
|
+
'### Bundled libraries',
|
|
4825
|
+
'### Library relations by programming role',
|
|
4826
|
+
'### Interoperability, autoloading, and portability',
|
|
4827
|
+
'### Specialized library implementation notes',
|
|
4828
|
+
'### Complete predicate indicator reference',
|
|
4829
|
+
];
|
|
4830
|
+
let previous = -1;
|
|
4831
|
+
for (const heading of orderedHeadings) {
|
|
4832
|
+
const position = chapter.indexOf(heading);
|
|
4833
|
+
assertEqual(position > previous, true, `Chapter 39 section order: ${heading}`);
|
|
4834
|
+
previous = position;
|
|
4835
|
+
}
|
|
4836
|
+
},
|
|
4837
|
+
},
|
|
4838
|
+
{
|
|
4839
|
+
name: 'book keeps editorial and build mechanics out of reader-facing prose',
|
|
4840
|
+
run: () => {
|
|
4841
|
+
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
4842
|
+
for (const backstage of [
|
|
4843
|
+
'stacked layout',
|
|
4844
|
+
'Markdown tables',
|
|
4845
|
+
'horizontal scrollbars',
|
|
4846
|
+
'horizontal scrolling',
|
|
4847
|
+
'documentation test',
|
|
4848
|
+
'documentation regression',
|
|
4849
|
+
'stable numeric IDs',
|
|
4850
|
+
'generated reference',
|
|
4851
|
+
'final generated section',
|
|
4852
|
+
'Read the chapter in that order',
|
|
4853
|
+
'after editing the book',
|
|
4854
|
+
'should be rebuilt with `npm run generate`',
|
|
4855
|
+
'Keeping these details here',
|
|
4856
|
+
'# Part XII — Development note',
|
|
4857
|
+
'## 46. AI-assisted editing',
|
|
4858
|
+
'release gate',
|
|
4859
|
+
'release-facing',
|
|
4860
|
+
'# Refresh the vendored TU Wien WG17 inventory',
|
|
4861
|
+
'the tables in this chapter',
|
|
4862
|
+
'The generated [`examples/book/`',
|
|
4863
|
+
]) assertNotIncludes(book, backstage, `book avoids backstage prose: ${backstage}`);
|
|
4864
|
+
assertIncludes(book, 'Chapters are numbered continuously across eleven parts, from Chapter 1 to Chapter 45.', 'reader-facing chapter count');
|
|
4807
4865
|
},
|
|
4808
4866
|
},
|
|
4809
4867
|
{
|
|
@@ -4825,7 +4883,7 @@ ${profile}`;
|
|
|
4825
4883
|
assertIncludes(book, 'including recursive calls, use depth-first resolution unless the source', 'ordinary recursion is depth-first');
|
|
4826
4884
|
assertIncludes(book, 'explicitly declares `:- table p/n.`', 'tabling is explicit');
|
|
4827
4885
|
assertIncludes(book, 'The autoload index covers every', 'generic bundled-library autoload');
|
|
4828
|
-
assertIncludes(book, 'interactive top-level query
|
|
4886
|
+
assertIncludes(book, 'interactive top-level query autoloads its canonical bundled provider', 'REPL autoload');
|
|
4829
4887
|
assertIncludes(book, 'Autoloading therefore supplies', 'autoload syntax boundary');
|
|
4830
4888
|
assertIncludes(book, 'Residual constraints are part of the displayed answer even when', 'top-level hidden residuals');
|
|
4831
4889
|
assertIncludes(book, 'EyeProlog normal mode also accepts `:+`', 'Eyelet forward-rule extension');
|
|
@@ -7564,7 +7622,7 @@ function bookReferenceDocumentationIssues() {
|
|
|
7564
7622
|
if (book.includes('EyeProlog does not perform it.')) {
|
|
7565
7623
|
issues.push('book contradicts implementation occurs-check behavior');
|
|
7566
7624
|
}
|
|
7567
|
-
for (const heading of ['## 38. Language and ISO profile', '## 39.
|
|
7625
|
+
for (const heading of ['## 38. Language and ISO profile', '## 39. Predicate reference', '## 40. Running EyeProlog: command line and corpus']) {
|
|
7568
7626
|
if (!book.includes(heading)) issues.push(`book is missing ${heading}`);
|
|
7569
7627
|
}
|
|
7570
7628
|
if (!guide.includes('[*The Art of EyeProlog*](../../the-art-of-eyeprolog.md) is the reference')) {
|
|
@@ -7811,26 +7869,31 @@ function registeredBuiltinSummary() {
|
|
|
7811
7869
|
|
|
7812
7870
|
function bookBuiltinNames() {
|
|
7813
7871
|
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
7814
|
-
return documentedBuiltinNames(
|
|
7872
|
+
return documentedBuiltinNames(
|
|
7873
|
+
between(book, '<!-- eyeprolog-core-catalog:start -->', '<!-- eyeprolog-core-catalog:end -->'),
|
|
7874
|
+
);
|
|
7815
7875
|
}
|
|
7816
7876
|
|
|
7817
7877
|
function bookEyePrologLibraryNames() {
|
|
7818
7878
|
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
7819
7879
|
const iso = new Set(registeredBuiltinNames());
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7880
|
+
const section = between(book, '<!-- eyeprolog-library-catalog:start -->', '<!-- eyeprolog-library-catalog:end -->');
|
|
7881
|
+
const exports = section.split('\n')
|
|
7882
|
+
.filter((line) => line.trimStart().startsWith('**Exports:**'))
|
|
7883
|
+
.join('\n');
|
|
7884
|
+
return documentedBuiltinNames(exports).filter((indicator) => !iso.has(indicator));
|
|
7824
7885
|
}
|
|
7825
7886
|
|
|
7826
7887
|
function bookLibraryModuleIssues() {
|
|
7827
7888
|
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
7828
7889
|
const section = between(book, '<!-- eyeprolog-library-catalog:start -->', '<!-- eyeprolog-library-catalog:end -->');
|
|
7829
7890
|
const documented = new Map();
|
|
7830
|
-
|
|
7831
|
-
|
|
7891
|
+
const lines = section.split('\n');
|
|
7892
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7893
|
+
const match = lines[i].match(/^- \*\*`library\(([^)`]+)\)`\*\*/);
|
|
7832
7894
|
if (match == null) continue;
|
|
7833
|
-
|
|
7895
|
+
const exports = lines[i + 1] ?? '';
|
|
7896
|
+
documented.set(match[1], documentedBuiltinNames(exports));
|
|
7834
7897
|
}
|
|
7835
7898
|
|
|
7836
7899
|
const issues = [];
|
|
@@ -7864,18 +7927,12 @@ function bookBuiltinSummary() {
|
|
|
7864
7927
|
return { entries: Number(match[1]), names: Number(match[2]) };
|
|
7865
7928
|
}
|
|
7866
7929
|
|
|
7867
|
-
function documentedBuiltinNames(section
|
|
7930
|
+
function documentedBuiltinNames(section) {
|
|
7868
7931
|
const names = [];
|
|
7869
|
-
for (const
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
const arity = match[2].trim() === '' ? 0 : match[2].split(',').length;
|
|
7874
|
-
names.push(`${match[1]}/${arity}`);
|
|
7875
|
-
}
|
|
7876
|
-
for (const match of catalogCell.matchAll(/`([^`\s]+)\/(\d+)`/g)) {
|
|
7877
|
-
names.push(`${match[1]}/${match[2]}`);
|
|
7878
|
-
}
|
|
7932
|
+
for (const match of section.matchAll(/`([^`]+)`/g)) {
|
|
7933
|
+
const indicator = match[1].match(/^(.+)\/(\d+)$/);
|
|
7934
|
+
if (indicator == null) continue;
|
|
7935
|
+
names.push(`${indicator[1]}/${indicator[2]}`);
|
|
7879
7936
|
}
|
|
7880
7937
|
return [...new Set(names)].sort();
|
|
7881
7938
|
}
|