eyeprolog 1.2.16 → 1.2.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/conformance-report.md +2 -2
- package/package.json +1 -1
- package/src/iso.js +9 -1
- package/src/repl.js +9 -2
- package/test/conformance/README.md +1 -1
- package/test/conformance/cases/iso/number_chars_minus_line_comment.pl +8 -0
- package/test/conformance/expected/iso/number_chars_minus_line_comment.pl +1 -0
- package/test/fixtures/number_chars_cont_quad.pl +3 -0
- package/test/run-regression.mjs +83 -3
- package/the-art-of-eyeprolog.md +15 -9
package/conformance-report.md
CHANGED
|
@@ -11,7 +11,7 @@ This report summarizes the file-based conformance corpus under `test/conformance
|
|
|
11
11
|
| builtins | 11 | 0 | 0 | 0 | 11 |
|
|
12
12
|
| context | 11 | 0 | 0 | 0 | 11 |
|
|
13
13
|
| control | 15 | 0 | 0 | 0 | 15 |
|
|
14
|
-
| iso |
|
|
14
|
+
| iso | 168 | 218 | 0 | 0 | 386 |
|
|
15
15
|
| lists | 52 | 3 | 0 | 0 | 55 |
|
|
16
16
|
| modules | 2 | 0 | 0 | 0 | 2 |
|
|
17
17
|
| negation | 8 | 0 | 19 | 0 | 27 |
|
|
@@ -23,4 +23,4 @@ This report summarizes the file-based conformance corpus under `test/conformance
|
|
|
23
23
|
| terms | 26 | 3 | 0 | 0 | 29 |
|
|
24
24
|
| unification | 18 | 0 | 0 | 0 | 18 |
|
|
25
25
|
| variables | 16 | 9 | 0 | 0 | 25 |
|
|
26
|
-
| **Total** | **
|
|
26
|
+
| **Total** | **483** | **269** | **19** | **21** | **792** |
|
package/package.json
CHANGED
package/src/iso.js
CHANGED
|
@@ -1556,7 +1556,15 @@ function parseIsoNumber(text) {
|
|
|
1556
1556
|
let sign = '';
|
|
1557
1557
|
|
|
1558
1558
|
if (text[position] === '-') {
|
|
1559
|
-
|
|
1559
|
+
const next = text[position + 1] ?? '';
|
|
1560
|
+
// Every token class may carry leading layout (6.4). Thus a negative
|
|
1561
|
+
// number may have layout between the name `-` and its numeric token. A
|
|
1562
|
+
// `%...\n` comment can start immediately after `-` because `%` cannot
|
|
1563
|
+
// continue a graphic name token. In contrast `/*...*/` cannot start
|
|
1564
|
+
// there without separating layout: `/` *can* continue the graphic token,
|
|
1565
|
+
// and the eager-consumer rule therefore keeps `-/**/1` ill-formed (the
|
|
1566
|
+
// number_chars continuation corpus case 24).
|
|
1567
|
+
if (/[\u0009-\u000d\u0020]/.test(next) || next === '%') {
|
|
1560
1568
|
position = skipNumberLayout(text, position + 1);
|
|
1561
1569
|
sign = '-';
|
|
1562
1570
|
}
|
package/src/repl.js
CHANGED
|
@@ -9,7 +9,7 @@ const ANSWER_HELP = `
|
|
|
9
9
|
SPACE, "n" or ";": next solution, if any
|
|
10
10
|
RETURN or ".": stop enumeration
|
|
11
11
|
"a": enumerate all solutions
|
|
12
|
-
"f": enumerate the next 5 solutions
|
|
12
|
+
"f": enumerate through the next group of 5 solutions
|
|
13
13
|
"h": display this help message
|
|
14
14
|
"w": write terms without depth limit
|
|
15
15
|
"p": print terms with depth limit
|
|
@@ -486,11 +486,13 @@ async function solveQuery(engine, state, goal, reader, output) {
|
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
let automatic = 0;
|
|
489
|
+
let answersShown = 0;
|
|
489
490
|
let firstAnswer = true;
|
|
490
491
|
while (!current.result.done) {
|
|
491
492
|
const next = pullSolution(solver, solutions, reader);
|
|
492
493
|
output.write(current.output);
|
|
493
494
|
output.write(`${firstAnswer ? ' ' : ''}${formatAnswer(engine, state, variables, current.result.value)}`);
|
|
495
|
+
answersShown++;
|
|
494
496
|
firstAnswer = false;
|
|
495
497
|
if (!next.error && next.result.done) {
|
|
496
498
|
output.write('.\n');
|
|
@@ -516,7 +518,12 @@ async function solveQuery(engine, state, goal, reader, output) {
|
|
|
516
518
|
break;
|
|
517
519
|
}
|
|
518
520
|
if (control === 'f') {
|
|
519
|
-
|
|
521
|
+
// `f` groups leaf answers in blocks of five, rather than merely
|
|
522
|
+
// adding five more answers after whatever the user has already
|
|
523
|
+
// inspected. Stop for control again at the next 5-answer boundary.
|
|
524
|
+
const remainder = answersShown % 5;
|
|
525
|
+
const answersToBoundary = remainder === 0 ? 5 : 5 - remainder;
|
|
526
|
+
automatic = answersToBoundary - 1;
|
|
520
527
|
break;
|
|
521
528
|
}
|
|
522
529
|
if (control === 'w' || control === 'p') {
|
|
@@ -102,7 +102,7 @@ Selected cases are adapted from the ISO and standard-core suites of Logtalk,
|
|
|
102
102
|
Scryer Prolog, Trealla Prolog, and SWI-Prolog. Their upstream identifiers and licenses
|
|
103
103
|
are recorded in [THIRD_PARTY.md](THIRD_PARTY.md).
|
|
104
104
|
|
|
105
|
-
The corpus has
|
|
105
|
+
The corpus has 386 cases in `iso/` and 792 file-based conformance cases in
|
|
106
106
|
total. The generated `conformance-report.md` is the authoritative source for
|
|
107
107
|
current category totals. Together with regression, documentation-sync, API,
|
|
108
108
|
example, and book-example checks, `npm test` is the release gate.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
% ISO 13211-1 8.16.7/8.16.8 with 6.3.1 and token layout from 6.4.
|
|
2
|
+
%% goal: answer(X0, X1, X2, X3)
|
|
3
|
+
|
|
4
|
+
answer(CharZero, CharOne, CodeZero, CodeOne) :-
|
|
5
|
+
number_chars(CharZero, "-%\n0"),
|
|
6
|
+
number_chars(CharOne, "-% comment\n1"),
|
|
7
|
+
number_codes(CodeZero, [45, 37, 10, 48]),
|
|
8
|
+
number_codes(CodeOne, [45, 37, 32, 99, 111, 109, 109, 101, 110, 116, 10, 49]).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
answer(0, -1, 0, -1).
|
package/test/run-regression.mjs
CHANGED
|
@@ -491,13 +491,51 @@ c4 ?- call((!;1)).
|
|
|
491
491
|
run: () => {
|
|
492
492
|
const filename = path.join(testRoot, 'fixtures', 'number_chars_cont_quad.pl');
|
|
493
493
|
const source = fs.readFileSync(filename, 'utf8');
|
|
494
|
+
const numbered = new Set([...source.matchAll(/^(\d+)\s+\?-/gm)].map((match) => Number(match[1])));
|
|
495
|
+
assertEqual(numbered.size, 74, 'numbered case total');
|
|
496
|
+
for (let id = 1; id <= 74; id++) {
|
|
497
|
+
if (!numbered.has(id)) throw new Error(`number_chars continuation case #${id} is missing`);
|
|
498
|
+
}
|
|
494
499
|
const result = publicApi.runQuads(Program.parseSources([{
|
|
495
500
|
text: source,
|
|
496
501
|
filename,
|
|
497
502
|
}]));
|
|
498
|
-
assertEqual(result.total,
|
|
499
|
-
assertEqual(result.passed,
|
|
500
|
-
assertEqual(result.stdout, 'quads:
|
|
503
|
+
assertEqual(result.total, 78, 'answer-description total');
|
|
504
|
+
assertEqual(result.passed, 78, 'answer-description passed');
|
|
505
|
+
assertEqual(result.stdout, 'quads: 78 run, 78 passed, 0 failed.\n', 'quad report');
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
name: 'number conversion accepts line-comment layout after a minus token',
|
|
510
|
+
run: () => {
|
|
511
|
+
const source = String.raw`
|
|
512
|
+
?- number_chars(N,"-%\n0").
|
|
513
|
+
N = 0.
|
|
514
|
+
?- number_chars(N,"-% comment\n1").
|
|
515
|
+
N = -1.
|
|
516
|
+
?- number_codes(N,[45,37,10,48]).
|
|
517
|
+
N = 0.
|
|
518
|
+
?- number_codes(N,[45,37,32,99,111,109,109,101,110,116,10,49]).
|
|
519
|
+
N = -1.
|
|
520
|
+
`;
|
|
521
|
+
const result = publicApi.runQuads(source);
|
|
522
|
+
assertEqual(result.total, 4, 'quad total');
|
|
523
|
+
assertEqual(result.passed, 4, 'quad passed');
|
|
524
|
+
assertEqual(result.stdout, 'quads: 4 run, 4 passed, 0 failed.\n', 'quad report');
|
|
525
|
+
|
|
526
|
+
// Keep the eager-consumer distinction from continuation case #24:
|
|
527
|
+
// an adjacent bracketed comment can be consumed as part of a graphic
|
|
528
|
+
// token after `-`, so it is not equivalent to the `%` line comment.
|
|
529
|
+
for (const goal of ['number_chars(N,"-/**/1")', 'number_codes(N,[45,47,42,42,47,49])']) {
|
|
530
|
+
let caught = null;
|
|
531
|
+
try {
|
|
532
|
+
publicApi.run('', { goal });
|
|
533
|
+
} catch (error) {
|
|
534
|
+
caught = error;
|
|
535
|
+
}
|
|
536
|
+
if (caught == null) throw new Error(`${goal} should throw`);
|
|
537
|
+
assertIncludes(String(caught?.message ?? caught), 'syntax_error(number)', goal);
|
|
538
|
+
}
|
|
501
539
|
},
|
|
502
540
|
},
|
|
503
541
|
{
|
|
@@ -752,6 +790,48 @@ c4 ?- call((!;1)).
|
|
|
752
790
|
assertEqual(result.stderr, '', 'stderr');
|
|
753
791
|
},
|
|
754
792
|
},
|
|
793
|
+
{
|
|
794
|
+
name: 'REPL f stops at five-answer boundaries instead of adding five answers',
|
|
795
|
+
run: () => {
|
|
796
|
+
const result = runCli([], {
|
|
797
|
+
input:
|
|
798
|
+
'use_module(library(prologue), [between/3]).\n' +
|
|
799
|
+
'between(0,11,I).\nf\n\n' +
|
|
800
|
+
'between(0,11,J).\n;\n;\nf\n\n' +
|
|
801
|
+
'between(0,11,K).\nf\nf\n\n' +
|
|
802
|
+
'halt.\n',
|
|
803
|
+
});
|
|
804
|
+
assertEqual(result.status, 0, 'exit status');
|
|
805
|
+
assertEqual(result.stdout,
|
|
806
|
+
'?- true.\n' +
|
|
807
|
+
'?- I = 0\n' +
|
|
808
|
+
'; I = 1\n' +
|
|
809
|
+
'; I = 2\n' +
|
|
810
|
+
'; I = 3\n' +
|
|
811
|
+
'; I = 4\n' +
|
|
812
|
+
'; ... .\n' +
|
|
813
|
+
'?- J = 0\n' +
|
|
814
|
+
'; J = 1\n' +
|
|
815
|
+
'; J = 2\n' +
|
|
816
|
+
'; J = 3\n' +
|
|
817
|
+
'; J = 4\n' +
|
|
818
|
+
'; ... .\n' +
|
|
819
|
+
'?- K = 0\n' +
|
|
820
|
+
'; K = 1\n' +
|
|
821
|
+
'; K = 2\n' +
|
|
822
|
+
'; K = 3\n' +
|
|
823
|
+
'; K = 4\n' +
|
|
824
|
+
'; K = 5\n' +
|
|
825
|
+
'; K = 6\n' +
|
|
826
|
+
'; K = 7\n' +
|
|
827
|
+
'; K = 8\n' +
|
|
828
|
+
'; K = 9\n' +
|
|
829
|
+
'; ... .\n' +
|
|
830
|
+
'?- ',
|
|
831
|
+
'stdout');
|
|
832
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
833
|
+
},
|
|
834
|
+
},
|
|
755
835
|
{
|
|
756
836
|
name: 'REPL parenthesizes operator-valued answer substitutions',
|
|
757
837
|
run: () => {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -5758,12 +5758,16 @@ quoted_atom("ab"). % quoted_atom(ab)
|
|
|
5758
5758
|
|
|
5759
5759
|
Conversions accept partial output lists when the atomic input is known, but
|
|
5760
5760
|
constructing an atom or number requires a complete proper list with no unbound
|
|
5761
|
-
elements. Numeric parsing accepts
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
and
|
|
5761
|
+
elements. Numeric parsing accepts ISO layout before tokens, including layout between a
|
|
5762
|
+
minus token and the following numeric token. A single-line `%...` comment may
|
|
5763
|
+
therefore follow `-` directly because `%` cannot continue a graphic token; an
|
|
5764
|
+
adjacent bracketed comment in `-/**/1` remains a syntax error under the eager
|
|
5765
|
+
token-consumer rule. Decimal fractions and decimal exponents are supported;
|
|
5766
|
+
trailing material and non-finite values are rejected. The regression gate
|
|
5767
|
+
vendors all 74 numbered cases from Ulrich Neumerkel's contemporary
|
|
5768
|
+
`number_chars/2` comparison, including the Cor.2 error-precedence cases;
|
|
5769
|
+
`number_codes/2` shares the same numeric parser and has mirrored coverage for
|
|
5770
|
+
the recent numeric-syntax regressions.
|
|
5767
5771
|
|
|
5768
5772
|
### Streams and unit I/O
|
|
5769
5773
|
|
|
@@ -6264,8 +6268,10 @@ may span lines and end with a full stop, as in Scryer Prolog:
|
|
|
6264
6268
|
|
|
6265
6269
|
When another answer exists in an interactive terminal, press `;`, Space, or
|
|
6266
6270
|
`n` to ask for it immediately; no Return is needed. Return or `.` stops
|
|
6267
|
-
enumeration, `a` enumerates all remaining answers, `f`
|
|
6268
|
-
five
|
|
6271
|
+
enumeration, `a` enumerates all remaining answers, and `f` advances to the
|
|
6272
|
+
next five-answer boundary (5, 10, 15, ... displayed leaf answers), regardless
|
|
6273
|
+
of how many answers were stepped through individually beforehand. `h` displays
|
|
6274
|
+
the answer-control help. While a query is actively
|
|
6269
6275
|
computing, EyeProlog releases readline's terminal signal handling: `Ctrl-C`
|
|
6270
6276
|
therefore terminates the current EyeProlog process immediately, and on POSIX
|
|
6271
6277
|
terminals `Ctrl-Z` suspends it in the usual shell-managed way. This remains a
|
|
@@ -7018,7 +7024,7 @@ precedence still need one-by-one closure. `test/conformance/ISO-MATRIX.md`
|
|
|
7018
7024
|
maps language families to representative executable cases.
|
|
7019
7025
|
|
|
7020
7026
|
The complete suite must pass before release. The file-based conformance corpus
|
|
7021
|
-
contains
|
|
7027
|
+
contains 792 cases, including 386 focused ISO
|
|
7022
7028
|
cases derived from the success, failure, mode, and error behavior in
|
|
7023
7029
|
ISO/IEC 13211-1 clauses 7 and 8, Part 2 modules, and Part 3 grammar rules.
|
|
7024
7030
|
Separate exact-output suites check 189 normal
|