eyeprolog 1.5.21 → 1.5.23
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/index.d.ts +52 -2
- package/package.json +1 -1
- package/src/ARCHITECTURE.md +6 -0
- package/src/cli.js +42 -6
- package/src/explain.js +315 -15
- package/src/index.js +4 -4
- package/src/write.js +29 -11
- package/test/benchmark.mjs +61 -0
- package/test/conformance/ISO-COMPLIANCE.md +4 -4
- package/test/conformance/ISO-IMPLEMENTATION-DEFINED.md +1 -1
- package/test/conformance/README.md +1 -1
- package/test/conformance/WG17-SYNTAX-STATUS.md +9 -9
- package/test/conformance/expected/iso/logtalk_univ.pl +1 -1
- package/test/conformance/wg17-syntax-cases.json +4 -103
- package/test/conformance/wg17-syntax-coverage.json +3 -3
- package/test/run-regression.mjs +216 -5
- package/the-art-of-eyeprolog.md +68 -11
- package/tools/upgrade-wg17.mjs +26 -0
- package/why-eyeprolog.md +14 -3
package/src/write.js
CHANGED
|
@@ -152,6 +152,20 @@ function writeString(value) {
|
|
|
152
152
|
return out + '"';
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
function quotedListCharacter(item, doubleQuotes) {
|
|
156
|
+
if (doubleQuotes === 'chars') {
|
|
157
|
+
if (item.type !== ATOM || Array.from(item.name).length !== 1) return null;
|
|
158
|
+
return item.name;
|
|
159
|
+
}
|
|
160
|
+
if (doubleQuotes === 'codes') {
|
|
161
|
+
if (item.type !== NUMBER || !/^\d+$/.test(item.name)) return null;
|
|
162
|
+
const code = BigInt(item.name);
|
|
163
|
+
if (code < 0n || code > 0x10ffffn || (code >= 0xd800n && code <= 0xdfffn)) return null;
|
|
164
|
+
return String.fromCodePoint(Number(code));
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
|
|
155
169
|
function quotedListSplice(term, env, doubleQuotes) {
|
|
156
170
|
if (doubleQuotes !== 'chars' && doubleQuotes !== 'codes') return null;
|
|
157
171
|
const characters = [];
|
|
@@ -164,16 +178,9 @@ function quotedListSplice(term, env, doubleQuotes) {
|
|
|
164
178
|
if (!isCons(cursor)) {
|
|
165
179
|
return characters.length === 0 ? null : { text: characters.join(''), tail: cursor };
|
|
166
180
|
}
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
characters.push(item.name);
|
|
171
|
-
} else {
|
|
172
|
-
if (item.type !== NUMBER || !/^\d+$/.test(item.name)) return null;
|
|
173
|
-
const code = BigInt(item.name);
|
|
174
|
-
if (code < 0n || code > 0x10ffffn || (code >= 0xd800n && code <= 0xdfffn)) return null;
|
|
175
|
-
characters.push(String.fromCodePoint(Number(code)));
|
|
176
|
-
}
|
|
181
|
+
const character = quotedListCharacter(deref(cursor.args[0], env), doubleQuotes);
|
|
182
|
+
if (character == null) return null;
|
|
183
|
+
characters.push(character);
|
|
177
184
|
cursor = cursor.args[1];
|
|
178
185
|
}
|
|
179
186
|
}
|
|
@@ -351,15 +358,26 @@ function format(term, env, options, table, maxPriority = 1200, context = 'term')
|
|
|
351
358
|
|
|
352
359
|
if (!options.ignoreOps) {
|
|
353
360
|
const parts = [];
|
|
361
|
+
let quotedSuffix = [];
|
|
354
362
|
let cursor = resolved;
|
|
355
363
|
while (true) {
|
|
356
364
|
cursor = deref(cursor, env);
|
|
357
365
|
const separator = options.compact ? ',' : ', ';
|
|
358
|
-
if (isEmptyList(cursor))
|
|
366
|
+
if (isEmptyList(cursor)) {
|
|
367
|
+
if (quotedSuffix.length > 1 && quotedSuffix.length < parts.length) {
|
|
368
|
+
const prefix = parts.slice(0, parts.length - quotedSuffix.length);
|
|
369
|
+
return `[${prefix.join(separator)}|${writeString(quotedSuffix.join(''))}]`;
|
|
370
|
+
}
|
|
371
|
+
return `[${parts.join(separator)}]`;
|
|
372
|
+
}
|
|
359
373
|
if (!isCons(cursor)) {
|
|
360
374
|
const tailSeparator = options.compact ? '|' : ' | ';
|
|
361
375
|
return `[${parts.join(separator)}${tailSeparator}${format(cursor, env, options, table, 999, 'argument')}]`;
|
|
362
376
|
}
|
|
377
|
+
const item = deref(cursor.args[0], env);
|
|
378
|
+
const character = quotedListCharacter(item, options.doubleQuotes);
|
|
379
|
+
if (character == null) quotedSuffix = [];
|
|
380
|
+
else quotedSuffix.push(character);
|
|
363
381
|
parts.push(format(cursor.args[0], env, options, table, 999, 'argument'));
|
|
364
382
|
cursor = cursor.args[1];
|
|
365
383
|
}
|
package/test/benchmark.mjs
CHANGED
|
@@ -128,6 +128,48 @@ function changeText(item) {
|
|
|
128
128
|
return `${change < 0 ? '↓' : '↑'} ${value}`;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function summarizeResults(results) {
|
|
132
|
+
const comparable = results.filter((item) =>
|
|
133
|
+
Number.isFinite(item.medianMs) &&
|
|
134
|
+
item.medianMs > 0 &&
|
|
135
|
+
Number.isFinite(item.baselineMs) &&
|
|
136
|
+
item.baselineMs > 0);
|
|
137
|
+
|
|
138
|
+
if (comparable.length === 0) {
|
|
139
|
+
return {
|
|
140
|
+
comparable: 0,
|
|
141
|
+
total: results.length,
|
|
142
|
+
ratio: null,
|
|
143
|
+
changePercent: null,
|
|
144
|
+
currentTotalMs: null,
|
|
145
|
+
baselineTotalMs: null,
|
|
146
|
+
totalRatio: null,
|
|
147
|
+
totalChangePercent: null,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const ratio = Math.exp(
|
|
152
|
+
comparable.reduce(
|
|
153
|
+
(sum, item) => sum + Math.log(item.medianMs / item.baselineMs),
|
|
154
|
+
0,
|
|
155
|
+
) / comparable.length,
|
|
156
|
+
);
|
|
157
|
+
const currentTotalMs = comparable.reduce((sum, item) => sum + item.medianMs, 0);
|
|
158
|
+
const baselineTotalMs = comparable.reduce((sum, item) => sum + item.baselineMs, 0);
|
|
159
|
+
const totalRatio = currentTotalMs / baselineTotalMs;
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
comparable: comparable.length,
|
|
163
|
+
total: results.length,
|
|
164
|
+
ratio,
|
|
165
|
+
changePercent: (ratio - 1) * 100,
|
|
166
|
+
currentTotalMs,
|
|
167
|
+
baselineTotalMs,
|
|
168
|
+
totalRatio,
|
|
169
|
+
totalChangePercent: (totalRatio - 1) * 100,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
131
173
|
function runWorker(item) {
|
|
132
174
|
const child = spawnSync(process.execPath, [
|
|
133
175
|
path.join(root, 'test', 'benchmark-worker.mjs'),
|
|
@@ -176,6 +218,8 @@ for (const item of selected) {
|
|
|
176
218
|
});
|
|
177
219
|
}
|
|
178
220
|
|
|
221
|
+
const summary = summarizeResults(results);
|
|
222
|
+
|
|
179
223
|
if (options.save != null) {
|
|
180
224
|
await fs.mkdir(path.dirname(options.save), { recursive: true });
|
|
181
225
|
const saved = {
|
|
@@ -202,6 +246,7 @@ if (options.json) {
|
|
|
202
246
|
targetMs: options.targetMs,
|
|
203
247
|
baseline: baselinePath,
|
|
204
248
|
baselineWarning,
|
|
249
|
+
summary,
|
|
205
250
|
results,
|
|
206
251
|
}, null, 2)}\n`);
|
|
207
252
|
} else {
|
|
@@ -220,9 +265,25 @@ if (options.json) {
|
|
|
220
265
|
printRow(headers);
|
|
221
266
|
printRow(widths.map((width) => '-'.repeat(width)));
|
|
222
267
|
for (const row of rows) printRow(row);
|
|
268
|
+
|
|
269
|
+
if (summary.comparable > 0) {
|
|
270
|
+
process.stdout.write(
|
|
271
|
+
`\nSuite score: ${summary.ratio.toFixed(3)}x baseline ` +
|
|
272
|
+
`(${changeText({ changePercent: summary.changePercent })}); ` +
|
|
273
|
+
`equal-weight geometric mean across ${summary.comparable}/${summary.total} comparable benchmarks.\n`,
|
|
274
|
+
);
|
|
275
|
+
process.stdout.write(
|
|
276
|
+
`Time-weighted total: ${formatMs(summary.currentTotalMs)} vs ${formatMs(summary.baselineTotalMs)} ` +
|
|
277
|
+
`(${changeText({ changePercent: summary.totalChangePercent })}).\n`,
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
223
281
|
process.stdout.write(`\n${results.length} benchmarks; ${options.runs} measured batch${options.runs === 1 ? '' : 'es'} each after ${options.warmup} warm-up batch${options.warmup === 1 ? '' : 'es'}, calibrated after one priming execution toward ${options.targetMs} ms per batch.\n`);
|
|
224
282
|
if (baselineWarning) process.stdout.write(`${baselineWarning}\n`);
|
|
225
283
|
if (baselinePath == null && !baselineWarning) process.stdout.write('No timing baseline found; run npm run benchmark:baseline to create .benchmarks/baseline.json.\n');
|
|
226
284
|
if (options.save != null) process.stdout.write(`Saved timing baseline: ${path.relative(root, options.save)}\n`);
|
|
227
285
|
process.stdout.write('Change compares the current median/op directly with the saved baseline median/op; the measured range is shown separately.\n');
|
|
286
|
+
if (summary.comparable > 0) {
|
|
287
|
+
process.stdout.write('Suite score is the geometric mean of current/baseline ratios, so every benchmark has equal relative weight; Time-weighted total compares summed medians and is dominated by longer workloads.\n');
|
|
288
|
+
}
|
|
228
289
|
}
|
|
@@ -19,7 +19,7 @@ relevant implementation-dependent overlap choice to an explicit audit outcome.
|
|
|
19
19
|
|
|
20
20
|
| Requirement | Status | EyeProlog evidence / remaining work |
|
|
21
21
|
| --- | --- | --- |
|
|
22
|
-
| 5.1(a) prepare conforming Prolog text | covered | Clause 6 token/term production and rejection families are mapped by the strict production gate and the complete
|
|
22
|
+
| 5.1(a) prepare conforming Prolog text | covered | Clause 6 token/term production and rejection families are mapped by the strict production gate and the complete 366-case vendored WG17 syntax matrix; 7.4 preparation/directive behavior is separately closed. |
|
|
23
23
|
| 5.1(b) execute conforming Prolog goals | covered | Clause 7 term/control/execution semantics, the higher-level 7.10 stream model, 7.11 flags, the 7.12 error envelope, all 8.2-8.17 built-in rows, and Clause 9 arithmetic have explicit executable dispositions. |
|
|
24
24
|
| 5.1(c) reject nonconforming text/read-terms | covered | WG17 negative syntax cases, focused malformed-production/escape/comment/operator cases, read-term syntax errors, and strict rejection of implementation-specific syntax provide explicit rejection evidence across the Clause 6 families. |
|
|
25
25
|
| 5.1(d) document permitted variations | covered | The clause-by-clause [ISO 5.4 decision index](ISO-IMPLEMENTATION-DEFINED.md) records every explicit implementation-defined decision found in the Part 1 + Corrigenda baseline and separately inventories implementation-specific extension families. The index retains an `audit gap` category for future discoveries; no current release-facing row depends on one. |
|
|
@@ -31,7 +31,7 @@ relevant implementation-dependent overlap choice to an explicit audit outcome.
|
|
|
31
31
|
|
|
32
32
|
| Standard area | Status | Current evidence |
|
|
33
33
|
| --- | --- | --- |
|
|
34
|
-
| Clause 6 — tokens, terms, lists, operators, quoted text | covered | The strict Clause 6 gate maps atomic/variable/compound/operator/list/curly/double-quoted term forms, layout/comments, quoted escapes, integer bases/character codes, floating tokens, and solo/meta token boundaries, with malformed counterparts rejected. The complete
|
|
34
|
+
| Clause 6 — tokens, terms, lists, operators, quoted text | covered | The strict Clause 6 gate maps atomic/variable/compound/operator/list/curly/double-quoted term forms, layout/comments, quoted escapes, integer bases/character codes, floating tokens, and solo/meta token boundaries, with malformed counterparts rejected. The complete 366-case WG17 syntax matrix provides independent production-level coverage, and a cross-profile gate verifies that normal syntax extensions preserve every strict-accepted standard observation. The implementation-defined 6.5/6.6 PCS/collation choices are documented separately. |
|
|
35
35
|
| 7.1-7.3 — term types, term order, unification | covered | [ISO-TERM-SEMANTICS-MATRIX.md](ISO-TERM-SEMANTICS-MATRIX.md) records the five mutually exclusive strict term types, derived variable/compound/list notions, the complete standard-order classes and implementation-dependent variable-order choice, NSTO MGU/failure behavior, and EyeProlog's permitted consistent occurs-check failure for Part 1's undefined STO ordinary-unification cases. The normal JavaScript API string term is documented as a 5.5.4 extension and rejected at strict program/goal entry. |
|
|
36
36
|
| 7.4 — Prolog text and directives | covered | [ISO-PROLOG-TEXT-EXECUTION-MATRIX.md](ISO-PROLOG-TEXT-EXECUTION-MATRIX.md) closes the preparation/directive rows: declaration semantics, source clauses, cross-text operators/character conversion/flags, initialization order/lifetime, `include/1`, and one-time `ensure_loaded/1`, with implementation-defined cross-text choices indexed under 5.4. |
|
|
37
37
|
| 7.5-7.6 — database and term/clause conversion | covered | [ISO-PROLOG-TEXT-EXECUTION-MATRIX.md](ISO-PROLOG-TEXT-EXECUTION-MATRIX.md) closes static/dynamic and private/public procedure semantics, clause order, logical-update visibility, empty/unknown lifetime, and term/body/clause conversion. Source and runtime assertion conversion recurse through `,/2`, `;/2`, and `->/2`, preserve variable identity, and protect standardized static/control procedures. |
|
|
@@ -286,7 +286,7 @@ post-N289 STC drafts remain review input until standardized.
|
|
|
286
286
|
| Criterion | Status | Evidence |
|
|
287
287
|
| --- | --- | --- |
|
|
288
288
|
| Clause 5 processor obligations have explicit dispositions | covered | `ISO-PROCESSOR-REQUIREMENTS.md` gives explicit outcomes for 5.1-5.5, including the strict/normal extension boundary. |
|
|
289
|
-
| Clause 6 lexical/syntactic requirements have explicit dispositions | covered | the strict Clause 6 production/rejection gate and the
|
|
289
|
+
| Clause 6 lexical/syntactic requirements have explicit dispositions | covered | the strict Clause 6 production/rejection gate and the 366-case vendored WG17 matrix cover the standard families; cross-profile preservation verifies that normal extensions do not reinterpret strict-accepted text. |
|
|
290
290
|
| Clause 7 semantic requirements have explicit dispositions | covered | 7.1-7.12 now have explicit semantic, implementation-defined, or error-envelope dispositions backed by strict tests and the specialized matrices. |
|
|
291
291
|
| Clause 8 built-in modes/errors have explicit dispositions | covered | `ISO-BUILTIN-MODE-ERROR-MATRIX.md` closes 8.2-8.17 row by row |
|
|
292
292
|
| Clause 9 evaluable-functor requirements have explicit dispositions | covered | `ISO-EVALUABLE-FUNCTOR-MATRIX.md` plus the strict arithmetic regression closes the published Part 1 + Corrigenda arithmetic rows |
|
|
@@ -294,7 +294,7 @@ post-N289 STC drafts remain review input until standardized.
|
|
|
294
294
|
| Implementation-specific strict/normal boundary is documented and tested | covered | all 5.5 hooks have explicit dispositions; the WG17 cross-profile gate verifies syntax-preservation for standard text accepted by the strict reader. |
|
|
295
295
|
| Published Corrigenda 1-3 are incorporated | covered | dedicated conformance/strict tests and this ledger track all three published Corrigenda |
|
|
296
296
|
| Current post-N289 draft is tracked without silently changing the published baseline | covered | `STC-DRAFT-STATUS.md` tracks reviewed draft items separately from normative requirements |
|
|
297
|
-
| Independent external syntax corpus is an offline release gate | covered | the vendored WG17 syntax matrix has
|
|
297
|
+
| Independent external syntax corpus is an offline release gate | covered | the vendored WG17 syntax matrix has 366 executable dispositions checked against its upstream expectations |
|
|
298
298
|
| Third-party standard-core regression provenance is retained | covered | adapted Logtalk, Scryer, Trealla, and SWI-Prolog cases retain source identifiers and licenses in `THIRD_PARTY.md` |
|
|
299
299
|
| No unexplained deviation remains in the release-facing ledger | covered | the release-facing ledger contains no remaining `audit` rows; documented variation points are implementation-defined/specific or draft-only rather than unexplained deviations. |
|
|
300
300
|
|
|
@@ -124,7 +124,7 @@ families; `--iso-strict` is intended to remove their Part 1 interpretation.
|
|
|
124
124
|
| 5.5.9 Built-in predicates | EyeProlog libraries, CLP(Z), statistics, Part 3 `phrase/2-3`, and bundled-library autoloaded predicates | Strict registry contains only the Part 1 + Corrigenda core registry. |
|
|
125
125
|
| 5.5.10 Evaluable functors | Normal mode additionally accepts the EyeProlog evaluable atom `e`; the remaining arithmetic functors accepted by strict mode are the Part 1 + Corrigenda set. | Strict mode rejects `e/0` as non-evaluable and retains the Corrigendum arithmetic additions. **covered** — strict extension-boundary regression plus `src/iso-arithmetic.js`. |
|
|
126
126
|
| 5.5.11 Reserved atoms | None | None. |
|
|
127
|
-
| Cor.3 5.5.12 Options | Extra library/host options may exist outside core option lists | Normal mode additionally accepts the EyeProlog `write_term/2-3` options `double_quotes(true|false)` and `spacing(true|false)`. `double_quotes(true)` is orthogonal to `ignore_ops(true)`: eligible character/code lists retain double-quoted notation while operator terms use functional notation, and the order of those distinct options does not affect the result. `spacing(false)` emits only lexically required separators; `spacing(true)` adds conventional layout around operators. Strict core excludes these implementation-specific extensions and accepts only the Part 1 plus Corrigendum 3 write-option surface; unknown extension options raise `domain_error(write_option,...)`. |
|
|
127
|
+
| Cor.3 5.5.12 Options | Extra library/host options may exist outside core option lists | Normal mode additionally accepts the EyeProlog `write_term/2-3` options `double_quotes(true|false)` and `spacing(true|false)`. `double_quotes(true)` is orthogonal to `ignore_ops(true)`: eligible character/code lists, including a proper list's maximal character/code suffix of at least two elements, retain double-quoted notation while operator terms use functional notation, and the order of those distinct options does not affect the result. `spacing(false)` emits only lexically required separators; `spacing(true)` adds conventional layout around operators. Strict core excludes these implementation-specific extensions and accepts only the Part 1 plus Corrigendum 3 write-option surface; unknown extension options raise `domain_error(write_option,...)`. |
|
|
128
128
|
|
|
129
129
|
Normal mode provides documented module and DCG compatibility profiles whose
|
|
130
130
|
features overlap standardized Part 2 and Part 3 facilities. They are extensions
|
|
@@ -145,7 +145,7 @@ are recorded in [THIRD_PARTY.md](THIRD_PARTY.md).
|
|
|
145
145
|
|
|
146
146
|
The corpus has 386 cases in `iso/` and 802 file-based conformance cases in
|
|
147
147
|
total. Of those, 11 cases in `stc/` are explicitly labelled working-draft
|
|
148
|
-
review evidence rather than normative ISO claims. The separate strict-reader WG17 matrix has
|
|
148
|
+
review evidence rather than normative ISO claims. The separate strict-reader WG17 matrix has 366 executable dispositions.
|
|
149
149
|
The generated `conformance-report.md` is the authoritative source for the current
|
|
150
150
|
executable WG17 syntax result and file-based category totals. Together with regression, documentation-sync, API, example,
|
|
151
151
|
and book-example checks, `npm test` is the release gate.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# WG17 syntax traceability status
|
|
2
2
|
|
|
3
3
|
Source: [Conformity Testing I: Syntax](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing)
|
|
4
|
-
Upstream inventory checked: 2026-
|
|
4
|
+
Upstream inventory checked: 2026-09-01
|
|
5
5
|
|
|
6
6
|
This ledger counts an upstream case when its WG17 identifier, query, and
|
|
7
7
|
expected ISO disposition are stored in the offline executable matrix. Every
|
|
@@ -20,25 +20,25 @@ A represented case still has to pass the executable upstream assertion in
|
|
|
20
20
|
|
|
21
21
|
| Measure | Count |
|
|
22
22
|
| --- | ---: |
|
|
23
|
-
| Active upstream cases |
|
|
24
|
-
| Upstream cases represented in the executable matrix |
|
|
23
|
+
| Active upstream cases | 366 |
|
|
24
|
+
| Upstream cases represented in the executable matrix | 366 (100.0%) |
|
|
25
25
|
| Not yet traced one-by-one | 0 |
|
|
26
26
|
| Deleted upstream identifiers | #20, #273 |
|
|
27
27
|
|
|
28
28
|
The matrix runs in strict ISO stream-reader mode as part of `npm test`. The
|
|
29
29
|
3 upstream `waits` cases are checked through EyeProlog's interactive input
|
|
30
|
-
hook. All
|
|
31
|
-
upstream Codex expectation.
|
|
32
|
-
outcomes for stronger regression checking;
|
|
30
|
+
hook. All 366 executable cases are independently checked against the
|
|
31
|
+
upstream Codex expectation. 365 cases additionally retain exact reviewed
|
|
32
|
+
outcomes for stronger regression checking; 1 case currently relies on the upstream assertion alone.
|
|
33
33
|
|
|
34
34
|
## Traceable evidence
|
|
35
35
|
|
|
36
36
|
| Executable evidence | Referenced IDs | WG17 cases |
|
|
37
37
|
| --- | ---: | --- |
|
|
38
|
-
| [complete offline executable matrix](../run-wg17.mjs) |
|
|
38
|
+
| [complete offline executable matrix](../run-wg17.mjs) | 366 | #1–#19, #21–#272, #274–#368 |
|
|
39
39
|
|
|
40
|
-
The evidence groups overlap. Their union is **
|
|
41
|
-
#1–#19, #21–#272, #274–#
|
|
40
|
+
The evidence groups overlap. Their union is **366** active cases:
|
|
41
|
+
#1–#19, #21–#272, #274–#368.
|
|
42
42
|
|
|
43
43
|
## Untraced upstream identifiers
|
|
44
44
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
univ_results(foo(a, b), [foo
|
|
1
|
+
univ_results(foo(a, b), [foo|"ab"], "a", ['.', 1, []], [1.0]).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "https://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing",
|
|
3
|
-
"checkedOn": "2026-
|
|
3
|
+
"checkedOn": "2026-09-01",
|
|
4
4
|
"protocol": "Each query is read and executed in strict ISO mode; /**/ rows reuse the preceding setup.",
|
|
5
5
|
"cases": [
|
|
6
6
|
{
|
|
@@ -4139,16 +4139,8 @@
|
|
|
4139
4139
|
"query": "write_canonical(B+B).",
|
|
4140
4140
|
"input": "write_canonical(B+B).",
|
|
4141
4141
|
"readCount": 1,
|
|
4142
|
-
"expected": "e.g. +(_1
|
|
4143
|
-
"
|
|
4144
|
-
"type": "success",
|
|
4145
|
-
"stages": [
|
|
4146
|
-
{
|
|
4147
|
-
"output": "+(_A,_A)",
|
|
4148
|
-
"variables": "['B'=B]"
|
|
4149
|
-
}
|
|
4150
|
-
]
|
|
4151
|
-
}
|
|
4142
|
+
"expected": "e.g. +(_1,_1)",
|
|
4143
|
+
"assertion": "upstream"
|
|
4152
4144
|
},
|
|
4153
4145
|
{
|
|
4154
4146
|
"id": 228,
|
|
@@ -5565,99 +5557,8 @@
|
|
|
5565
5557
|
}
|
|
5566
5558
|
]
|
|
5567
5559
|
}
|
|
5568
|
-
},
|
|
5569
|
-
{
|
|
5570
|
-
"id": 369,
|
|
5571
|
-
"query": "writeq(?-).",
|
|
5572
|
-
"input": "writeq(?-).",
|
|
5573
|
-
"readCount": 1,
|
|
5574
|
-
"expected": "?-",
|
|
5575
|
-
"outcome": {
|
|
5576
|
-
"type": "success",
|
|
5577
|
-
"stages": [
|
|
5578
|
-
{
|
|
5579
|
-
"output": "?-",
|
|
5580
|
-
"variables": "[]"
|
|
5581
|
-
}
|
|
5582
|
-
]
|
|
5583
|
-
}
|
|
5584
|
-
},
|
|
5585
|
-
{
|
|
5586
|
-
"id": 370,
|
|
5587
|
-
"query": "writeq(./*).",
|
|
5588
|
-
"input": "writeq(./*).",
|
|
5589
|
-
"readCount": 1,
|
|
5590
|
-
"expected": "./*",
|
|
5591
|
-
"outcome": {
|
|
5592
|
-
"type": "success",
|
|
5593
|
-
"stages": [
|
|
5594
|
-
{
|
|
5595
|
-
"output": "./*",
|
|
5596
|
-
"variables": "[]"
|
|
5597
|
-
}
|
|
5598
|
-
]
|
|
5599
|
-
}
|
|
5600
|
-
},
|
|
5601
|
-
{
|
|
5602
|
-
"id": 371,
|
|
5603
|
-
"query": "writeq({*}).",
|
|
5604
|
-
"input": "writeq({*}).",
|
|
5605
|
-
"readCount": 1,
|
|
5606
|
-
"expected": "{*}",
|
|
5607
|
-
"outcome": {
|
|
5608
|
-
"type": "success",
|
|
5609
|
-
"stages": [
|
|
5610
|
-
{
|
|
5611
|
-
"output": "{*}",
|
|
5612
|
-
"variables": "[]"
|
|
5613
|
-
}
|
|
5614
|
-
]
|
|
5615
|
-
}
|
|
5616
|
-
},
|
|
5617
|
-
{
|
|
5618
|
-
"id": 372,
|
|
5619
|
-
"query": "writeq(.*).",
|
|
5620
|
-
"input": "writeq(.*).",
|
|
5621
|
-
"readCount": 1,
|
|
5622
|
-
"expected": ".*",
|
|
5623
|
-
"outcome": {
|
|
5624
|
-
"type": "success",
|
|
5625
|
-
"stages": [
|
|
5626
|
-
{
|
|
5627
|
-
"output": ".*",
|
|
5628
|
-
"variables": "[]"
|
|
5629
|
-
}
|
|
5630
|
-
]
|
|
5631
|
-
}
|
|
5632
|
-
},
|
|
5633
|
-
{
|
|
5634
|
-
"id": 373,
|
|
5635
|
-
"query": "writeq(...*).",
|
|
5636
|
-
"input": "writeq(...*).",
|
|
5637
|
-
"readCount": 1,
|
|
5638
|
-
"expected": "...*",
|
|
5639
|
-
"outcome": {
|
|
5640
|
-
"type": "success",
|
|
5641
|
-
"stages": [
|
|
5642
|
-
{
|
|
5643
|
-
"output": "...*",
|
|
5644
|
-
"variables": "[]"
|
|
5645
|
-
}
|
|
5646
|
-
]
|
|
5647
|
-
}
|
|
5648
|
-
},
|
|
5649
|
-
{
|
|
5650
|
-
"id": 374,
|
|
5651
|
-
"query": "Finis ().",
|
|
5652
|
-
"input": "Finis ().",
|
|
5653
|
-
"readCount": 1,
|
|
5654
|
-
"expected": "syntax err.",
|
|
5655
|
-
"outcome": {
|
|
5656
|
-
"type": "error",
|
|
5657
|
-
"formal": "syntax_error(read_term)"
|
|
5658
|
-
}
|
|
5659
5560
|
}
|
|
5660
5561
|
],
|
|
5661
5562
|
"sourceRevision": "1.300",
|
|
5662
|
-
"sourceSha256": "
|
|
5563
|
+
"sourceSha256": "b6590c1c5269e8e62a1ec72a8f04f21f123a77709854a8a66c436df25f3ff418"
|
|
5663
5564
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"source": "https://www.complang.tuwien.ac.at/ulrich/iso-prolog/conformity_testing",
|
|
3
|
-
"checkedOn": "2026-
|
|
3
|
+
"checkedOn": "2026-09-01",
|
|
4
4
|
"upstream": {
|
|
5
5
|
"firstId": 1,
|
|
6
|
-
"lastId":
|
|
6
|
+
"lastId": 368,
|
|
7
7
|
"deletedIds": [
|
|
8
8
|
20,
|
|
9
9
|
273
|
|
10
10
|
],
|
|
11
|
-
"activeCases":
|
|
11
|
+
"activeCases": 366
|
|
12
12
|
},
|
|
13
13
|
"evidence": [
|
|
14
14
|
{
|