eyeprolog 1.3.58 → 1.3.60
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 +18 -1
- package/package.json +1 -1
- package/src/iso-arithmetic.js +12 -4
- package/test/conformance/ISO-BUILTIN-MODE-ERROR-MATRIX.md +6 -4
- package/test/conformance/ISO-COMPLIANCE.md +21 -22
- package/test/conformance/ISO-EVALUABLE-FUNCTOR-MATRIX.md +91 -0
- package/test/conformance/ISO-EXIT-CRITERIA.md +55 -0
- package/test/conformance/ISO-IMPLEMENTATION-DEFINED.md +6 -5
- package/test/conformance/ISO-MATRIX.md +6 -3
- package/test/conformance/ISO-PROCESSOR-REQUIREMENTS.md +8 -7
- package/test/conformance/ISO-TERM-SEMANTICS-MATRIX.md +53 -0
- package/test/conformance/README.md +12 -6
- package/test/run-iso-strict.mjs +163 -0
- package/test/run-regression.mjs +75 -5
- package/test/run-wg17.mjs +10 -9
- package/the-art-of-eyeprolog.md +26 -10
- package/why-eyeprolog.md +5 -3
package/README.md
CHANGED
|
@@ -226,7 +226,14 @@ precedence for `read_term/3`, `write_term/3`, `op/3`, and `current_op/3`, and
|
|
|
226
226
|
the complete Part 1 flag defaults/value domains/changeability rules. The
|
|
227
227
|
ongoing issue #65 audit additionally tightens Prolog-text declaration ordering,
|
|
228
228
|
initialization lifetime, stream/open/close behavior, character/byte stream
|
|
229
|
-
errors, `keysort/2` error cases, and
|
|
229
|
+
errors, `keysort/2` error cases, the now-closed 5.5.6 side-effect and 5.5.10 evaluable-functor strict
|
|
230
|
+
extension boundaries, and the standard's permitted arithmetic variation points: mixed-type Corrigendum 2
|
|
231
|
+
`max/2`/`min/2` and signed Clause 9.4 bitwise/shift behavior. The row-level
|
|
232
|
+
7.1-7.3 term-semantics audit and 7.9/Clause 9 expression/evaluable-functor
|
|
233
|
+
audit are now closed as well. That arithmetic pass also corrected float-only
|
|
234
|
+
`float_integer_part/1` and `float_fractional_part/1`: an integer operand, even
|
|
235
|
+
a huge valid unbounded integer, now reaches `type_error(float,...)` before any
|
|
236
|
+
integer-to-float overflow.
|
|
230
237
|
Those additions improve the Part 1 surface without turning the remaining audit
|
|
231
238
|
rows into a blanket conformance claim. The post-N289 WG17/STC working draft is
|
|
232
239
|
reviewed separately rather than treated as a fourth Corrigendum. The
|
|
@@ -236,10 +243,20 @@ proposal that would make the two power-underflow rows depend on the processor's
|
|
|
236
243
|
9.1.4.2 `resultF` choice. Strict mode retains the published Part 1 +
|
|
237
244
|
Corrigenda 1-3 behavior where the draft has not been standardized.
|
|
238
245
|
|
|
246
|
+
As an additional 5.5.1 extension-safety gate, every vendored WG17 syntax case
|
|
247
|
+
that succeeds in the strict Part 1 reader is re-run in the normal profile and
|
|
248
|
+
must retain the same observable outcome; normal mode may accept extra extension
|
|
249
|
+
syntax, but it must not reinterpret text already accepted as standard syntax.
|
|
250
|
+
|
|
239
251
|
The auditable processor-requirement checklist lives in
|
|
240
252
|
[`test/conformance/ISO-COMPLIANCE.md`](test/conformance/ISO-COMPLIANCE.md).
|
|
241
253
|
The ISO 5.4 implementation-defined/implementation-specific decision index is
|
|
242
254
|
[`test/conformance/ISO-IMPLEMENTATION-DEFINED.md`](test/conformance/ISO-IMPLEMENTATION-DEFINED.md).
|
|
255
|
+
The closed term and arithmetic row audits are
|
|
256
|
+
[`ISO-TERM-SEMANTICS-MATRIX.md`](test/conformance/ISO-TERM-SEMANTICS-MATRIX.md) and
|
|
257
|
+
[`ISO-EVALUABLE-FUNCTOR-MATRIX.md`](test/conformance/ISO-EVALUABLE-FUNCTOR-MATRIX.md);
|
|
258
|
+
[`ISO-EXIT-CRITERIA.md`](test/conformance/ISO-EXIT-CRITERIA.md) states the remaining
|
|
259
|
+
normative and external-corpus exit conditions.
|
|
243
260
|
The separate [WG17 syntax ledger](test/conformance/WG17-SYNTAX-STATUS.md)
|
|
244
261
|
records executable dispositions for the vendored active upstream WG17 syntax
|
|
245
262
|
cases and runs as part of `npm test`. Reviewed cases can pin exact outcomes;
|
package/package.json
CHANGED
package/src/iso-arithmetic.js
CHANGED
|
@@ -71,10 +71,18 @@ function evaluateOperation(term, args, options = {}) {
|
|
|
71
71
|
if (arity === 1 && ['abs', 'sign', 'float', 'truncate', 'round', 'ceiling', 'floor',
|
|
72
72
|
'float_integer_part', 'float_fractional_part',
|
|
73
73
|
'sin', 'cos', 'atan', 'asin', 'acos', 'tan', 'exp', 'log', 'sqrt'].includes(name)) {
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
if (options.isoStrict === true && [
|
|
74
|
+
// These six conversion/rounding functors have float-only input templates
|
|
75
|
+
// in 9.1.1/9.1.6. They therefore require type_error(float,...) when their
|
|
76
|
+
// evaluated argument has integer type, before any I->F conversion.
|
|
77
|
+
if (options.isoStrict === true && [
|
|
78
|
+
'truncate', 'round', 'ceiling', 'floor',
|
|
79
|
+
'float_integer_part', 'float_fractional_part',
|
|
80
|
+
].includes(name) && args[0].integer) {
|
|
81
|
+
// These functors have only F->I or F->F templates. In particular,
|
|
82
|
+
// float_integer_part/1 and float_fractional_part/1 must reject an
|
|
83
|
+
// integer by type before any I->F conversion is attempted; otherwise a
|
|
84
|
+
// sufficiently large (but valid, unbounded) integer can be misreported
|
|
85
|
+
// as float_overflow instead of type_error(float,...).
|
|
78
86
|
throw new PrologError('type_error(float)', numericTerm(args[0]));
|
|
79
87
|
}
|
|
80
88
|
if (name === 'abs' && args[0].integer) return { integer: true, value: args[0].value < 0n ? -args[0].value : args[0].value };
|
|
@@ -372,7 +372,9 @@ and conditional/not-applicable processor branches all have explicit outcomes.
|
|
|
372
372
|
ISO 7.12 simultaneous-error selection remains an implementation-dependent
|
|
373
373
|
processor choice unless more specific normative text constrains it.
|
|
374
374
|
|
|
375
|
-
The remaining #65 work is therefore above/below this built-in table
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
375
|
+
The remaining #65 work is therefore above/below this built-in table. The
|
|
376
|
+
7.1-7.3 term-semantics and 7.9/Clause 9 evaluable-functor rows are now closed in
|
|
377
|
+
their dedicated matrices. What remains is Clause 6 text/rejection mapping,
|
|
378
|
+
Clause 7.4-7.8 plus higher-level 7.10/7.12 processor/control semantics, residual
|
|
379
|
+
Clause 5 dependency rows, and the external conversion/variable-name exit
|
|
380
|
+
criteria recorded in `ISO-EXIT-CRITERIA.md`.
|
|
@@ -7,7 +7,11 @@ Corrigenda 1:2007, 2:2012, and 3:2017. It complements
|
|
|
7
7
|
executable tests, [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md),
|
|
8
8
|
which records the row-by-row built-in audit, and
|
|
9
9
|
[ISO-PROCESSOR-REQUIREMENTS.md](ISO-PROCESSOR-REQUIREMENTS.md), which decomposes
|
|
10
|
-
Clause 5 processor obligations.
|
|
10
|
+
Clause 5 processor obligations. [ISO-TERM-SEMANTICS-MATRIX.md](ISO-TERM-SEMANTICS-MATRIX.md)
|
|
11
|
+
and [ISO-EVALUABLE-FUNCTOR-MATRIX.md](ISO-EVALUABLE-FUNCTOR-MATRIX.md) close the
|
|
12
|
+
row-level Clause 7.1-7.3 and 7.9/Clause 9 audits, while
|
|
13
|
+
[ISO-EXIT-CRITERIA.md](ISO-EXIT-CRITERIA.md) makes the remaining release exit
|
|
14
|
+
conditions explicit. The generated [`conformance-report.md`](../../conformance-report.md)
|
|
11
15
|
gives current case totals.
|
|
12
16
|
|
|
13
17
|
The ledger deliberately does **not** claim independent certification. A row
|
|
@@ -22,29 +26,29 @@ relevant implementation-dependent overlap choice to an explicit audit outcome.
|
|
|
22
26
|
| Requirement | Status | EyeProlog evidence / remaining work |
|
|
23
27
|
| --- | --- | --- |
|
|
24
28
|
| 5.1(a) prepare conforming Prolog text | audit | Clause 6 parser/tokenizer coverage, directive coverage, syntax-error corpus, and the [complete vendored WG17 syntax matrix](WG17-SYNTAX-STATUS.md). Wider shall-by-shall text-processing audit remains open. |
|
|
25
|
-
| 5.1(b) execute conforming Prolog goals | audit | Clause 7-9 conformance corpus plus regression/API/example gates.
|
|
29
|
+
| 5.1(b) execute conforming Prolog goals | audit | Clause 7-9 conformance corpus plus regression/API/example gates. The 7.1-7.3 term-semantics, 7.9/Clause 9 arithmetic, and 8.2-8.17 built-in row audits are now closed; the dependency remains open on 7.4-7.8, higher-level 7.10, and residual processor-level 7.12 semantics. |
|
|
26
30
|
| 5.1(c) reject nonconforming text/read-terms | audit | Dedicated syntax-error cases and strict-core extension rejection. Exhaustive lexical rejection coverage remains open. |
|
|
27
31
|
| 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. Rows marked `audit gap` remain conformance work, but the variation is no longer undocumented. |
|
|
28
32
|
| 5.1(e) offer a strictly conforming mode | covered | `--iso-strict` and API option `isoStrict: true` restrict the processor to the Part 1 + Corrigenda 1-3 core language surface, remove EyeProlog-only registry/flag/operator features, disable automatic tabling/recursion guards, and reject the normal-profile host `stringTerm/1` term type at strict program/goal entry. |
|
|
29
33
|
| 5.4 accompanying documentation | covered | *The Art of EyeProlog* remains the implementation reference; [ISO-IMPLEMENTATION-DEFINED.md](ISO-IMPLEMENTATION-DEFINED.md) is the closed clause-by-clause 5.4 decision index and points each decision to implementation evidence or an explicit audit gap. |
|
|
30
|
-
| 5.5 extension boundaries | audit | [ISO-PROCESSOR-REQUIREMENTS.md](ISO-PROCESSOR-REQUIREMENTS.md)
|
|
34
|
+
| 5.5 extension boundaries | audit | [ISO-PROCESSOR-REQUIREMENTS.md](ISO-PROCESSOR-REQUIREMENTS.md) splits 5.5 into its individual extension hooks. Operators, character conversion, the normal-profile host string type, directives, control constructs, flags, built-ins, evaluable functors, and reserved atoms now have explicit decisions. The remaining open extension work is now concentrated in exhaustive syntax-preservation (5.5.1); the Prolog-visible additional-side-effect boundary (5.5.6) is explicitly filtered in strict mode and host instrumentation is documented as an embedding concern. |
|
|
31
35
|
|
|
32
36
|
## Normative language families
|
|
33
37
|
|
|
34
38
|
| Standard area | Status | Current evidence |
|
|
35
39
|
| --- | --- | --- |
|
|
36
|
-
| Clause 6 — tokens, terms, lists, operators, quoted text | audit | Complete vendored WG17 syntax matrix, `lexical_and_curly_terms`, `scryer_lexical_terms`, operator suites, syntax-error cases, quoted-layout/escape error cases, writer/read-back regressions, and Unicode-scalar PCS/collation boundary tests. The implementation-defined 6.5/6.6 character-model decisions are
|
|
37
|
-
| 7.1-7.3 — term types, term order, unification |
|
|
40
|
+
| Clause 6 — tokens, terms, lists, operators, quoted text | audit | Complete vendored WG17 syntax matrix, `lexical_and_curly_terms`, `scryer_lexical_terms`, operator suites, syntax-error cases, quoted-layout/escape error cases, writer/read-back regressions, and Unicode-scalar PCS/collation boundary tests. A cross-profile gate now verifies that every WG17 case accepted by the strict Part 1 reader has the same observable outcome under normal-mode syntax extensions. The implementation-defined 6.5/6.6 character-model decisions are closed; the remaining work is the explicit production-by-production shall map. |
|
|
41
|
+
| 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. |
|
|
38
42
|
| 7.4 — Prolog text and directives | audit | All Part 1 directive indicators are parsed; include/ensure-loaded/operator/flag/character-conversion behavior has executable coverage. Preparation-time `char_conversion/2` affects later unquoted source text and respects `char_conversion=off`. Strict preparation now enforces declaration-before-clause ordering for `dynamic/1`, `multifile/1`, and `discontiguous/1`, cross-text `multifile/1`, discontiguous clause grouping, empty declared procedures, include textual-replacement behavior, and one-time initialization per prepared program. The remaining shall-by-shall mapping is still open. |
|
|
39
43
|
| 7.5-7.6 — database and term/clause conversion | audit | Dynamic database and logical-update-view suites. Strict mode restores Part 1 private-static/public-dynamic `clause/2` access; focused strict checks cover the database built-ins and empty-procedure lifetime. Clause-body conversion now applies 7.6.2 both to prepared source clauses and runtime `asserta/1` / `assertz/1`: variables become `call/1`, `,/2`, `;/2`, and `->/2` are converted recursively, and head/body variable identity is preserved so `clause/2` and `retract/1` observe the converted term correctly. Runtime protection includes the solver-native conjunction control construct `','/2` and, following STC #56's accepted-direction action item, `(:-)/1-2` for database modification/private access while leaving their call behavior distinct. The remaining clause-conversion shall-by-shall mapping is still open. |
|
|
40
44
|
| 7.7 — execution and backtracking | audit | Control/search suites. Strict mode disables EyeProlog automatic tabling, cycle guards, and recursive numeric shortcuts so core execution uses ordinary clause selection/backtracking. |
|
|
41
45
|
| 7.8 — control constructs and exceptions | audit | call, cut, conjunction, disjunction (including failed branches after callee-local cuts), if-then, catch/throw, renamed-copy tests. The 8.15 built-in slice (`\+/1`, `once/1`, `repeat/0`, Corrigendum 2 `call/2..8`, `false/0`) is now row-audited in [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md); the remaining general control-construct semantics ledger stays open. |
|
|
42
|
-
| 7.9 — expression evaluation |
|
|
46
|
+
| 7.9 — expression evaluation | covered | [ISO-EVALUABLE-FUNCTOR-MATRIX.md](ISO-EVALUABLE-FUNCTOR-MATRIX.md) closes recursive evaluation, direct-variable precedence, corrected non-evaluable `F/N` errors (including STC #69), operand template/type rules, mixed arithmetic-comparison conversion, exceptional values, and finite-host resource normalization. The audit also fixes float-only `float_integer_part/1` and `float_fractional_part/1` so even huge valid integers reach `type_error(float,...)` before any I->F overflow. |
|
|
43
47
|
| 7.10 — input/output concepts | audit | Stream, character/byte I/O, read/write options, operator-sensitive write-back, and Corrigendum 3 writer cases. The complete 8.11-8.14 built-in mode/error family is now row-audited in [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md), including lifecycle/current-stream handling, stream positions, text/binary permissions, EOF actions, `force(true)`, input-code representation timing, term-I/O options, operators, and character conversion. `stream_property/2` now also distinguishes a malformed stream-term (domain error) from a valid stream-term whose stream is no longer open (ordinary failure). The higher-level 7.10 source/sink, buffering, positioning, and implementation-defined stream semantics remain under shall-by-shall audit. |
|
|
44
48
|
| 7.11 — flags | covered | The complete Part 1 flag set, selected defaults, standard value domains, changeability, `current_prolog_flag/2`, and `set_prolog_flag/2` error behavior have dedicated strict tests. EyeProlog selects `bounded=false` and `integer_rounding_function=toward_zero`; valid alternative values of those fixed flags reach `permission_error(modify,flag,...)`, while `max_integer` and `min_integer` have no current value. STC #70 is recorded explicitly: EyeProlog has no separate finite procedure-arity ceiling, so the optional `max_procedure_arity` flag is absent while `max_arity` remains `unbounded`. Strict mode excludes the EyeProlog `occurs_check` extension. |
|
|
45
49
|
| 7.12 — errors | audit | ISO `error(Error, Context)` envelope, type/domain/permission/representation/evaluation/syntax/resource families and focused error cases. [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md) now gives explicit mode/error-condition outcomes across the complete 8.2-8.17 built-in family, including Corrigendum additions and not-applicable conditional branches. The audit records the 7.12 rule that simultaneous error conditions are implementation dependent: overlap regressions document stable EyeProlog choices rather than inventing a universal table-order requirement. Remaining work is concentrated in non-built-in Clause 7 semantics, Clause 9 exceptional interactions, and processor-level error conditions. |
|
|
46
50
|
| 8.2-8.17 — built-in predicates | covered | [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md) now records the complete Part 1 + Corrigenda built-in family at one row per prescribed mode, success/failure behavior, individual error condition, and conditional/not-applicable branch. The row audit exposed and fixed source/runtime 7.6.2 body conversion/variable sharing, strict host-string leakage, input-code error timing, `close/2` force handling, and closed-stream `stream_property/2` behavior. Simultaneous-error choices are documented as implementation dependent under 7.12 unless separately constrained. |
|
|
47
|
-
| Clause 9 — evaluable functors |
|
|
51
|
+
| Clause 9 — evaluable functors | covered | [ISO-EVALUABLE-FUNCTOR-MATRIX.md](ISO-EVALUABLE-FUNCTOR-MATRIX.md) records the published Part 1 + Corrigenda arithmetic templates and exceptional branches across 9.1, 9.3, and 9.4. It pins the unbounded integer model, `rndI`/`rndF`/`resultF` choices, float-only conversion rules, I->F overflow, explicit `exp/1` and power underflow, Corrigendum 2 additions and mixed-type `max/2`/`min/2` implementation-dependent choice, Corrigendum 3 negative-power correction, signed bitwise/shift choices, and resource-error translation. Post-N289 STC #75 remains a separately tracked draft proposal rather than a silent change to the published baseline. |
|
|
48
52
|
| Corrigendum 1 | covered | Double-quoted atom/operator-priority corrections have dedicated cases. |
|
|
49
53
|
| Corrigendum 2 | covered | Added predicates/functors, catch corrections, bar/operator and uninstantiation corrections have dedicated cases. |
|
|
50
54
|
| Corrigendum 3 | covered | Writer options, `variable_names/1`, canonical list output and negative-power corrections have dedicated cases. |
|
|
@@ -288,18 +292,13 @@ outputs are never auto-accepted.
|
|
|
288
292
|
|
|
289
293
|
## Exit criteria for a full conformance claim
|
|
290
294
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
precedence actually constrained by procedural rules or Corrigenda have
|
|
302
|
-
executable coverage, while 7.12 simultaneous-error choices are documented;
|
|
303
|
-
5. every `audit gap` recorded in the ISO 5.4 decision index is either fixed or
|
|
304
|
-
explicitly excluded from the strict-conformance claim; and
|
|
305
|
-
6. an external conformance run has found no unexplained deviations.
|
|
295
|
+
[ISO-EXIT-CRITERIA.md](ISO-EXIT-CRITERIA.md) is now the authoritative checklist
|
|
296
|
+
for moving public wording from “ISO profile” to “conforming ISO/IEC 13211-1
|
|
297
|
+
processor”. It requires closure of every remaining normative `audit` row,
|
|
298
|
+
reproducible offline external comparison evidence, and no unexplained deviation.
|
|
299
|
+
|
|
300
|
+
The row-level 8.2-8.17 built-in audit, 7.1-7.3 term-semantics audit, and
|
|
301
|
+
7.9/Clause 9 evaluable-functor audit are already closed. The checklist remains
|
|
302
|
+
open because Clause 6, 7.4-7.8, higher-level 7.10/7.12, their Clause 5 dependency
|
|
303
|
+
rows, and part of the external conversion/variable-name evidence are not yet
|
|
304
|
+
fully reduced to explicit dispositions.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# ISO Part 1 expression/evaluable-functor audit matrix
|
|
2
|
+
|
|
3
|
+
This file is the row-level audit for Part 1 Clause 7.9 and Clause 9, including
|
|
4
|
+
the arithmetic additions and corrections in Technical Corrigenda 1-3. It is
|
|
5
|
+
paired with the strict regression named `closes the ISO 7.9 and Clause 9
|
|
6
|
+
evaluable-functor rows`.
|
|
7
|
+
|
|
8
|
+
The published ISO/IEC 13211-1:1995 + Corrigenda 1-3 text is the normative
|
|
9
|
+
baseline. Post-N289 STC draft proposals are tracked separately in
|
|
10
|
+
`STC-DRAFT-STATUS.md`; they do not silently replace published requirements.
|
|
11
|
+
|
|
12
|
+
## 7.9 - evaluating an expression
|
|
13
|
+
|
|
14
|
+
| Requirement | Status | Evidence / decision |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Evaluate variables | covered | direct variable operands raise `instantiation_error` before competing expression errors in strict mode |
|
|
17
|
+
| Evaluate numeric constants | covered | integer and float constants retain their numeric types subject to the documented float representation |
|
|
18
|
+
| Select an evaluable functor by name/arity | covered | Part 1 + Corrigenda functors are accepted; a non-evaluable term reports `type_error(evaluable,F/N)`, including the corrected zero-arity culprit shape |
|
|
19
|
+
| Recursively evaluate operands | covered | nested arithmetic, arithmetic comparisons, and `is/2` suites cover recursive evaluation; EyeProlog documents its stable operand-evaluation choice where Part 1 permits implementation dependence |
|
|
20
|
+
| Operand type constraints | covered | integer-only and float-only templates report the required type errors after expression evaluation |
|
|
21
|
+
| Exceptional values | covered | zero divisor, undefined, float overflow, explicit underflow, and finite-host resource exhaustion are pinned in strict tests |
|
|
22
|
+
|
|
23
|
+
## 9.1 - simple arithmetic and type conversion
|
|
24
|
+
|
|
25
|
+
| Functor / operation family | Required templates and exceptional branches | Status | Evidence / implementation choice |
|
|
26
|
+
| --- | --- | --- | --- |
|
|
27
|
+
| `+/2`, `-/2`, `*/2` | integer/integer -> integer; mixed/float -> float | covered | BigInt exact integer operations; binary64 mixed/float operations; host BigInt exhaustion -> `resource_error(memory)` |
|
|
28
|
+
| `/2` | numeric operands -> float; zero divisor | covered | binary64 division; zero divisor is an evaluation error |
|
|
29
|
+
| `//2` | integer operands; zero divisor | covered | `integer_rounding_function=toward_zero` and BigInt truncating division |
|
|
30
|
+
| `rem/2`, `mod/2` | integer operands; zero divisor | covered | sign behavior is pinned for negative operands |
|
|
31
|
+
| unary `-/1` | integer or float | covered | preserves numeric type |
|
|
32
|
+
| `abs/1`, `sign/1` | integer or float | covered | preserves integer results for integer operands and float results for float operands |
|
|
33
|
+
| `float/1` | integer -> float; float -> float | covered | integer-to-float overflow is detected before the selected floating operation |
|
|
34
|
+
| `floor/1`, `truncate/1`, `round/1`, `ceiling/1` | float -> integer only | covered | integer operands report `type_error(float,...)`; representative negative/positive rounding results are pinned |
|
|
35
|
+
| `float_integer_part/1`, `float_fractional_part/1` | float -> float only | covered | integer operands report `type_error(float,...)` before any I->F conversion; regression includes huge unbounded integers so float overflow cannot mask the required type error |
|
|
36
|
+
| integer model | bounded or unbounded choice | covered | `bounded=false`; semantic integer range is unbounded, with finite-host exhaustion represented as a resource error |
|
|
37
|
+
| `rndI` | processor integer-division rounding choice | covered | toward zero, consistent with the fixed flag |
|
|
38
|
+
| `rndF` / float representation | implementation-defined float rounding model | covered | ECMAScript IEEE-754 binary64 |
|
|
39
|
+
| `resultF` | choose generic tiny-result rounding or underflow | covered | EyeProlog selects `round(x)`; representable subnormals survive and still-smaller generic arithmetic may round to `0.0` |
|
|
40
|
+
| approximate addition | implementation-defined floating addition | covered | ECMAScript binary64 addition |
|
|
41
|
+
|
|
42
|
+
## Corrigendum 2 simple-arithmetic additions
|
|
43
|
+
|
|
44
|
+
| Functor | Status | Evidence / decision |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| unary `+/1` | covered | identity over numeric expressions |
|
|
47
|
+
| `div/2` | covered | integer floor division; negative-operand cases distinguish it from `//2` |
|
|
48
|
+
|
|
49
|
+
## 9.3 - other evaluable functors
|
|
50
|
+
|
|
51
|
+
| Functor family | Status | Exceptional / implementation-dependent coverage |
|
|
52
|
+
| --- | --- | --- |
|
|
53
|
+
| `**/2` | covered | negative-base restrictions, zero/negative exponent, float overflow, and the published explicit underflow row are pinned |
|
|
54
|
+
| `sin/1`, `cos/1`, `atan/1` | covered | integer templates perform I->F conversion first; conversion overflow is detected |
|
|
55
|
+
| `exp/1` | covered | float overflow and published non-zero-result underflow are pinned |
|
|
56
|
+
| `log/1`, `sqrt/1` | covered | non-positive/domain-invalid values report `evaluation_error(undefined)` as applicable |
|
|
57
|
+
| Corrigendum 2 `max/2`, `min/2` | covered | all type templates are supported; mixed numeric types use the documented implementation-dependent exact comparison and return one original operand, preserving its type |
|
|
58
|
+
| Corrigendum 2 `^/2` plus Corrigendum 3 correction | covered | integer powers remain exact where defined; negative integer exponent/type rules, negative-base rules, zero-negative exponent, overflow, and published underflow are pinned |
|
|
59
|
+
| Corrigendum 2 `asin/1`, `acos/1` | covered | valid values plus out-of-domain undefined errors |
|
|
60
|
+
| Corrigendum 2 `atan2/2` | covered | numeric templates plus the zero/zero undefined condition |
|
|
61
|
+
| Corrigendum 2 `tan/1` | covered | integer/float templates and I->F conversion behavior |
|
|
62
|
+
| Corrigendum 2 `pi/0` | covered | strict evaluable constant is available |
|
|
63
|
+
|
|
64
|
+
The 2026-08-23 post-N289 draft item #75 proposes conditioning the published
|
|
65
|
+
`**/2` and `^/2` underflow rows on the processor's `resultF` choice. EyeProlog
|
|
66
|
+
records that proposal but keeps the published unconditional strict behavior
|
|
67
|
+
until a normative corrigendum changes the baseline.
|
|
68
|
+
|
|
69
|
+
## 9.4 - bitwise functors
|
|
70
|
+
|
|
71
|
+
| Functor | Status | Implementation-defined negative/signed behavior |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| `>>/2` | covered | BigInt arithmetic/sign-propagating right shift; negative shift count reverses direction |
|
|
74
|
+
| `<</2` | covered | BigInt signed left shift; negative shift count reverses direction |
|
|
75
|
+
| `/\\/2` | covered | BigInt infinite-two's-complement semantics |
|
|
76
|
+
| `\\//2` | covered | BigInt infinite-two's-complement semantics |
|
|
77
|
+
| `\\/1` | covered | BigInt complement, equivalent to `-N-1` |
|
|
78
|
+
| Corrigendum 2 `xor/2` | covered | BigInt infinite-two's-complement semantics |
|
|
79
|
+
|
|
80
|
+
All 9.4 functors require integer operands; non-integers report
|
|
81
|
+
`type_error(integer,...)`. Very large otherwise-valid shifts retain the
|
|
82
|
+
unbounded integer model and translate finite-host exhaustion to
|
|
83
|
+
`resource_error(memory)`.
|
|
84
|
+
|
|
85
|
+
## Closure note
|
|
86
|
+
|
|
87
|
+
With this matrix and the strict arithmetic regression, the release-facing
|
|
88
|
+
Clause 7.9 and Clause 9 rows are `covered`. The remaining issue #65 audit is not
|
|
89
|
+
therefore an arithmetic audit: it is concentrated in Clause 6 text/rejection,
|
|
90
|
+
Clause 7.4-7.8 and 7.10/7.12 processor semantics, their Clause 5 dependencies,
|
|
91
|
+
and the remaining external-corpus exit criteria.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# ISO Part 1 audit exit criteria
|
|
2
|
+
|
|
3
|
+
Issue #65 is intentionally closed by evidence rather than by a single large
|
|
4
|
+
test count. This checklist defines what must be true before EyeProlog can remove
|
|
5
|
+
the remaining qualification that its strict ISO/IEC 13211-1 profile is still
|
|
6
|
+
under systematic audit.
|
|
7
|
+
|
|
8
|
+
The normative baseline is ISO/IEC 13211-1:1995 plus Technical Corrigenda 1-3.
|
|
9
|
+
Post-N289 STC drafts are review input only until standardized.
|
|
10
|
+
|
|
11
|
+
## Exit checklist
|
|
12
|
+
|
|
13
|
+
| Criterion | Status | Evidence / remaining work |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Clause 5 processor obligations have explicit dispositions | open | `ISO-PROCESSOR-REQUIREMENTS.md` still has dependent audit rows for preparation/execution/rejection and syntax preservation |
|
|
16
|
+
| Clause 6 lexical/syntactic requirements have explicit dispositions | open | 366-case vendored WG17 syntax gate and cross-profile preservation are green, but the production-by-production shall/rejection map is not yet complete |
|
|
17
|
+
| Clause 7 semantic requirements have explicit dispositions | open | 7.1-7.3 and 7.9 are now closed; 7.4-7.8, higher-level 7.10, and residual processor-level 7.12 rows remain |
|
|
18
|
+
| Clause 8 built-in modes/errors have explicit dispositions | covered | `ISO-BUILTIN-MODE-ERROR-MATRIX.md` closes 8.2-8.17 row by row |
|
|
19
|
+
| 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 |
|
|
20
|
+
| Implementation-defined choices are documented | covered | `ISO-IMPLEMENTATION-DEFINED.md` is the Clause 5.4 decision index and strict tests pin the behavior that affects execution |
|
|
21
|
+
| Implementation-specific strict/normal boundary is documented and tested | open | major 5.5 hooks are closed; exhaustive 5.5.1 syntax-preservation mapping remains tied to the Clause 6 audit |
|
|
22
|
+
| Published Corrigenda 1-3 are incorporated | covered | dedicated conformance/strict tests and the compliance matrix track all three published Corrigenda |
|
|
23
|
+
| Current post-N289 draft is tracked without changing the published baseline silently | covered | `STC-DRAFT-STATUS.md` tracks the reviewed 2026-08-23 items #73-#76, including the deliberate published-baseline treatment of #75 |
|
|
24
|
+
| Independent external syntax corpus is an offline release gate | covered | vendored active WG17 syntax matrix: 366 executable dispositions, checked against upstream expectations and reviewed exact outcomes |
|
|
25
|
+
| Third-party standard-core regression evidence is retained with provenance | covered | adapted Logtalk, Scryer, Trealla, and SWI-Prolog cases are vendored under `iso/`; `THIRD_PARTY.md` records origin and licenses |
|
|
26
|
+
| Known external-corpus deviations are explained and pinned | covered for vendored gates | the Prologue `bounded=false` / `max_integer` divergence is retained as upstream material and explicitly regression-tested; WG17 rows independently validate upstream expectation before any local reviewed snapshot can pass |
|
|
27
|
+
| External conversion/variable-name comparisons used during the audit are reproducible offline | open | focused behavior is already covered internally, but the remaining public comparison material has not all been normalized into a vendored offline fixture |
|
|
28
|
+
| Optional cross-engine runs have no unexplained deviations | open / environment-dependent | external-engine runner evidence is useful corroboration but is not substituted for normative ISO rows; release environments without those engines record the gate as unavailable rather than silently passing it |
|
|
29
|
+
| No unexplained deviation remains in the release-facing ledger | open | may become covered only when every open normative/external item above is either fixed, declared not applicable, or documented as a permitted implementation-defined/dependent choice |
|
|
30
|
+
|
|
31
|
+
## What counts as an explained deviation
|
|
32
|
+
|
|
33
|
+
A difference from an external corpus or another Prolog implementation is not an
|
|
34
|
+
automatic conformance defect. It is explained only when the repository records
|
|
35
|
+
which of these applies and has an executable regression where applicable:
|
|
36
|
+
|
|
37
|
+
- EyeProlog was wrong and was fixed to the published baseline;
|
|
38
|
+
- the external expectation reflects a different permitted implementation-defined
|
|
39
|
+
or implementation-dependent choice;
|
|
40
|
+
- the external fixture itself targets behavior outside the published baseline;
|
|
41
|
+
- a later STC draft proposes a change that is not yet a published Corrigendum;
|
|
42
|
+
- the behavior is an EyeProlog implementation-specific extension excluded from
|
|
43
|
+
`--iso-strict`; or
|
|
44
|
+
- the condition is genuinely not applicable to EyeProlog's declared processor
|
|
45
|
+
model.
|
|
46
|
+
|
|
47
|
+
An unexplained mismatch, host exception, skipped vendored row, or documentation
|
|
48
|
+
claim without executable support keeps the relevant exit criterion open.
|
|
49
|
+
|
|
50
|
+
## Release use
|
|
51
|
+
|
|
52
|
+
`ISO-COMPLIANCE.md` is the release-facing status ledger. This file is the exit
|
|
53
|
+
checklist behind it. Closing a row here must not be inferred solely from a test
|
|
54
|
+
count: the corresponding normative or external evidence must be identifiable
|
|
55
|
+
and the user-facing documentation must describe the same boundary.
|
|
@@ -75,9 +75,9 @@ Status values are:
|
|
|
75
75
|
| 9.1.4.1 | Floating-point rounding function `rndF` | Floating values and operations use ECMAScript `Number` (IEEE-754 binary64) and the host's specified binary64 arithmetic/conversions. | **defined** — `src/iso-arithmetic.js`, `src/number-value.js`. |
|
|
76
76
|
| 9.1.4.2 | Floating-point result function for operations whose result is governed only by `resultF` | EyeProlog chooses `round(x)` rather than the optional exceptional value `underflow`. ECMAScript binary64 arithmetic therefore preserves a representable subnormal result and rounds a still-smaller generic arithmetic result to `0.0`, consistently with float-token, `number_chars/2`, and `number_codes/2` input. The published Part 1 `**/2` and Corrigendum 2 `^/2` tables still contain separate unconditional underflow rows, which strict mode retains; post-N289 STC #75 proposes making those two power rows conditional on this `resultF` choice and is tracked separately as draft work. `exp/1` has its own published exceptional condition and is not the subject of STC #75. | **defined** — arithmetic evaluation in `src/iso-arithmetic.js` and parser/number conversion; strict exceptional-value regressions. |
|
|
77
77
|
| 9.1.4.3 | Approximate-addition function | ECMAScript binary64 addition is used; subtraction is implemented through the corresponding host operation and all finite results remain binary64 values. | **defined** — arithmetic evaluation in `src/iso-arithmetic.js`. |
|
|
78
|
-
| 9.4 | Representation of negative integers for bitwise operations | BigInt's unbounded signed binary semantics are used, equivalent to an infinite two's-complement sign extension for bitwise operations. | **defined** — `src/iso-arithmetic.js` BigInt bitwise operators. |
|
|
79
|
-
| 9.4.1 | Right shift of negative integers and unusual shift counts | `>>` is arithmetic/sign-propagating. A negative count reverses direction according to JavaScript BigInt shift semantics; there is no finite integer bit-size ceiling in the Prolog model. | **defined** — `a >> b` in `src/iso-arithmetic.js
|
|
80
|
-
| 9.4.2 | Left shift of negative integers and unusual shift counts | `<<` uses BigInt signed shift semantics; a negative count reverses direction. Resource exhaustion remains possible for very large results. | **defined** — `a << b` in `src/iso-arithmetic.js
|
|
78
|
+
| 9.4 | Representation of negative integers for bitwise operations | BigInt's unbounded signed binary semantics are used, equivalent to an infinite two's-complement sign extension for bitwise operations. | **defined** — `src/iso-arithmetic.js` BigInt bitwise operators and strict Clause 9.4 boundary regressions. |
|
|
79
|
+
| 9.4.1 | Right shift of negative integers and unusual shift counts | `>>` is arithmetic/sign-propagating. A negative count reverses direction according to JavaScript BigInt shift semantics; there is no finite integer bit-size ceiling in the Prolog model. | **defined** — `a >> b` in `src/iso-arithmetic.js`; strict regressions pin negative operands/counts. |
|
|
80
|
+
| 9.4.2 | Left shift of negative integers and unusual shift counts | `<<` uses BigInt signed shift semantics; a negative count reverses direction. Resource exhaustion remains possible for very large results. | **defined** — `a << b` in `src/iso-arithmetic.js`; strict regressions pin negative counts and resource exhaustion. |
|
|
81
81
|
| 9.4.3 | Bitwise AND with negative operands | BigInt infinite-two's-complement semantics. | **defined** — `a & b`. |
|
|
82
82
|
| 9.4.4 | Bitwise OR with negative operands | BigInt infinite-two's-complement semantics. | **defined** — `a \| b`. |
|
|
83
83
|
| 9.4.5 | Bitwise complement | BigInt complement, i.e. `~N = -N-1`. | **defined** — `~a`. |
|
|
@@ -118,11 +118,11 @@ families; `--iso-strict` is intended to remove their Part 1 interpretation.
|
|
|
118
118
|
| 5.5.3 Character-conversion mapping | No non-identity initial `Convc` extension | Identity initial mapping. |
|
|
119
119
|
| 5.5.4 Types | The normal JavaScript API exposes an implementation-specific string term `stringTerm(Text)`. It is disjoint from the five Part 1 term types; normal term order places it after atoms and before compound terms, and normal `atomic/1` treats it as atomic. It has no Prolog source token syntax (double-quoted source still follows `double_quotes`), is non-callable for term-to-clause conversion, is not evaluable as an arithmetic expression, and writes as a double-quoted host string. | Strict mode rejects a programmatic string term at program/goal entry with `representation_error(term)`, so the additional type cannot enter the Part 1 execution domain. **defined** — `src/term.js`, `src/program.js`, `src/solver.js`; strict API-boundary regression. |
|
|
120
120
|
| 5.5.5 Directives | `module/2`, `use_module/1-2`, `meta_predicate/1` and normal-profile library behavior | Rejected as implementation-specific Part 1 directives. |
|
|
121
|
-
| 5.5.6 Side effects |
|
|
121
|
+
| 5.5.6 Side effects | Normal mode adds `statistics/0-2`, cleanup/library state, and optional proof/statistics host instrumentation. | The strict registry excludes Prolog-visible statistics/cleanup/library adapters; ordinary Part 1 I/O/database/flag/operator side effects remain. Host proof/statistics collection observes execution through the embedding API rather than adding a strict Prolog goal effect. **covered** — strict registry/execution regression. |
|
|
122
122
|
| 5.5.7 Control constructs | `tnot/1` and normal-profile execution optimizations | `tnot/1` is absent; automatic tabling/recursion guards are disabled. |
|
|
123
123
|
| 5.5.8 Flags | `occurs_check` | Absent in strict mode. |
|
|
124
124
|
| 5.5.9 Built-in predicates | EyeProlog libraries, CLP(Z), statistics, Part 3 `phrase/2-3`, and interop autoloaded predicates | Strict registry contains only the Part 1 + Corrigenda core registry. |
|
|
125
|
-
| 5.5.10 Evaluable functors |
|
|
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
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` option `double_quotes(true|false)`. Strict core excludes that extension and accepts only the Part 1 plus Corrigendum 3 write-option surface; unknown extension options raise `domain_error(write_option,...)`. |
|
|
128
128
|
|
|
@@ -139,6 +139,7 @@ For portability work, EyeProlog also documents these choices even though the
|
|
|
139
139
|
- distinct variables are ordered by first encounter within the operation that
|
|
140
140
|
needs a stable ordering;
|
|
141
141
|
- expression arguments are evaluated left-to-right by the JavaScript evaluator;
|
|
142
|
+
- Corrigendum 2 mixed integer/float `max/2` and `min/2` use exact mathematical comparison and return one of the original operands without forcing integer-to-float conversion; equal values choose the left operand, so its original numeric type is preserved. EyeProlog does not elect the optional mixed-type `undefined` or `float_overflow` outcomes solely because the operand types differ;
|
|
142
143
|
- generated variable names use EyeProlog's stable `_A`, `_B`, ... style within
|
|
143
144
|
a write operation/top-level query;
|
|
144
145
|
- resource and syntax-error detail atoms are EyeProlog implementation details;
|
|
@@ -5,11 +5,14 @@ Technical Corrigenda 1:2007, 2:2012, and 3:2017. This matrix links the standard
|
|
|
5
5
|
families to executable coverage; `conformance-report.md` supplies the generated
|
|
6
6
|
case totals. [ISO-COMPLIANCE.md](ISO-COMPLIANCE.md) tracks the processor-level
|
|
7
7
|
compliance audit and the remaining work before a full conformance claim.
|
|
8
|
+
`ISO-TERM-SEMANTICS-MATRIX.md` and `ISO-EVALUABLE-FUNCTOR-MATRIX.md` provide
|
|
9
|
+
the closed row-level Clause 7.1-7.3 and 7.9/Clause 9 ledgers;
|
|
10
|
+
`ISO-EXIT-CRITERIA.md` records the remaining project-level exit conditions.
|
|
8
11
|
|
|
9
12
|
| Standard area | Implementation | Representative executable coverage |
|
|
10
13
|
| --- | --- | --- |
|
|
11
|
-
| Clause 6 lexical and term syntax | tokenizer, operator parser, lists, curly terms, quotes, numeric syntax, comments, Unicode-scalar PCS/collation | `scryer_lexical_terms`, `lexical_and_curly_terms`, `double_quoted_lists`, `corrigendum1_double_quote_operator`, `wg17_syntax_high_risk`, `wg17_invalid_octal_escape`, `wg17_unterminated_quoted_token`, `wg17_literal_newline_in_quote`, `wg17_non_iso_escape`, strict PCS/collation tests in `run-iso-strict.mjs`, syntax error cases |
|
|
12
|
-
| Clause 7 term order and unification | finite-tree unification, identity, standard order,
|
|
14
|
+
| Clause 6 lexical and term syntax | tokenizer, operator parser, lists, curly terms, quotes, numeric syntax, comments, Unicode-scalar PCS/collation | `scryer_lexical_terms`, `lexical_and_curly_terms`, `double_quoted_lists`, `corrigendum1_double_quote_operator`, `wg17_syntax_high_risk`, `wg17_invalid_octal_escape`, `wg17_unterminated_quoted_token`, `wg17_literal_newline_in_quote`, `wg17_non_iso_escape`, strict PCS/collation tests in `run-iso-strict.mjs`, syntax error cases, and a cross-profile check that all strict-success WG17 cases retain the same normal-profile outcome |
|
|
15
|
+
| Clause 7.1-7.3 term types, term order and unification | five strict term types, derived term notions, finite-tree unification, identity, standard order, occurs-check behavior | `ISO-TERM-SEMANTICS-MATRIX.md`, `unification_control_information`, `swipl_occurs_check`, `term_modes_and_ordering`, `logtalk_compare_standard_order`, and the strict 7.1-7.3 closure regression |
|
|
13
16
|
| Clause 7 control and exceptions | call, cut, conjunction, disjunction, if-then-else, catch and throw | `cut_control`, `control_and_terms`, `exceptions_and_flags`, `corrigenda_catch_callability`, `throw_copies_ball` |
|
|
14
17
|
| 8.2-8.5 term predicates | unification, Corrigendum 2 tests, comparison, sorting, creation and decomposition | `corrigenda_term_predicates`, `corrigenda_sort_keysort`, `logtalk_arg_unification`, `logtalk_univ`, associated error cases, and the one-row-per-mode/error 8.2-8.5 slice in `ISO-BUILTIN-MODE-ERROR-MATRIX.md`, including conditional finite-`max_arity` branches |
|
|
15
18
|
| 8.6-8.7 arithmetic predicates | `is/2` and all six arithmetic comparisons | `arithmetic`, comparison cases, isolated evaluation errors, and the explicit row-level 8.6-8.7 mode/error-condition audit |
|
|
@@ -18,7 +21,7 @@ compliance audit and the remaining work before a full conformance claim.
|
|
|
18
21
|
| 8.15 logic and control | negation, once, repeat, `call/2` through `call/8`, `false/0` | `logtalk_once`, `corrigenda_call_closure`, `false_builtin`, plus the complete 8.15 row-audit in `ISO-BUILTIN-MODE-ERROR-MATRIX.md` |
|
|
19
22
|
| 8.16 atomic processing | atoms, characters, codes and number conversion with prescribed errors | `atomic_term_processing`, focused forward/reverse cases, parenthesized-number rejection, Logtalk-derived cases, and the complete 8.16 mode/error slice in `ISO-BUILTIN-MODE-ERROR-MATRIX.md` |
|
|
20
23
|
| 8.17 flags and halt | complete required Part 1 flag set, selected defaults, standard value domains/changeability, and halt status handling | `exceptions_and_flags`, `remaining_builtins_and_directives`, the complete strict flag audit, halt cases, and explicit 8.17 rows in `ISO-BUILTIN-MODE-ERROR-MATRIX.md` |
|
|
21
|
-
| Clause 9 evaluable functors | integer, float, rounding, transcendental and bitwise operations | `arithmetic`, `corrigenda_arithmetic`, `corrigenda_atan2_zero`, `corrigenda_integer_negative_power`,
|
|
24
|
+
| Clause 7.9 / Clause 9 evaluable functors | recursive expression evaluation plus integer, float, rounding, transcendental and bitwise operations | `ISO-EVALUABLE-FUNCTOR-MATRIX.md`, `arithmetic`, `corrigenda_arithmetic`, `corrigenda_atan2_zero`, `corrigenda_integer_negative_power`, the strict row-closure regression (including huge-integer float-only template precedence), published `exp/1`/`**/2`/`^/2` underflow with STC #75 tracked separately, mixed comparison/max/min choices, signed bitwise/negative-shift semantics, and unbounded-integer resource normalization |
|
|
22
25
|
| Module compatibility profile (related to ISO/IEC 13211-2 and later WG17 amendment work) | module declarations, exports, imports, qualification, meta-predicate context | `modules/qualified_call`, `modules/selective_library_import`, `dcg_module_nonterminal_indicator` |
|
|
23
26
|
| Part 3-oriented DCG compatibility profile | `-->`, terminal and partial sequences, grammar control constructs, semicontexts, nonterminal indicators, modules, `phrase/2-3`, steadfastness and errors | `dcg_terminals_and_remainder`, `dcg_control_constructs`, `dcg_partial_sequences`, `dcg_phrase_steadfastness`, `dcg_dynamic_nonterminal_indicator`, `logtalk_dcg_phrase_identity`, `logtalk_dcg_semicontexts`, DCG error and precedence cases |
|
|
24
27
|
|
|
@@ -17,7 +17,7 @@ certification claim.
|
|
|
17
17
|
| Requirement | Status | Current evidence / remaining work |
|
|
18
18
|
| --- | --- | --- |
|
|
19
19
|
| 5.1(a) prepare conforming Prolog text | audit | parser/preparation tests, directives, include behavior, preparation-time operators/flags/character conversion, and the complete vendored WG17 syntax matrix; the remaining Clause 6/7.4 shall-by-shall map is still open |
|
|
20
|
-
| 5.1(b) execute conforming Prolog goals | audit |
|
|
20
|
+
| 5.1(b) execute conforming Prolog goals | audit | the 7.1-7.3 term-semantics matrix, 7.9/Clause 9 evaluable-functor matrix, and complete 8.2-8.17 built-in row audit are closed; remaining dependency rows are 7.4-7.8, higher-level 7.10, and residual processor-level 7.12 semantics |
|
|
21
21
|
| 5.1(c) reject nonconforming text/read terms | audit | syntax-error corpus, WG17 negative syntax cases, strict extension rejection; exhaustive Clause 6 rejection mapping remains open |
|
|
22
22
|
| 5.1(d) specify permitted variations | covered | `ISO-IMPLEMENTATION-DEFINED.md` records the Part 1 implementation-defined choices and implementation-specific extension families |
|
|
23
23
|
| 5.1(e) offer a strictly conforming mode | covered | CLI `--iso-strict` and API `isoStrict: true`; registry/directive/operator/flag extension filtering plus disabled implementation-specific execution shortcuts |
|
|
@@ -27,7 +27,7 @@ certification claim.
|
|
|
27
27
|
| Requirement | Status | Current evidence / remaining work |
|
|
28
28
|
| --- | --- | --- |
|
|
29
29
|
| 5.2 conforming and strictly conforming Prolog text boundary | audit | strict parser accepts Part 1 + Corrigenda syntax plus implementation-defined PCS choices and rejects implementation-specific language facilities; full Clause 6/7.4 dependency audit remains open |
|
|
30
|
-
| 5.3 conforming and strictly conforming Prolog goal boundary | audit | strict registry/control/evaluable filtering
|
|
30
|
+
| 5.3 conforming and strictly conforming Prolog goal boundary | audit | strict registry/control/evaluable filtering plus closed 7.1-7.3, 7.9/Clause 9, and 8.2-8.17 row matrices; remaining general execution/control, higher-level stream, and processor-error semantics keep the top-level goal boundary open |
|
|
31
31
|
| 5.4 accompanying documentation for implementation-defined and implementation-specific features | covered | `ISO-IMPLEMENTATION-DEFINED.md`, *The Art of EyeProlog*, strict-boundary documentation, and release-facing conformance ledgers |
|
|
32
32
|
|
|
33
33
|
## 5.5 — extension boundaries
|
|
@@ -35,21 +35,22 @@ certification claim.
|
|
|
35
35
|
| Requirement | Status | EyeProlog decision / evidence |
|
|
36
36
|
| --- | --- | --- |
|
|
37
37
|
| 5.5 general extension rule | covered | normal mode may provide documented extensions; strict mode removes their Part 1 interpretation rather than changing implementation-defined choices |
|
|
38
|
-
| 5.5.1 syntax extensions preserve standard token/text meaning | audit | WG17 syntax is a release gate and strict mode removes module/DCG/quad interpretation
|
|
38
|
+
| 5.5.1 syntax extensions preserve standard token/text meaning | audit | WG17 syntax is a release gate and strict mode removes module/DCG/quad interpretation. Every vendored WG17 case that succeeds in the Part 1 strict reader now has an identical normal-profile observable outcome, directly checking that normal syntax extensions do not reinterpret accepted standard text. A complete one-row preservation map for every Clause 6 production remains open |
|
|
39
39
|
| 5.5.2 additional predefined operators | covered | strict mode starts from the Part 1 predefined operator table; normal-profile extra operators are documented and filtered |
|
|
40
40
|
| 5.5.3 initial character-conversion mapping | covered | identity initial mapping; user changes are exercised through preparation/execution `char_conversion/2` behavior |
|
|
41
41
|
| 5.5.4 additional term types | covered | the normal JavaScript API's `stringTerm(Text)` is documented as an implementation-specific sixth term type, including disjointness, ordering, clause conversion, lack of source token syntax, expression behavior, and writing; strict program/goal entry rejects that type with `representation_error(term)` |
|
|
42
42
|
| 5.5.5 additional directives | covered | normal module/library directives are documented implementation-specific features and are rejected by strict mode |
|
|
43
|
-
| 5.5.6 additional side effects |
|
|
43
|
+
| 5.5.6 additional side effects | covered | normal-profile `statistics/0-2`, cleanup/library state, proof/statistics host instrumentation, and other extension effects are documented outside the Part 1 core; strict registry tests exclude the Prolog-visible statistics/cleanup extensions. Host instrumentation is an embedding observation rather than an extra strict Prolog goal effect |
|
|
44
44
|
| 5.5.7 additional control constructs | covered | `tnot/1` and implementation-specific execution optimizations are absent/disabled in strict mode; standard control constructs remain separately audited |
|
|
45
45
|
| 5.5.8 additional flags | covered | normal `occurs_check` extension is absent from strict mode; the Part 1 flag family is fully audited |
|
|
46
46
|
| 5.5.9 additional built-in predicates and error forms | covered | strict registry excludes normal-profile library/native additions; `ISO-BUILTIN-MODE-ERROR-MATRIX.md` closes the complete 8.2-8.17 family row-by-row; simultaneous-error choices are documented per 7.12 rather than treated as a global table-order mandate |
|
|
47
|
-
| 5.5.10 additional evaluable functors/types |
|
|
47
|
+
| 5.5.10 additional evaluable functors/types | covered | strict mode rejects the normal-profile evaluable `e` extension while retaining the full Part 1 + Corrigenda arithmetic set. `ISO-EVALUABLE-FUNCTOR-MATRIX.md` now closes the Clause 9 semantic/error audit and pins the 9.1.4.2 `resultF`, mixed-type `max/2`/`min/2`, and signed bitwise/shift choices. Post-N289 STC #75 remains separate from the published baseline |
|
|
48
48
|
| 5.5.11 reserved atoms | not applicable | EyeProlog declares no reserved-atom extension; extension names remain ordinary atoms unless used in a documented syntactic/predicate/directive role |
|
|
49
49
|
|
|
50
50
|
## Exit-use rule
|
|
51
51
|
|
|
52
52
|
A top-level row stays `audit` until all of the normative clauses it depends on
|
|
53
53
|
have explicit pass, not-applicable, or documented implementation-defined
|
|
54
|
-
outcomes.
|
|
55
|
-
a
|
|
54
|
+
outcomes. `ISO-EXIT-CRITERIA.md` records the same dependency closure from the
|
|
55
|
+
release-exit perspective. This prevents a large green regression suite from
|
|
56
|
+
being mistaken for a completed processor-requirement audit.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# ISO Part 1 term-semantics audit matrix
|
|
2
|
+
|
|
3
|
+
This file closes the Clause 7.1-7.3 audit at a finer granularity than the
|
|
4
|
+
release-facing `ISO-COMPLIANCE.md`. The normative baseline is ISO/IEC
|
|
5
|
+
13211-1:1995 plus Technical Corrigenda 1-3.
|
|
6
|
+
|
|
7
|
+
`covered` means the applicable Part 1 semantic rule has an implementation
|
|
8
|
+
choice where the standard permits one and executable evidence in the strict
|
|
9
|
+
profile. This matrix is implementation evidence, not independent
|
|
10
|
+
certification.
|
|
11
|
+
|
|
12
|
+
## 7.1 - term types and derived term notions
|
|
13
|
+
|
|
14
|
+
| Requirement family | Status | EyeProlog evidence |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| Five mutually exclusive core term types | covered | strict type predicates and ordering tests cover variable, float, integer, atom, and compound; the normal-profile host string term is rejected at strict program/goal entry |
|
|
17
|
+
| Atomic-term boundary | covered | integers, floats, and atoms satisfy the atomic predicates; compound terms do not |
|
|
18
|
+
| Variable set / repeated-variable identity | covered | `term_variables/2`, read-term Corrigendum 3 variable metadata, `copy_term/2`, collector tests, and repeated-variable unification preserve identity and first occurrence |
|
|
19
|
+
| Existential/free-variable use by collectors | covered | `bagof/3` and `setof/3` mode/semantic suites cover explicit `^/2` existential variables and grouping by free variables |
|
|
20
|
+
| Integer type | covered | `bounded=false` selects the full mathematical-integer model; `max_integer`/`min_integer` therefore have no value and host exhaustion is translated to `resource_error(memory)` rather than a numeric representation bound |
|
|
21
|
+
| Byte and character-code subranges | covered | byte I/O rows and the Unicode-scalar processor character set are separately pinned; byte values remain 0..255 while character codes follow the declared PCS |
|
|
22
|
+
| Floating-point type | covered | ECMAScript IEEE-754 binary64 is the documented implementation-defined float model; input overflow and arithmetic exceptional values have strict tests |
|
|
23
|
+
| Atoms and one-character atoms | covered | parser/reader/writer, atom conversion, character conversion, and PCS/collation suites cover atom identity and one-character atoms |
|
|
24
|
+
| Compound term / arguments / arity | covered | `functor/3`, `arg/3`, `=../2`, parser, predicate-indicator operations, and `max_arity=unbounded` tests cover construction/decomposition and arbitrary semantic arity |
|
|
25
|
+
| Lists, predicate indicators, and related derived term notions | covered | list, proper-list, sort/keysort, predicate-indicator, `current_predicate/1`, `abolish/1`, `call/N`, and module/DCG boundary tests exercise the applicable Part 1 derived forms |
|
|
26
|
+
| Variants / renamed copies | covered | `copy_term/2`, all-solutions collectors, clause selection, and Corrigendum variable-name tests verify renamed-copy behavior without sharing source variables |
|
|
27
|
+
|
|
28
|
+
## 7.2 - standard order of terms
|
|
29
|
+
|
|
30
|
+
| Rule | Status | EyeProlog evidence / decision |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| Type order | covered | strict gate pins `variable < float < integer < atom < compound` |
|
|
33
|
+
| Distinct variable order | covered | implementation-dependent stable encounter order is documented in `ISO-IMPLEMENTATION-DEFINED.md`; sort/collector operations keep that order stable for the operation |
|
|
34
|
+
| Float order | covered | numeric floating ordering is used within the float type |
|
|
35
|
+
| Integer order | covered | mathematical BigInt ordering is used within the integer type |
|
|
36
|
+
| Atom order | covered | null atom and lexicographic ordering use the declared Unicode-scalar collating sequence |
|
|
37
|
+
| Compound order | covered | arity precedes functor name, then arguments are compared left-to-right by standard term order; strict regression pins representative arity/functor cases |
|
|
38
|
+
|
|
39
|
+
## 7.3 - unification
|
|
40
|
+
|
|
41
|
+
| Rule | Status | EyeProlog evidence / decision |
|
|
42
|
+
| --- | --- | --- |
|
|
43
|
+
| NSTO unifiable terms produce an MGU | covered | equality, clause-head matching, repeated-variable, list-tail, nested-compound, and explicit strict regression cases |
|
|
44
|
+
| NSTO non-unifiable terms fail | covered | scalar/functor/arity/repeated-variable mismatch suites and strict regression cases |
|
|
45
|
+
| STO ordinary unification | covered | Part 1 leaves the result undefined; EyeProlog consistently performs an occurs check and fails cyclic bindings, which is one permitted processor behavior for this undefined case |
|
|
46
|
+
| Explicit occurs-check unification | covered | `unify_with_occurs_check/2` succeeds for finite unifiable terms and fails positive-occurs-check cases |
|
|
47
|
+
| Implicit unification uses the same finite-tree model | covered | clause-head matching, database operations, control constructs, and collectors share the same unifier; the vendored Prologue STO annotations remain external comparison evidence rather than redefining Part 1 behavior |
|
|
48
|
+
|
|
49
|
+
## Closure note
|
|
50
|
+
|
|
51
|
+
The Clause 7.1-7.3 row is `covered` only for the published Part 1 + Corrigenda
|
|
52
|
+
baseline. Normal-mode string terms and other EyeProlog extensions remain outside
|
|
53
|
+
this strict five-type model and are documented separately under Clause 5.5.
|
|
@@ -10,9 +10,13 @@ and proof output test the behavior of the JavaScript implementation.
|
|
|
10
10
|
[ISO-MATRIX.md](ISO-MATRIX.md) maps Part 1 normative clause families, all three
|
|
11
11
|
corrigenda, plus EyeProlog's module and DCG compatibility profiles, to representative
|
|
12
12
|
executable cases. [ISO-BUILTIN-MODE-ERROR-MATRIX.md](ISO-BUILTIN-MODE-ERROR-MATRIX.md)
|
|
13
|
-
tracks the row-by-row built-in audit,
|
|
14
|
-
[ISO-
|
|
15
|
-
|
|
13
|
+
tracks the row-by-row built-in audit,
|
|
14
|
+
[ISO-TERM-SEMANTICS-MATRIX.md](ISO-TERM-SEMANTICS-MATRIX.md) closes 7.1-7.3,
|
|
15
|
+
[ISO-EVALUABLE-FUNCTOR-MATRIX.md](ISO-EVALUABLE-FUNCTOR-MATRIX.md) closes
|
|
16
|
+
7.9/Clause 9, and [ISO-PROCESSOR-REQUIREMENTS.md](ISO-PROCESSOR-REQUIREMENTS.md)
|
|
17
|
+
decomposes the Clause 5 processor obligations.
|
|
18
|
+
[ISO-EXIT-CRITERIA.md](ISO-EXIT-CRITERIA.md) makes the remaining normative and
|
|
19
|
+
external-corpus release-exit conditions explicit. [WG17-SYNTAX-STATUS.md](WG17-SYNTAX-STATUS.md) records the
|
|
16
20
|
complete one-to-one trace for the vendored active upstream WG17 syntax cases.
|
|
17
21
|
[STC-DRAFT-STATUS.md](STC-DRAFT-STATUS.md) separately tracks executable
|
|
18
22
|
implementation questions from the post-N289 working draft (reviewed through the 2026-08-23 items #73-#76); those cases are
|
|
@@ -24,9 +28,11 @@ predicate indicators listed in Appendix B of the book across the Part 1 strict-c
|
|
|
24
28
|
target and the normal-mode module/DCG compatibility families. [ISO-COMPLIANCE.md](ISO-COMPLIANCE.md) is the explicit
|
|
25
29
|
release-facing ledger for the Part 1 strict-core audit. This suite is
|
|
26
30
|
still not an independent certification of every processor requirement or lexical
|
|
27
|
-
edge. The complete 8.2-8.17 built-in family
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
edge. The complete 8.2-8.17 built-in family, 7.1-7.3 term semantics, and
|
|
32
|
+
7.9/Clause 9 expression/evaluable-functor families are now tracked and closed
|
|
33
|
+
at row level. The remaining Clause 6, 7.4-7.8, higher-level 7.10/7.12,
|
|
34
|
+
processor-dependency, and external-corpus criteria stay explicitly open in the
|
|
35
|
+
dedicated audit files. Cases under `iso/`
|
|
30
36
|
identify standards-derived behavior; other directories cover EyeProlog host
|
|
31
37
|
contracts and extensions. EyeProlog-only execution features such as automatic
|
|
32
38
|
tabling and `tnot/1` well-founded negation are outside the Part 1 strict-core
|
package/test/run-iso-strict.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Env,
|
|
9
9
|
compound,
|
|
10
10
|
createStrictIsoRegistry,
|
|
11
|
+
getEyePrologRegistry,
|
|
11
12
|
parseGoalText,
|
|
12
13
|
parseProgramText,
|
|
13
14
|
run,
|
|
@@ -196,6 +197,31 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
196
197
|
'representation_error(term)', 'strict program construction rejects API string terms');
|
|
197
198
|
});
|
|
198
199
|
|
|
200
|
+
|
|
201
|
+
reporter.test('closes the ISO 7.1-7.3 term-semantics rows', () => {
|
|
202
|
+
for (const goal of [
|
|
203
|
+
'var(X), \\+ nonvar(X)',
|
|
204
|
+
'integer(1), float(1.0), atom(a), compound(f(a))',
|
|
205
|
+
'atomic(1), atomic(1.0), atomic(a), \\+ atomic(f(a))',
|
|
206
|
+
'term_variables(f(X,Y,X),[X,Y])',
|
|
207
|
+
'f(X,a)=f(b,Y), X==b, Y==a',
|
|
208
|
+
'\\+ (f(a)=g(a))',
|
|
209
|
+
'\\+ (X=f(X))',
|
|
210
|
+
'\\+ unify_with_occurs_check(X,f(X))',
|
|
211
|
+
'copy_term(f(X,X),f(Y,Y)), X \\== Y',
|
|
212
|
+
'f(a) @< f(a,b)',
|
|
213
|
+
'f(a) @< g(a)',
|
|
214
|
+
]) equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 1, goal);
|
|
215
|
+
|
|
216
|
+
const program = Program.parse('', { isoStrict: true });
|
|
217
|
+
const solver = new Solver(program, { isoStrict: true });
|
|
218
|
+
const answers = (goal) => [...solver.solve([parseGoalText(goal, { isoStrict: true })], new Env(), 0)].length;
|
|
219
|
+
equal(answers('X @< 1.0'), 1, 'variable < float');
|
|
220
|
+
equal(answers('1.0 @< 1'), 1, 'float < integer');
|
|
221
|
+
equal(answers('1 @< a'), 1, 'integer < atom');
|
|
222
|
+
equal(answers('a @< f(a)'), 1, 'atom < compound');
|
|
223
|
+
});
|
|
224
|
+
|
|
199
225
|
reporter.test('keeps the strict write-option surface to Part 1 plus Corrigendum 3', () => {
|
|
200
226
|
const strictError = capture(() => run('', {
|
|
201
227
|
isoStrict: true,
|
|
@@ -673,6 +699,143 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
673
699
|
'evaluation_error(undefined)', 'zero-negative power precedes exponent conversion overflow');
|
|
674
700
|
});
|
|
675
701
|
|
|
702
|
+
reporter.test('closes the 5.5.6 additional side-effect extension boundary', () => {
|
|
703
|
+
const normalRegistry = getEyePrologRegistry();
|
|
704
|
+
const strictRegistry = createStrictIsoRegistry();
|
|
705
|
+
equal(Boolean(normalRegistry.get('statistics', 0)), true, 'normal statistics/0 side-effect extension');
|
|
706
|
+
equal(Boolean(strictRegistry.get('statistics', 0)), false, 'strict statistics/0 excluded');
|
|
707
|
+
equal(Boolean(strictRegistry.get('statistics', 2)), false, 'strict statistics/2 excluded');
|
|
708
|
+
equal(Boolean(strictRegistry.get('call_cleanup', 2)), false, 'strict cleanup extension excluded');
|
|
709
|
+
equal(Boolean(strictRegistry.get('setup_call_cleanup', 3)), false, 'strict setup/cleanup extension excluded');
|
|
710
|
+
equal(capture(() => run('', { isoStrict: true, goal: 'statistics' })).formal,
|
|
711
|
+
'existence_error(procedure)', 'strict execution cannot invoke statistics/0');
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
reporter.test('closes the 5.5.10 evaluable-functor extension boundary', () => {
|
|
715
|
+
const strictExtension = capture(() => run('', { isoStrict: true, goal: 'X is e' }));
|
|
716
|
+
equal(strictExtension.formal, 'type_error(evaluable)', 'normal-only e/0 is not evaluable in strict mode');
|
|
717
|
+
equal(run('', { goal: 'X is e' }).stats.completed_goal_lists, 1, 'normal e/0 extension remains available');
|
|
718
|
+
|
|
719
|
+
for (const goal of [
|
|
720
|
+
'X is +1',
|
|
721
|
+
'X is -7 div 3',
|
|
722
|
+
'X is max(2,3.0)',
|
|
723
|
+
'X is min(2.0,3)',
|
|
724
|
+
'X is 3^3',
|
|
725
|
+
'X is asin(0)',
|
|
726
|
+
'X is acos(1)',
|
|
727
|
+
'X is atan2(1,0)',
|
|
728
|
+
'X is tan(0)',
|
|
729
|
+
'X is pi',
|
|
730
|
+
'X is xor(10,12)',
|
|
731
|
+
]) equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 1, `Corrigendum evaluable ${goal}`);
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
reporter.test('pins Corrigendum 2 mixed-type max/min implementation-dependent behavior', () => {
|
|
735
|
+
for (const goal of [
|
|
736
|
+
'X is max(2.0,3), X == 3',
|
|
737
|
+
'X is max(2,3.0), X == 3.0',
|
|
738
|
+
'X is min(2.0,3), X == 2.0',
|
|
739
|
+
'X is min(2,3.0), X == 2',
|
|
740
|
+
'X is max(0,0.0), X == 0',
|
|
741
|
+
'X is max(0.0,0), X == 0.0',
|
|
742
|
+
]) equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 1, goal);
|
|
743
|
+
|
|
744
|
+
// Corrigendum 2 permits several mixed-type choices, including returning
|
|
745
|
+
// one of the original operands without converting the integer to float.
|
|
746
|
+
// EyeProlog compares the mathematical values exactly and preserves the
|
|
747
|
+
// selected operand's original type, so a huge integer does not create a
|
|
748
|
+
// float-overflow merely because the other operand is a float.
|
|
749
|
+
const huge = `1${'0'.repeat(400)}`;
|
|
750
|
+
equal(run('', { isoStrict: true, goal: `X is max(${huge},1.0), X == ${huge}` }).stats.completed_goal_lists,
|
|
751
|
+
1, 'mixed max/2 does not force integer-to-float conversion');
|
|
752
|
+
equal(run('', { isoStrict: true, goal: `X is min(${huge},1.0), X == 1.0` }).stats.completed_goal_lists,
|
|
753
|
+
1, 'mixed min/2 preserves selected float operand');
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
reporter.test('pins implementation-defined Clause 9.4 signed bitwise and shift behavior', () => {
|
|
757
|
+
for (const goal of [
|
|
758
|
+
'X is ((-16) >> 2), X == -4',
|
|
759
|
+
'X is (16 >> -2), X == 64',
|
|
760
|
+
'X is (16 << -2), X == 4',
|
|
761
|
+
'X is ((-1) /\\ 5), X == 5',
|
|
762
|
+
'X is ((-1) \\/ 5), X == -1',
|
|
763
|
+
'X is xor(-1,5), X == -6',
|
|
764
|
+
'X is \\ 5, X == -6',
|
|
765
|
+
]) equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 1, goal);
|
|
766
|
+
});
|
|
767
|
+
|
|
768
|
+
|
|
769
|
+
reporter.test('closes the ISO 7.9 and Clause 9 evaluable-functor rows', () => {
|
|
770
|
+
for (const goal of [
|
|
771
|
+
'X is 7+35, X==42',
|
|
772
|
+
'X is 7-35, X== -28',
|
|
773
|
+
'X is 7*5, X==35',
|
|
774
|
+
'X is 7/2, X =:= 3.5',
|
|
775
|
+
'X is 7//(-3), X== -2',
|
|
776
|
+
'X is 7 div (-3), X== -3',
|
|
777
|
+
'X is (-7) rem 3, X== -1',
|
|
778
|
+
'X is (-7) mod 3, X==2',
|
|
779
|
+
'X is +7, X==7',
|
|
780
|
+
'X is -7, X== -7',
|
|
781
|
+
'X is abs(-7), X==7',
|
|
782
|
+
'X is sign(-7), X== -1',
|
|
783
|
+
'X is float(7), X =:= 7.0',
|
|
784
|
+
'X is floor(1.9), X==1',
|
|
785
|
+
'X is truncate(-1.9), X== -1',
|
|
786
|
+
'X is round(1.4), X==1',
|
|
787
|
+
'X is ceiling(1.1), X==2',
|
|
788
|
+
'X is float_integer_part(1.5), X =:= 1.0',
|
|
789
|
+
'X is float_fractional_part(-1.5), X =:= -0.5',
|
|
790
|
+
'X is 2 ** 3, X =:= 8.0',
|
|
791
|
+
'X is sin(0), X =:= 0.0',
|
|
792
|
+
'X is cos(0), X =:= 1.0',
|
|
793
|
+
'X is atan(0), X =:= 0.0',
|
|
794
|
+
'X is exp(0), X =:= 1.0',
|
|
795
|
+
'X is log(1), X =:= 0.0',
|
|
796
|
+
'X is sqrt(4), X =:= 2.0',
|
|
797
|
+
'X is max(2,3.0), X==3.0',
|
|
798
|
+
'X is min(2.0,3), X==2.0',
|
|
799
|
+
'X is 3^3, X==27',
|
|
800
|
+
'X is asin(0), X =:= 0.0',
|
|
801
|
+
'X is acos(1), X =:= 0.0',
|
|
802
|
+
'X is atan2(1,0), X > 1.5',
|
|
803
|
+
'X is tan(0), X =:= 0.0',
|
|
804
|
+
'X is pi, X > 3.14',
|
|
805
|
+
'X is xor(10,12), X==6',
|
|
806
|
+
'X is (10 /\\ 12), X==8',
|
|
807
|
+
'X is (10 \\/ 12), X==14',
|
|
808
|
+
'X is (8 << 2), X==32',
|
|
809
|
+
'X is (8 >> 2), X==2',
|
|
810
|
+
'X is \\ 5, X== -6',
|
|
811
|
+
]) equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 1, goal);
|
|
812
|
+
|
|
813
|
+
const huge = `1${'0'.repeat(400)}`;
|
|
814
|
+
for (const functor of ['float_integer_part', 'float_fractional_part']) {
|
|
815
|
+
equal(capture(() => run('', { isoStrict: true, goal: `X is ${functor}(${huge})` })).formal,
|
|
816
|
+
'type_error(float)', `${functor}/1 float-only template precedes I->F overflow`);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
for (const [goal, formal, label] of [
|
|
820
|
+
['X is Y+1', 'instantiation_error', 'direct variable expression'],
|
|
821
|
+
['X is foo', 'type_error(evaluable)', 'non-evaluable atom'],
|
|
822
|
+
['X is 1.5 // 1', 'type_error(integer)', 'integer-only arithmetic'],
|
|
823
|
+
['X is floor(1)', 'type_error(float)', 'float-only rounding'],
|
|
824
|
+
['X is 1/0', 'evaluation_error(zero_divisor)', 'floating division zero'],
|
|
825
|
+
['X is 1 div 0', 'evaluation_error(zero_divisor)', 'integer division zero'],
|
|
826
|
+
['X is log(0)', 'evaluation_error(undefined)', 'log domain'],
|
|
827
|
+
['X is sqrt(-1)', 'evaluation_error(undefined)', 'sqrt domain'],
|
|
828
|
+
['X is asin(2)', 'evaluation_error(undefined)', 'asin domain'],
|
|
829
|
+
['X is acos(2)', 'evaluation_error(undefined)', 'acos domain'],
|
|
830
|
+
['X is atan2(0,0)', 'evaluation_error(undefined)', 'atan2 zero pair'],
|
|
831
|
+
['X is 0 ** -1', 'evaluation_error(undefined)', 'power zero-negative'],
|
|
832
|
+
['X is (-2) ** 0.5', 'evaluation_error(undefined)', 'negative-base power'],
|
|
833
|
+
['X is exp(1000.0)', 'evaluation_error(float_overflow)', 'transcendental overflow'],
|
|
834
|
+
['X is exp(-1000.0)', 'evaluation_error(underflow)', 'transcendental underflow'],
|
|
835
|
+
['X is 2.0 ** -1075.0', 'evaluation_error(underflow)', 'published power underflow'],
|
|
836
|
+
]) equal(capture(() => run('', { isoStrict: true, goal })).formal, formal, label);
|
|
837
|
+
});
|
|
838
|
+
|
|
676
839
|
reporter.test('uses the Part 1 mixed arithmetic comparison operations', () => {
|
|
677
840
|
// 8.7 converts the integer operand to float in mixed comparisons.
|
|
678
841
|
equal(run('', { isoStrict: true, goal: '18014398509481985 =:= 18014398509481984.0' }).stats.completed_goal_lists,
|
package/test/run-regression.mjs
CHANGED
|
@@ -1245,21 +1245,34 @@ c4 ?- call((!;1)).
|
|
|
1245
1245
|
run: () => {
|
|
1246
1246
|
const filename = path.join(testRoot, 'fixtures', 'prologue_quad_runner.pl');
|
|
1247
1247
|
const source = fs.readFileSync(filename, 'utf8');
|
|
1248
|
-
const
|
|
1248
|
+
const program = Program.parseSources([{
|
|
1249
1249
|
text: source,
|
|
1250
1250
|
filename,
|
|
1251
1251
|
baseDir: path.dirname(filename),
|
|
1252
|
-
}])
|
|
1253
|
-
assertEqual(
|
|
1252
|
+
}]);
|
|
1253
|
+
assertEqual(program.quads.length, 33, 'vendored quad total');
|
|
1254
|
+
const maxIntegerQuads = program.quads.filter(({ query }) =>
|
|
1255
|
+
termToString(query).includes('current_prolog_flag(max_integer, Max)'));
|
|
1256
|
+
assertEqual(maxIntegerQuads.length, 1, 'max_integer quad count');
|
|
1257
|
+
|
|
1258
|
+
// This regression is about the one deliberate ISO divergence in the
|
|
1259
|
+
// upstream Prologue fixture. Running all 33 records also explores two
|
|
1260
|
+
// intentionally non-terminating STO examples and used to dominate the
|
|
1261
|
+
// regression suite by several seconds, without adding evidence for
|
|
1262
|
+
// max_integer. Keep the full vendored corpus intact, but execute only
|
|
1263
|
+
// the relevant record here.
|
|
1264
|
+
program.quads = maxIntegerQuads;
|
|
1265
|
+
const result = publicApi.runQuads(program);
|
|
1254
1266
|
// The upstream working-draft quad accepts either integer overflow or
|
|
1255
1267
|
// Max=unbounded. ISO/IEC 13211-1 7.11.1.1 instead says that when
|
|
1256
1268
|
// bounded=false, current_prolog_flag(max_integer, N) fails. Preserve
|
|
1257
1269
|
// the upstream fixture unchanged and make that one deliberate
|
|
1258
1270
|
// standards-driven divergence explicit in the regression gate.
|
|
1259
|
-
assertEqual(result.
|
|
1271
|
+
assertEqual(result.total, 1, 'quad total');
|
|
1272
|
+
assertEqual(result.passed, 0, 'quad passed');
|
|
1260
1273
|
assertEqual(result.failed, 1, 'quad failed');
|
|
1261
1274
|
assertIncludes(result.stdout, 'current_prolog_flag(max_integer, Max)', 'max_integer divergence');
|
|
1262
|
-
assertIncludes(result.stdout, 'quads:
|
|
1275
|
+
assertIncludes(result.stdout, 'quads: 1 run, 0 passed, 1 failed.', 'quad report');
|
|
1263
1276
|
},
|
|
1264
1277
|
},
|
|
1265
1278
|
{
|
|
@@ -3531,6 +3544,21 @@ function documentationSyncCases() {
|
|
|
3531
3544
|
);
|
|
3532
3545
|
},
|
|
3533
3546
|
},
|
|
3547
|
+
{
|
|
3548
|
+
name: 'normal syntax extensions preserve successful WG17 Part 1 outcomes',
|
|
3549
|
+
run: () => {
|
|
3550
|
+
const fixture = readWg17SyntaxFixture();
|
|
3551
|
+
let checked = 0;
|
|
3552
|
+
for (const item of fixture.cases) {
|
|
3553
|
+
const strict = executeWg17Item(item);
|
|
3554
|
+
if (strict.type !== 'success') continue;
|
|
3555
|
+
const normal = executeWg17Item(item, { isoStrict: false });
|
|
3556
|
+
assertEqual(JSON.stringify(normal), JSON.stringify(strict), `WG17 #${item.id} cross-profile outcome`);
|
|
3557
|
+
checked++;
|
|
3558
|
+
}
|
|
3559
|
+
if (checked === 0) throw new Error('WG17 fixture has no successful Part 1 syntax cases');
|
|
3560
|
+
},
|
|
3561
|
+
},
|
|
3534
3562
|
{
|
|
3535
3563
|
name: 'WG17 stream-sensitive cases #270 and #271 follow the upstream input protocol',
|
|
3536
3564
|
run: () => {
|
|
@@ -3663,6 +3691,48 @@ function documentationSyncCases() {
|
|
|
3663
3691
|
assertIncludes(text, 'Implementation-specific features required to be documented by 5.4', '5.5 extension inventory');
|
|
3664
3692
|
},
|
|
3665
3693
|
},
|
|
3694
|
+
{
|
|
3695
|
+
name: 'ISO term and arithmetic row matrices are closed and linked',
|
|
3696
|
+
run: () => {
|
|
3697
|
+
const compliance = fs.readFileSync(path.join(testRoot, 'conformance', 'ISO-COMPLIANCE.md'), 'utf8');
|
|
3698
|
+
const terms = fs.readFileSync(path.join(testRoot, 'conformance', 'ISO-TERM-SEMANTICS-MATRIX.md'), 'utf8');
|
|
3699
|
+
const arithmetic = fs.readFileSync(path.join(testRoot, 'conformance', 'ISO-EVALUABLE-FUNCTOR-MATRIX.md'), 'utf8');
|
|
3700
|
+
assertIncludes(compliance, '| 7.1-7.3 — term types, term order, unification | covered |', '7.1-7.3 covered');
|
|
3701
|
+
assertIncludes(compliance, '| 7.9 — expression evaluation | covered |', '7.9 covered');
|
|
3702
|
+
assertIncludes(compliance, '| Clause 9 — evaluable functors | covered |', 'Clause 9 covered');
|
|
3703
|
+
assertIncludes(terms, '## 7.3 - unification', 'term unification row matrix');
|
|
3704
|
+
assertIncludes(arithmetic, '## 9.4 - bitwise functors', 'Clause 9.4 row matrix');
|
|
3705
|
+
assertIncludes(arithmetic, '`float_integer_part/1`, `float_fractional_part/1`', 'float-only conversion row');
|
|
3706
|
+
},
|
|
3707
|
+
},
|
|
3708
|
+
{
|
|
3709
|
+
name: 'ISO exit criteria keep remaining audit work explicit',
|
|
3710
|
+
run: () => {
|
|
3711
|
+
const exit = fs.readFileSync(path.join(testRoot, 'conformance', 'ISO-EXIT-CRITERIA.md'), 'utf8');
|
|
3712
|
+
for (const item of [
|
|
3713
|
+
'| Clause 6 lexical/syntactic requirements have explicit dispositions | open |',
|
|
3714
|
+
'| Clause 7 semantic requirements have explicit dispositions | open |',
|
|
3715
|
+
'| Clause 8 built-in modes/errors have explicit dispositions | covered |',
|
|
3716
|
+
'| Clause 9 evaluable-functor requirements have explicit dispositions | covered |',
|
|
3717
|
+
'| Independent external syntax corpus is an offline release gate | covered |',
|
|
3718
|
+
'| External conversion/variable-name comparisons used during the audit are reproducible offline | open |',
|
|
3719
|
+
'| No unexplained deviation remains in the release-facing ledger | open |',
|
|
3720
|
+
]) assertIncludes(exit, item, item);
|
|
3721
|
+
},
|
|
3722
|
+
},
|
|
3723
|
+
{
|
|
3724
|
+
name: 'public ISO documentation links the row matrices and exit checklist',
|
|
3725
|
+
run: () => {
|
|
3726
|
+
const readme = fs.readFileSync(path.join(packageRoot, 'README.md'), 'utf8');
|
|
3727
|
+
const book = fs.readFileSync(path.join(packageRoot, 'the-art-of-eyeprolog.md'), 'utf8');
|
|
3728
|
+
const profile = fs.readFileSync(path.join(packageRoot, 'why-eyeprolog.md'), 'utf8');
|
|
3729
|
+
for (const name of ['ISO-TERM-SEMANTICS-MATRIX.md', 'ISO-EVALUABLE-FUNCTOR-MATRIX.md', 'ISO-EXIT-CRITERIA.md']) {
|
|
3730
|
+
assertIncludes(readme, name, `README ${name}`);
|
|
3731
|
+
assertIncludes(book, name, `book ${name}`);
|
|
3732
|
+
}
|
|
3733
|
+
assertIncludes(profile, 'completed row-level 7.1-7.3 term-semantics and 7.9/Clause 9 arithmetic audits', 'Why EyeProlog audit state');
|
|
3734
|
+
},
|
|
3735
|
+
},
|
|
3666
3736
|
{
|
|
3667
3737
|
name: 'book is the single implementation reference',
|
|
3668
3738
|
run: () => assertArrayEqual(bookReferenceDocumentationIssues(), [], 'book reference documentation'),
|
package/test/run-wg17.mjs
CHANGED
|
@@ -33,13 +33,13 @@ function capturedStages(stdout) {
|
|
|
33
33
|
.map((match) => ({ output: match[2], variables: match[3] }));
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
function executeFinite(item) {
|
|
36
|
+
function executeFinite(item, isoStrict = true) {
|
|
37
37
|
try {
|
|
38
38
|
// Match the upstream protocol: the Query cell plus its terminating newline
|
|
39
39
|
// is input to read(G), G (and subsequent read/call stages when present).
|
|
40
40
|
// This is essential for stream-sensitive cases such as #270 and #271.
|
|
41
41
|
const result = run('', {
|
|
42
|
-
isoStrict
|
|
42
|
+
isoStrict,
|
|
43
43
|
goal: runnerStage(1, item.readCount ?? 16),
|
|
44
44
|
ioOptions: { input: `${item.input}\n` },
|
|
45
45
|
});
|
|
@@ -50,10 +50,10 @@ function executeFinite(item) {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
function executeWait(item) {
|
|
54
|
-
const program = Program.parse('', { isoStrict
|
|
53
|
+
function executeWait(item, isoStrict = true) {
|
|
54
|
+
const program = Program.parse('', { isoStrict });
|
|
55
55
|
const solver = new Solver(program, {
|
|
56
|
-
isoStrict
|
|
56
|
+
isoStrict,
|
|
57
57
|
ioOptions: { input: `${item.input}\n` },
|
|
58
58
|
});
|
|
59
59
|
const stream = solver.io.resolve('user_input');
|
|
@@ -63,7 +63,7 @@ function executeWait(item) {
|
|
|
63
63
|
return null;
|
|
64
64
|
};
|
|
65
65
|
const goal = parseGoalText('read_term(G, [])', {
|
|
66
|
-
isoStrict
|
|
66
|
+
isoStrict,
|
|
67
67
|
operatorDefinitions: [...program.operators.values()],
|
|
68
68
|
});
|
|
69
69
|
try {
|
|
@@ -310,10 +310,11 @@ export function wg17TestDescription(item) {
|
|
|
310
310
|
return `#${item.id} ${query} -> ${expected}`;
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
-
export function executeWg17Item(item) {
|
|
313
|
+
export function executeWg17Item(item, options = {}) {
|
|
314
|
+
const isoStrict = options.isoStrict ?? true;
|
|
314
315
|
return usesWaitMatcher(item.expected) || item.outcome?.type === 'waits'
|
|
315
|
-
? executeWait(item)
|
|
316
|
-
: executeFinite(item);
|
|
316
|
+
? executeWait(item, isoStrict)
|
|
317
|
+
: executeFinite(item, isoStrict);
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
function assertOutcome(item) {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -7589,13 +7589,22 @@ requirements whose normative `shall` clauses, option combinations, or error
|
|
|
7589
7589
|
precedence still need one-by-one closure. `test/conformance/ISO-MATRIX.md`
|
|
7590
7590
|
maps language families to representative executable cases.
|
|
7591
7591
|
`test/conformance/ISO-IMPLEMENTATION-DEFINED.md` is the ISO 5.4 decision
|
|
7592
|
-
index: it enumerates the Part 1 implementation-defined decisions
|
|
7593
|
-
implementation-specific extension families
|
|
7594
|
-
|
|
7595
|
-
|
|
7592
|
+
index: it enumerates the Part 1 implementation-defined decisions and the
|
|
7593
|
+
implementation-specific extension families without turning draft WG17/STC
|
|
7594
|
+
proposals into the licensed baseline. `ISO-TERM-SEMANTICS-MATRIX.md` closes the
|
|
7595
|
+
7.1-7.3 type/order/unification rows and `ISO-EVALUABLE-FUNCTOR-MATRIX.md` closes
|
|
7596
|
+
7.9/Clause 9 expression and arithmetic rows. `ISO-EXIT-CRITERIA.md` makes the
|
|
7597
|
+
remaining normative, external-corpus, and unexplained-deviation exit conditions
|
|
7598
|
+
explicit. `test/conformance/WG17-SYNTAX-STATUS.md` separately traces the vendored active
|
|
7596
7599
|
upstream syntax cases. Reviewed cases can pin exact strict-reader outcomes, while
|
|
7597
7600
|
newly upgraded cases execute directly against the upstream Codex expectation.
|
|
7598
7601
|
|
|
7602
|
+
The syntax audit also cross-checks extension safety: each vendored WG17 case
|
|
7603
|
+
accepted by the strict Part 1 reader is executed through the normal profile and
|
|
7604
|
+
must preserve the same observable outcome. Additional normal-mode syntax may
|
|
7605
|
+
accept texts outside the strict grammar, but it may not reinterpret an accepted
|
|
7606
|
+
standard case.
|
|
7607
|
+
|
|
7599
7608
|
The complete suite must pass before release. The file-based conformance corpus
|
|
7600
7609
|
contains 802 cases, including 386 focused ISO
|
|
7601
7610
|
cases derived from the success, failure, mode, and error behavior in
|
|
@@ -7663,9 +7672,16 @@ strict boundary. The continuing issue #65 audit also enforces Part 1
|
|
|
7663
7672
|
preparation constraints for `dynamic/1`, `multifile/1`, and `discontiguous/1`,
|
|
7664
7673
|
keeps initialization tied to preparation of a program, tightens stream
|
|
7665
7674
|
creation/position/EOF behavior and text-vs-binary permission errors, corrects
|
|
7666
|
-
Corrigendum 2 `keysort/2` error cases,
|
|
7667
|
-
|
|
7668
|
-
|
|
7675
|
+
Corrigendum 2 `keysort/2` error cases, closes the 5.5.6 Prolog-visible
|
|
7676
|
+
side-effect boundary by excluding statistics/cleanup extensions from strict
|
|
7677
|
+
mode, closes 5.5.10 by keeping the non-standard evaluable atom `e` outside
|
|
7678
|
+
strict mode, closes the row-level 7.1-7.3 term-semantics and 7.9/Clause 9
|
|
7679
|
+
arithmetic audits, and pins the permitted arithmetic variation points for
|
|
7680
|
+
mixed-type Corrigendum 2 `max/2`/`min/2` plus signed Clause 9.4 bitwise and
|
|
7681
|
+
negative-shift behavior. The Clause 9 audit also corrected float-only
|
|
7682
|
+
`float_integer_part/1` and `float_fractional_part/1` so integer operands are
|
|
7683
|
+
rejected by type before a potentially overflowing integer-to-float conversion.
|
|
7684
|
+
These are conformance improvements, while the remaining qualifications are:
|
|
7669
7685
|
|
|
7670
7686
|
- zero-arity compound syntax such as `ready()` is represented by the atom
|
|
7671
7687
|
`ready`;
|
|
@@ -7685,9 +7701,9 @@ Write terms explicitly, keep variables uppercase or underscore-prefixed, and
|
|
|
7685
7701
|
quote atom names that are neither lowercase plain names nor graphic tokens.
|
|
7686
7702
|
These boundaries distinguish implemented ISO functionality from certification.
|
|
7687
7703
|
The EyeProlog corpus verifies this documented profile and strict-core boundary.
|
|
7688
|
-
A public full-conformance claim is deferred until the
|
|
7689
|
-
|
|
7690
|
-
deviations.
|
|
7704
|
+
A public full-conformance claim is deferred until the explicit
|
|
7705
|
+
`test/conformance/ISO-EXIT-CRITERIA.md` checklist has no unresolved normative
|
|
7706
|
+
audits or unexplained external-corpus deviations.
|
|
7691
7707
|
|
|
7692
7708
|
### Security and resource use
|
|
7693
7709
|
|
package/why-eyeprolog.md
CHANGED
|
@@ -28,9 +28,11 @@ collating-sequence integers in both normal and strict profiles. Strict mode
|
|
|
28
28
|
therefore rejects implementation-specific language extensions without changing
|
|
29
29
|
that processor choice. Its executable conformance matrix and tests
|
|
30
30
|
document the supported behavior, including an executable trace of the vendored
|
|
31
|
-
active WG17 syntax cases.
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
active WG17 syntax cases, cross-profile preservation of all strict-success WG17 syntax outcomes, closed strict side-effect and evaluable-functor extension boundaries, the completed row-level 7.1-7.3 term-semantics and 7.9/Clause 9 arithmetic audits, and explicit choices at standardized variation points such as mixed-type
|
|
32
|
+
`max/2`/`min/2` and signed bitwise/shift operations. The remaining exit criteria
|
|
33
|
+
are recorded explicitly rather than inferred from aggregate test counts. This is
|
|
34
|
+
extensive implementation evidence, not a claim that every Part 1, Part 2, or
|
|
35
|
+
Part 3 normative requirement has already been certified or closed.
|
|
34
36
|
|
|
35
37
|
## Why a small implementation?
|
|
36
38
|
|