eyeprolog 1.3.56 → 1.3.57
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/package.json +1 -1
- package/src/iso.js +48 -40
- package/src/program.js +9 -1
- package/test/conformance/ISO-BUILTIN-MODE-ERROR-MATRIX.md +190 -17
- package/test/conformance/ISO-COMPLIANCE.md +40 -13
- package/test/conformance/ISO-MATRIX.md +3 -3
- package/test/conformance/ISO-PROCESSOR-REQUIREMENTS.md +3 -3
- package/test/conformance/README.md +4 -4
- package/test/run-iso-strict.mjs +306 -9
package/package.json
CHANGED
package/src/iso.js
CHANGED
|
@@ -393,9 +393,9 @@ function* functorBuiltin({ goal, env }) {
|
|
|
393
393
|
|
|
394
394
|
const name = deref(goal.args[1], env);
|
|
395
395
|
const arityTerm = deref(goal.args[2], env);
|
|
396
|
-
//
|
|
397
|
-
//
|
|
398
|
-
//
|
|
396
|
+
// Keep EyeProlog's deterministic construction-mode diagnostics aligned with
|
|
397
|
+
// the individual 8.5.1.3 conditions. Under 7.12, a call satisfying several
|
|
398
|
+
// error conditions at once does not acquire a globally mandated table order.
|
|
399
399
|
if (name.type === VAR) throw new PrologError('instantiation_error');
|
|
400
400
|
if (arityTerm.type === VAR) throw new PrologError('instantiation_error');
|
|
401
401
|
if (name.type === COMPOUND) throw new PrologError('type_error(atomic)', name);
|
|
@@ -562,7 +562,9 @@ function* clauseBuiltin({ solver, goal, env }) {
|
|
|
562
562
|
if (head.type !== ATOM && head.type !== COMPOUND) throw new PrologError('type_error(callable)', head);
|
|
563
563
|
const indicator = compound('/', [atom(head.name), numberTerm(head.arity)]);
|
|
564
564
|
const group = solver.program.findGroup(head.name, head.arity, head.module ?? goal.module ?? 'user');
|
|
565
|
-
//
|
|
565
|
+
// EyeProlog selects private-procedure access before Body callability when both
|
|
566
|
+
// conditions hold. ISO 7.12 permits an implementation-dependent choice when
|
|
567
|
+
// more than one error condition is simultaneously satisfied.
|
|
566
568
|
if (isProcessorStaticProcedure(solver, head) ||
|
|
567
569
|
(solver.isoStrict && group && !group.dynamic)) {
|
|
568
570
|
throw new PrologError('permission_error(access, private_procedure)', indicator);
|
|
@@ -590,7 +592,7 @@ function requireClauseHead(head) {
|
|
|
590
592
|
if (head.type !== ATOM && head.type !== COMPOUND) throw new PrologError('type_error(callable)', head);
|
|
591
593
|
}
|
|
592
594
|
|
|
593
|
-
function
|
|
595
|
+
export function convertClauseBodyTerm(term, culprit = term) {
|
|
594
596
|
if (term.type === VAR) return compound('call', [term]);
|
|
595
597
|
// ISO 7.6.2 converts each argument of conjunction, disjunction, and if-then
|
|
596
598
|
// recursively when a term is converted to a clause body. This matters for
|
|
@@ -599,8 +601,8 @@ function convertAssertedBody(term, culprit = term) {
|
|
|
599
601
|
// being stored and failing only if that branch is later executed.
|
|
600
602
|
if (term.type === COMPOUND && [',', ';', '->'].includes(term.name) && term.arity === 2) {
|
|
601
603
|
return compound(term.name, [
|
|
602
|
-
|
|
603
|
-
|
|
604
|
+
convertClauseBodyTerm(term.args[0], culprit),
|
|
605
|
+
convertClauseBodyTerm(term.args[1], culprit),
|
|
604
606
|
]);
|
|
605
607
|
}
|
|
606
608
|
if (term.type !== ATOM && term.type !== COMPOUND) {
|
|
@@ -643,7 +645,7 @@ function assertBuiltin(atStart) {
|
|
|
643
645
|
return function* ({ solver, goal, env }) {
|
|
644
646
|
const parts = clauseParts(goal.args[0], env);
|
|
645
647
|
requireClauseHead(parts.head);
|
|
646
|
-
const body =
|
|
648
|
+
const body = convertClauseBodyTerm(parts.body);
|
|
647
649
|
assertModifiable(solver, parts.head, goal.module ?? 'user');
|
|
648
650
|
const copied = freshCopy(compound('$clause', [parts.head, body]), env);
|
|
649
651
|
solver.program.insertDynamicClause({
|
|
@@ -782,9 +784,9 @@ function* opBuiltin({ solver, goal, env }) {
|
|
|
782
784
|
const priorityTerm = deref(goal.args[0], env);
|
|
783
785
|
const specifierTerm = deref(goal.args[1], env);
|
|
784
786
|
|
|
785
|
-
//
|
|
786
|
-
//
|
|
787
|
-
//
|
|
787
|
+
// Keep EyeProlog's selected 8.14.3.3 overlap order deterministic. Each
|
|
788
|
+
// individual condition remains observable; ISO 7.12 leaves the choice
|
|
789
|
+
// implementation dependent when several error conditions hold at once.
|
|
788
790
|
if (priorityTerm.type === VAR) throw new PrologError('instantiation_error');
|
|
789
791
|
if (specifierTerm.type === VAR) throw new PrologError('instantiation_error');
|
|
790
792
|
const operator = opListPreflight(goal.args[2], env);
|
|
@@ -943,12 +945,11 @@ function optionList(term, env) {
|
|
|
943
945
|
return items.map((item) => deref(item, env));
|
|
944
946
|
}
|
|
945
947
|
|
|
946
|
-
// read_term/3 and write_term/3
|
|
947
|
-
//
|
|
948
|
-
//
|
|
949
|
-
//
|
|
950
|
-
//
|
|
951
|
-
// validation so those predicates can follow the standard order exactly.
|
|
948
|
+
// Keep read_term/3 and write_term/3 diagnostics deterministic and make every
|
|
949
|
+
// 8.14 error condition independently testable. ISO 7.12 leaves the choice
|
|
950
|
+
// implementation dependent when several error conditions hold simultaneously,
|
|
951
|
+
// so this preflight order is an EyeProlog processor choice rather than a claim
|
|
952
|
+
// that the textual order of an error table is globally mandatory.
|
|
952
953
|
function preflightOptionList(term, env) {
|
|
953
954
|
const value = deref(term, env);
|
|
954
955
|
if (value.type === VAR) throw new PrologError('instantiation_error');
|
|
@@ -1017,9 +1018,9 @@ function* openBuiltin({ solver, goal, env }) {
|
|
|
1017
1018
|
const streamTarget = deref(goal.args[2], env);
|
|
1018
1019
|
const optionTerm = goal.arity === 3 ? emptyList() : goal.args[3];
|
|
1019
1020
|
|
|
1020
|
-
// ISO 8.11.5.3 + Corrigenda 2/3.
|
|
1021
|
-
//
|
|
1022
|
-
//
|
|
1021
|
+
// ISO 8.11.5.3 + Corrigenda 2/3. Keep each required condition observable
|
|
1022
|
+
// on its own. When several conditions hold, the order below is EyeProlog's
|
|
1023
|
+
// deterministic 7.12 processor choice unless a procedural rule constrains it.
|
|
1023
1024
|
if (source.type === VAR) throw new PrologError('instantiation_error');
|
|
1024
1025
|
if (mode.type === VAR) throw new PrologError('instantiation_error');
|
|
1025
1026
|
const preflight = preflightOptionList(optionTerm, env);
|
|
@@ -1183,16 +1184,21 @@ function isStreamPropertyPattern(value) {
|
|
|
1183
1184
|
function* streamPropertyBuiltin({ solver, goal, env }) {
|
|
1184
1185
|
const reference = deref(goal.args[0], env);
|
|
1185
1186
|
const propertyPattern = deref(goal.args[1], env);
|
|
1187
|
+
let fixedStreamId = null;
|
|
1186
1188
|
if (reference.type !== VAR) {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
+
// 8.11.8.1 enumerates (Stream, Property) pairs for currently open
|
|
1190
|
+
// streams. A ground term with the implementation's stream-term shape is
|
|
1191
|
+
// still a stream-term even when its stream is no longer open; in that
|
|
1192
|
+
// case the enumeration simply has no matching pair. domain_error(stream)
|
|
1193
|
+
// is reserved for a term which is not a stream-term at all.
|
|
1194
|
+
fixedStreamId = streamTermReference(goal.args[0], env);
|
|
1189
1195
|
}
|
|
1190
1196
|
if (!isStreamPropertyPattern(propertyPattern)) {
|
|
1191
1197
|
throw new PrologError('domain_error(stream_property)', propertyPattern);
|
|
1192
1198
|
}
|
|
1193
1199
|
const streams = reference.type === VAR
|
|
1194
1200
|
? [...solver.io.streams.values()]
|
|
1195
|
-
: [solver.io.resolve(
|
|
1201
|
+
: [solver.io.resolve(fixedStreamId)].filter(Boolean);
|
|
1196
1202
|
for (const stream of streams) {
|
|
1197
1203
|
for (const property of streamProperties(stream)) {
|
|
1198
1204
|
const next = env.clone();
|
|
@@ -1232,11 +1238,10 @@ function preflightInputUnitTarget(name, target, env, solver) {
|
|
|
1232
1238
|
throw new PrologError('type_error(in_character)', value);
|
|
1233
1239
|
}
|
|
1234
1240
|
} else if (name.endsWith('code')) {
|
|
1235
|
-
//
|
|
1236
|
-
//
|
|
1237
|
-
//
|
|
1238
|
-
//
|
|
1239
|
-
// itself has been inspected below.
|
|
1241
|
+
// Keep the selected 8.12 overlap behavior stable: integer type validation
|
|
1242
|
+
// is done here, while the in-character-code repertoire check is deferred
|
|
1243
|
+
// until after stream/entity diagnostics. ISO 7.12 permits this processor
|
|
1244
|
+
// choice when those error conditions overlap.
|
|
1240
1245
|
if (value.type !== VAR && (value.type !== NUMBER || !isDecimalInteger(value.name))) {
|
|
1241
1246
|
throw new PrologError('type_error(integer)', value);
|
|
1242
1247
|
}
|
|
@@ -1290,10 +1295,9 @@ function inputUnitBuiltin(name) {
|
|
|
1290
1295
|
if (!binary && unit != null && solver.isoStrict && !isStrictIsoPcsCharacter(unit)) {
|
|
1291
1296
|
throw new PrologError('representation_error(character)');
|
|
1292
1297
|
}
|
|
1293
|
-
//
|
|
1294
|
-
//
|
|
1295
|
-
//
|
|
1296
|
-
// output-stream, binary-stream, past-EOF, or invalid-character error.
|
|
1298
|
+
// EyeProlog deliberately defers this representation check until after
|
|
1299
|
+
// stream and input-entity diagnostics. ISO 7.12 permits that deterministic
|
|
1300
|
+
// choice when several 8.12 error conditions hold simultaneously.
|
|
1297
1301
|
const targetValue = deref(target, env);
|
|
1298
1302
|
if (name.endsWith('code') && targetValue.type !== VAR &&
|
|
1299
1303
|
!validStrictInputCharacterCode(targetValue, solver)) {
|
|
@@ -1596,9 +1600,9 @@ function* readTermBuiltin({ solver, goal, env }) {
|
|
|
1596
1600
|
const optionTerm = goal.args[goal.arity - 1];
|
|
1597
1601
|
const streamTerm = goal.arity === 3 ? deref(goal.args[0], env) : null;
|
|
1598
1602
|
|
|
1599
|
-
//
|
|
1600
|
-
//
|
|
1601
|
-
//
|
|
1603
|
+
// EyeProlog's selected 8.14.1.3 overlap order. Each listed error condition
|
|
1604
|
+
// is covered independently; 7.12 makes simultaneous-error selection
|
|
1605
|
+
// implementation dependent unless another procedural requirement constrains it.
|
|
1602
1606
|
if (streamTerm?.type === VAR) throw new PrologError('instantiation_error');
|
|
1603
1607
|
const preflight = preflightOptionList(optionTerm, env);
|
|
1604
1608
|
if (goal.arity === 3) streamReference(goal.args[0], env);
|
|
@@ -1712,9 +1716,9 @@ function* writeTermBuiltin({ solver, goal, env }) {
|
|
|
1712
1716
|
const optionTerm = goal.args[goal.arity - 1];
|
|
1713
1717
|
const streamTerm = goal.arity === 3 ? deref(goal.args[0], env) : null;
|
|
1714
1718
|
|
|
1715
|
-
//
|
|
1716
|
-
//
|
|
1717
|
-
//
|
|
1719
|
+
// EyeProlog's selected 8.14.2.3 overlap order. Each listed error condition
|
|
1720
|
+
// is covered independently; 7.12 makes simultaneous-error selection
|
|
1721
|
+
// implementation dependent unless another procedural requirement constrains it.
|
|
1718
1722
|
if (streamTerm?.type === VAR) throw new PrologError('instantiation_error');
|
|
1719
1723
|
const preflight = preflightOptionList(optionTerm, env);
|
|
1720
1724
|
const optionItems = requireProperOptionList(preflight);
|
|
@@ -2187,7 +2191,9 @@ function flatFindallTemplate(template) {
|
|
|
2187
2191
|
|
|
2188
2192
|
function* findallBuiltin({ solver, goal, env }) {
|
|
2189
2193
|
const [template, innerGoal, bag] = goal.args;
|
|
2190
|
-
//
|
|
2194
|
+
// EyeProlog validates Goal before Instances when both are erroneous. ISO 7.12
|
|
2195
|
+
// makes simultaneous-error selection implementation dependent; this order is
|
|
2196
|
+
// a documented/tested processor choice, not a blanket table-order rule.
|
|
2191
2197
|
const invoked = callable(innerGoal, env);
|
|
2192
2198
|
assertListOrPartial(bag, env);
|
|
2193
2199
|
const collector = solver.cloneForInnerGoal(10000000);
|
|
@@ -2252,7 +2258,9 @@ function sortedUnique(items) {
|
|
|
2252
2258
|
|
|
2253
2259
|
function allSolutionsBuiltin(asSet) {
|
|
2254
2260
|
return function* ({ solver, goal, env }) {
|
|
2255
|
-
//
|
|
2261
|
+
// EyeProlog validates the iterated goal before Instances. ISO 7.12 makes
|
|
2262
|
+
// simultaneous-error selection implementation dependent; keep this stable as
|
|
2263
|
+
// a processor choice rather than describing it as mandatory table ordering.
|
|
2256
2264
|
const { iterated, quantified } = bagGoalParts(goal.args[1], env);
|
|
2257
2265
|
assertListOrPartial(goal.args[2], env);
|
|
2258
2266
|
const free = freeVariables(iterated, goal.args[0], quantified, env);
|
package/src/program.js
CHANGED
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
parseGoalText,
|
|
13
13
|
tryParseClausesFastInto,
|
|
14
14
|
} from './parser.js';
|
|
15
|
-
import { PrologError, getStrictIsoRegistry } from './iso.js';
|
|
15
|
+
import { PrologError, convertClauseBodyTerm, getStrictIsoRegistry } from './iso.js';
|
|
16
16
|
import { currentWorkingDirectory, fs, path } from './platform.js';
|
|
17
17
|
import {
|
|
18
18
|
standardLibrarySources,
|
|
@@ -627,6 +627,14 @@ class ProgramBuilder {
|
|
|
627
627
|
}
|
|
628
628
|
|
|
629
629
|
if (!isDirectiveClause(clause)) {
|
|
630
|
+
if (program.strictIso && Array.isArray(clause.body) && clause.body.length > 0) {
|
|
631
|
+
// ISO 7.6.2 applies when source text is prepared as well as when a
|
|
632
|
+
// clause term is asserted dynamically. Keep the original variable
|
|
633
|
+
// objects while wrapping variable goals in call/1 so sharing with
|
|
634
|
+
// the head (and recursively through ;/2 and ->/2) is preserved for
|
|
635
|
+
// later clause/2 and retract/1 conversion back to terms.
|
|
636
|
+
clause.body = clause.body.map((goal) => convertClauseBodyTerm(goal));
|
|
637
|
+
}
|
|
630
638
|
assertHeadIsDefinable(clause.head, program.strictIso);
|
|
631
639
|
const head = clause.head;
|
|
632
640
|
if (head.type !== ATOM && head.type !== COMPOUND) continue;
|
|
@@ -4,12 +4,21 @@ This matrix turns the broad built-in audit in `ISO-COMPLIANCE.md` into smaller,
|
|
|
4
4
|
release-gated units. The normative baseline is ISO/IEC 13211-1:1995 plus
|
|
5
5
|
Technical Corrigenda 1:2007, 2:2012, and 3:2017.
|
|
6
6
|
|
|
7
|
-
A `covered` row has
|
|
8
|
-
failure behavior, or error condition. `not applicable` records a
|
|
9
|
-
standard branch that cannot occur under EyeProlog's documented
|
|
10
|
-
choices.
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
A `covered` row has executable evidence for the required successful mode,
|
|
8
|
+
failure behavior, or individual error condition. `not applicable` records a
|
|
9
|
+
conditional standard branch that cannot occur under EyeProlog's documented
|
|
10
|
+
processor choices. ISO 7.12 makes the reported error implementation dependent
|
|
11
|
+
when more than one error condition is simultaneously satisfied. Accordingly,
|
|
12
|
+
this matrix treats overlap tests as stable EyeProlog processor choices unless a
|
|
13
|
+
more specific procedural requirement or Corrigendum constrains the result; it
|
|
14
|
+
does not infer a universal priority merely from the textual order of an error
|
|
15
|
+
table.
|
|
16
|
+
|
|
17
|
+
The table is intentionally explicit about what has and has not been closed.
|
|
18
|
+
The current audit now covers the complete 8.2-8.17 built-in family at the
|
|
19
|
+
level of prescribed modes, success/failure behavior, individual error
|
|
20
|
+
conditions, and explicit not-applicable processor branches. Higher-level
|
|
21
|
+
Clause 7 and Clause 9 semantics remain tracked separately.
|
|
13
22
|
|
|
14
23
|
The focused assertions added for this matrix live in `test/run-iso-strict.mjs`;
|
|
15
24
|
existing file-based cases remain additional independent evidence.
|
|
@@ -102,6 +111,171 @@ The Corrigendum 2 additions have the same shape.
|
|
|
102
111
|
| Cor.2 8.5.5 `term_variables/2` | supplied partial/list result | covered | Corrigendum cases |
|
|
103
112
|
| Cor.2 8.5.5 error (a) | second argument neither partial list nor list -> list type error | covered | strict `term_variables(t,[X|foo])` |
|
|
104
113
|
|
|
114
|
+
## 8.6 — arithmetic evaluation
|
|
115
|
+
|
|
116
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
117
|
+
| --- | --- | --- | --- |
|
|
118
|
+
| 8.6.1 `is/2` | evaluate the second argument and unify/check the result | covered | strict `X is 1+2, X=3`, arithmetic corpus |
|
|
119
|
+
| 8.6.1 failed result unification | a successfully evaluated value need not unify with the first argument | covered | strict `4 is 1+2` fails |
|
|
120
|
+
| 8.6.1 error (a) | variable expression -> instantiation error | covered | strict `X is Y` |
|
|
121
|
+
| 8.6.1 delegated expression errors | evaluation may report any applicable 7.9.2 error | covered | strict `X is foo` plus Clause 9 arithmetic/error suites |
|
|
122
|
+
|
|
123
|
+
## 8.7 — arithmetic comparison
|
|
124
|
+
|
|
125
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
126
|
+
| --- | --- | --- | --- |
|
|
127
|
+
| 8.7.1 `(=:=)/2` | evaluate two expressions and test arithmetic equality | covered | strict `1 =:= 1`, arithmetic comparison corpus |
|
|
128
|
+
| 8.7.1 `(=\=)/2` | evaluate two expressions and test arithmetic inequality | covered | strict `1 =\= 2` |
|
|
129
|
+
| 8.7.1 `(<)/2` | arithmetic less-than | covered | strict `1 < 2` |
|
|
130
|
+
| 8.7.1 `(=<)/2` | arithmetic less-than-or-equal | covered | strict `1 =< 1` |
|
|
131
|
+
| 8.7.1 `(>)/2` | arithmetic greater-than | covered | strict `2 > 1` |
|
|
132
|
+
| 8.7.1 `(>=)/2` | arithmetic greater-than-or-equal | covered | strict `2 >= 2` |
|
|
133
|
+
| 8.7.1 error (a) | first expression variable -> instantiation error | covered | strict variable-first assertions across the comparison family |
|
|
134
|
+
| 8.7.1 error (b) | second expression variable -> instantiation error | covered | strict variable-second assertions across the comparison family |
|
|
135
|
+
| 8.7.1 delegated expression errors | either expression may report an applicable 7.9.2 error | covered | strict `foo =:= 1` plus Clause 9 error suites |
|
|
136
|
+
| 8.7 mixed integer/float operation | selected Part 1 I-to-F comparison operations, including conversion overflow | covered | dedicated strict mixed-comparison tests |
|
|
137
|
+
|
|
138
|
+
## 8.8 — clause inspection
|
|
139
|
+
|
|
140
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
141
|
+
| --- | --- | --- | --- |
|
|
142
|
+
| 8.8.1 `clause/2` | enumerate clauses of a public user-defined procedure | covered | dynamic-clause tests and grouped-solutions/clause corpus |
|
|
143
|
+
| 8.8.1 error (a) | variable head -> instantiation error | covered | strict `clause(X,_)` |
|
|
144
|
+
| 8.8.1 error (b) | non-callable head -> callable type error | covered | strict `clause(4,_)` |
|
|
145
|
+
| 8.8.1 error (c) | private procedure -> access/private-procedure permission error | covered | strict static/private tests |
|
|
146
|
+
| 8.8.1 error (d) | fixed non-callable Body -> callable type error | covered | strict dynamic `clause(p(_),4)` coverage |
|
|
147
|
+
| 8.8.1 clause-to-term conversion | source variable goals become `call/1` while preserving sharing with the head | covered | strict `foo(X):-X` -> `clause(foo(C),call(C))`; nested `;/2` and `->/2` regressions |
|
|
148
|
+
| 8.8.2 `current_predicate/1` | enumerate/query user-defined predicate indicators, including empty declared procedures | covered | strict row audit and empty-procedure lifetime tests |
|
|
149
|
+
| 8.8.2 error (a) | fixed non-predicate-indicator -> predicate-indicator type error | covered | strict `current_predicate(4)` |
|
|
150
|
+
|
|
151
|
+
## 8.9 — database modification
|
|
152
|
+
|
|
153
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
154
|
+
| --- | --- | --- | --- |
|
|
155
|
+
| 8.9.1 `asserta/1` | convert term to clause and insert before existing clauses | covered | dynamic-database corpus and strict body-conversion tests |
|
|
156
|
+
| 8.9.1 errors (a-b) | variable/non-callable Head -> instantiation/callable type error | covered | strict `asserta(_)`, `asserta(4)` |
|
|
157
|
+
| 8.9.1 error (c) | Body cannot be converted to a goal -> callable type error | covered | strict `asserta((p:-4))` and nested-control conversion tests |
|
|
158
|
+
| 8.9.1 error (d) | static procedure -> modify/static-procedure permission error | covered | strict static-procedure tests |
|
|
159
|
+
| 8.9.2 `assertz/1` | convert term to clause and insert after existing clauses | covered | dynamic-database corpus and strict body-conversion tests |
|
|
160
|
+
| 8.9.2 errors (a-d) | same Head/Body/static families as `asserta/1` | covered | strict `assertz(_)`, `assertz(4)`, `assertz((p:-4))`, static-procedure tests |
|
|
161
|
+
| 8.9.3 `retract/1` | retract matching dynamic clauses re-executably using the logical update view | covered | dynamic-database and logical-update-view suites |
|
|
162
|
+
| 8.9.3 errors (a-b) | variable/non-callable Head -> instantiation/callable type error | covered | strict `retract(_)`, `retract(4)` |
|
|
163
|
+
| Cor.2 8.9.3 error (c) | static procedure -> **modify**/static-procedure permission error | covered | strict `retract(atom(_))` and Corrigendum coverage |
|
|
164
|
+
| 8.9.3 clause-term matching | converted source body retains head/body variable identity when matched by `retract/1` | covered | strict `retract((foo(C):-call(C)))` regression |
|
|
165
|
+
| 8.9.4 `abolish/1` | remove a dynamic procedure | covered | strict lifetime tests |
|
|
166
|
+
| 8.9.4 errors (a-b) | variable indicator or variable Name/Arity component -> instantiation error | covered | strict `abolish(X)`, `abolish(foo/X)` |
|
|
167
|
+
| 8.9.4 error (c) | non-predicate-indicator -> predicate-indicator type error | covered | strict `abolish(foo)` |
|
|
168
|
+
| 8.9.4 error (d) | non-integer Arity -> integer type error | covered | strict `abolish(foo/a)` |
|
|
169
|
+
| 8.9.4 error (e) | non-atom Name -> atom type error | covered | strict `abolish(4/1)` |
|
|
170
|
+
| 8.9.4 error (f) | negative Arity -> non-negative domain error | covered | strict `abolish(foo/(-1))` |
|
|
171
|
+
| 8.9.4 finite-`max_arity` error (g) | Arity exceeds finite `max_arity` | not applicable | selected `max_arity=unbounded` |
|
|
172
|
+
| 8.9.4 error (h) | static procedure -> modify/static-procedure permission error | covered | strict `abolish(atom/1)` |
|
|
173
|
+
| Cor.2 8.9.5 `retractall/1` | remove all matching dynamic heads while retaining the procedure | covered | strict empty-procedure lifetime test and Corrigendum cases |
|
|
174
|
+
| Cor.2 8.9.5 errors (a-c) | variable/non-callable Head or static procedure | covered | strict `retractall(_)`, `retractall(4)`, static-procedure test |
|
|
175
|
+
|
|
176
|
+
## 8.10 — all solutions
|
|
177
|
+
|
|
178
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
179
|
+
| --- | --- | --- | --- |
|
|
180
|
+
| 8.10.1 `findall/3` | collect renamed template instances in solution order; empty result succeeds with `[]` | covered | strict `[1,2]` assertion plus all-solutions corpus |
|
|
181
|
+
| 8.10.1 error (a) | variable Goal -> instantiation error | covered | strict `findall(X,Y,L)` |
|
|
182
|
+
| 8.10.1 error (b) | non-callable Goal -> callable type error | covered | strict `findall(X,4,L)` |
|
|
183
|
+
| 8.10.1 error (c) | Instances neither partial list nor list -> list type error | covered | strict `findall(X,true,foo)` |
|
|
184
|
+
| 8.10.2 `bagof/3` | non-empty grouped solution lists, re-executable over free-variable witnesses | covered | grouped-solutions corpus and strict `[1,2]` assertion |
|
|
185
|
+
| 8.10.2 empty solution set | goal fails rather than returning `[]` | covered | strict `bagof(X,fail,L)` |
|
|
186
|
+
| 8.10.2 errors (a-b) | variable/non-callable iterated-goal term -> instantiation/callable type error | covered | strict `bagof(X,Y,L)`, `bagof(X,4,L)` |
|
|
187
|
+
| 8.10.2 error (c) | Instances neither partial list nor list -> list type error | covered | strict `bagof(X,true,foo)` |
|
|
188
|
+
| 8.10.3 `setof/3` | grouped solutions sorted with duplicates removed | covered | strict duplicate/sort assertion plus grouped-solutions corpus |
|
|
189
|
+
| 8.10.3 empty solution set | goal fails rather than returning `[]` | covered | strict `setof(X,fail,L)` |
|
|
190
|
+
| 8.10.3 errors (a-b) | variable/non-callable iterated-goal term -> instantiation/callable type error | covered | strict `setof(X,Y,L)`, `setof(X,4,L)` |
|
|
191
|
+
| 8.10.3 error (c) | Instances neither partial list nor list -> list type error | covered | strict `setof(X,true,foo)` |
|
|
192
|
+
| 8.10.2-3 witness-group order where the standard leaves a choice | implementation dependent | covered | existing grouping tests document EyeProlog's stable selection without turning it into a cross-processor requirement |
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
## 8.11 — stream selection and control
|
|
196
|
+
|
|
197
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
198
|
+
| --- | --- | --- | --- |
|
|
199
|
+
| 8.11.1 `current_input/1` | unify/query the current input stream-term | covered | strict current-input success assertion |
|
|
200
|
+
| 8.11.1 error | fixed argument is neither variable nor stream-term -> stream domain error | covered | strict `current_input(foo)` |
|
|
201
|
+
| 8.11.2 `current_output/1` | unify/query the current output stream-term | covered | strict current-output success assertion |
|
|
202
|
+
| 8.11.2 error | fixed argument is neither variable nor stream-term -> stream domain error | covered | strict `current_output(foo)` |
|
|
203
|
+
| 8.11.3 `set_input/1` | select an open input stream by stream-term or alias | covered | stream-selection corpus |
|
|
204
|
+
| 8.11.3 errors | variable; invalid stream-or-alias; missing stream; output stream | covered | dedicated strict assertions for all four conditions |
|
|
205
|
+
| 8.11.4 `set_output/1` | select an open output stream by stream-term or alias | covered | stream-selection corpus |
|
|
206
|
+
| 8.11.4 errors | variable; invalid stream-or-alias; missing stream; input stream | covered | dedicated strict assertions for all four conditions |
|
|
207
|
+
| 8.11.5 `open/4`, `open/3` | open a source/sink with standardized mode/options and return a fresh stream | covered | stream corpus plus strict successful/error probes |
|
|
208
|
+
| 8.11.5 errors: instantiation | variable source/mode or variable option element | covered | strict `open/4` assertions |
|
|
209
|
+
| 8.11.5 errors: argument shapes | non-atom mode; non-list options; non-variable stream output (Cor.2 uninstantiation) | covered | strict `open/4` assertions |
|
|
210
|
+
| 8.11.5 errors: domains | invalid source/sink, I/O mode, or stream option | covered | strict `open/4` assertions |
|
|
211
|
+
| 8.11.5 source/sink errors | missing read source or source/sink that cannot be opened | covered | strict host-I/O probes for existence/permission conditions |
|
|
212
|
+
| 8.11.5 alias collision | `alias(A)` already names an open stream -> open permission error with complete `alias(A)` culprit | covered | focused issue #65 alias-collision regression |
|
|
213
|
+
| 8.11.5 `reposition(true)` impossible | permission error when the requested stream cannot be repositioned | covered | stream option corpus and implementation-defined stream capability checks |
|
|
214
|
+
| 8.11.6 `close/2`, `close/1` | close an open non-standard stream and maintain current-stream fallbacks | covered | stream lifecycle corpus |
|
|
215
|
+
| 8.11.6 errors | variable stream/option element; non-list options; invalid stream-or-alias; invalid close option; missing stream | covered | strict close assertions |
|
|
216
|
+
| 8.11.6 `force(true)` | presence of `force(true)` suppresses resource/system close failure regardless of contradictory later `force(false)` | covered | dedicated two-order strict regression |
|
|
217
|
+
| 8.11.7 `flush_output/1`, `flush_output/0` | flush an output stream/current output | covered | strict success assertion and stream corpus |
|
|
218
|
+
| 8.11.7 errors | variable; invalid stream-or-alias; missing stream; input stream | covered | dedicated strict assertions |
|
|
219
|
+
| 8.11.8 `stream_property/2` | enumerate properties of currently open streams; order is implementation dependent | covered | stream-property corpus and strict checks |
|
|
220
|
+
| 8.11.8 stream-term error | fixed non-stream-term -> stream domain error | covered | strict `stream_property(foo,_)` |
|
|
221
|
+
| 8.11.8 property error | fixed non-stream-property -> stream-property domain error | covered | strict invalid-property assertion |
|
|
222
|
+
| 8.11.8 closed valid stream-term | no pair exists for a stream that is no longer open -> fail | covered | dedicated closed-stream regression |
|
|
223
|
+
| 8.11.8 `at_end_of_stream/0-1` | test current/named stream end or past-end state | covered | strict success and EOF corpus |
|
|
224
|
+
| 8.11.8 `at_end_of_stream/1` errors | variable; invalid stream-or-alias; missing stream | covered | dedicated strict assertions |
|
|
225
|
+
| 8.11.9 `set_stream_position/2` | set a repositionable open stream to a valid stream position | covered | dedicated positioned-stream success assertion |
|
|
226
|
+
| 8.11.9 errors | variable stream/position; invalid stream-or-alias/position; missing stream; non-repositionable stream | covered | dedicated strict assertions |
|
|
227
|
+
|
|
228
|
+
## 8.12 — character input/output
|
|
229
|
+
|
|
230
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
231
|
+
| --- | --- | --- | --- |
|
|
232
|
+
| 8.12.1 `get_char/1-2` | input next text character or EOF indicator | covered | stream/character corpus and strict probes |
|
|
233
|
+
| 8.12.1 `get_code/1-2` | input next text character code or `-1` at EOF | covered | stream/code corpus and strict probes |
|
|
234
|
+
| 8.12.1 argument errors | variable stream; invalid fixed in-character; non-integer fixed code | covered | dedicated strict assertions |
|
|
235
|
+
| 8.12.1 stream errors | invalid stream-or-alias; missing stream; output stream; binary stream; past-end with `eof_action(error)` | covered | dedicated strict and constructed-stream assertions |
|
|
236
|
+
| 8.12.1 input entity/code representation | non-character input entity or fixed integer not an in-character code | covered | strict entity/code representation regressions; bad-code check is deferred until earlier stream/entity conditions are resolved |
|
|
237
|
+
| 8.12.2 `peek_char/1-2`, `peek_code/1-2` | inspect next character/code without changing stream position | covered | strict probes and stream corpus |
|
|
238
|
+
| 8.12.2 errors | corresponding 8.12.1 argument, stream, EOF, entity and code-representation conditions | covered | dedicated strict assertions including overlap regression |
|
|
239
|
+
| 8.12.3 `put_char/1-2` | output one text character | covered | output corpus |
|
|
240
|
+
| 8.12.3 `put_code/1-2` | output character selected by character code | covered | output corpus |
|
|
241
|
+
| 8.12.3 `nl/0-1` | output implementation-defined new-line character | covered | output corpus |
|
|
242
|
+
| 8.12.3 argument errors | variable character/code or wrong character/integer type | covered | dedicated strict assertions |
|
|
243
|
+
| 8.12.3 stream errors | variable/invalid/missing stream; input stream; binary stream | covered | dedicated strict and constructed-stream assertions |
|
|
244
|
+
| 8.12.3 character-code representation | integer outside processor character-code set | covered | strict `put_code/1` boundary assertion |
|
|
245
|
+
|
|
246
|
+
## 8.13 — byte input/output
|
|
247
|
+
|
|
248
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
249
|
+
| --- | --- | --- | --- |
|
|
250
|
+
| 8.13.1 `get_byte/1-2` | input next byte or `-1` at EOF | covered | strict binary-stream success and byte corpus |
|
|
251
|
+
| 8.13.1 errors | variable stream; invalid fixed in-byte; invalid/missing/output stream; text stream; EOF-action conditions | covered | strict assertions and EOF stream corpus |
|
|
252
|
+
| 8.13.2 `peek_byte/1-2` | inspect next byte without changing position | covered | strict binary-stream success and byte corpus |
|
|
253
|
+
| 8.13.2 errors | corresponding fixed-byte, stream, text-stream, and EOF conditions | covered | strict assertions / shared byte-I/O implementation tests |
|
|
254
|
+
| 8.13.3 `put_byte/1-2` | output one byte to a binary stream | covered | strict binary-output success and byte corpus |
|
|
255
|
+
| 8.13.3 errors | variable byte/stream; non-byte value; invalid/missing/input stream; text stream | covered | dedicated strict assertions |
|
|
256
|
+
|
|
257
|
+
## 8.14 — term input/output, operators, and character conversion
|
|
258
|
+
|
|
259
|
+
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
260
|
+
| --- | --- | --- | --- |
|
|
261
|
+
| 8.14.1 `read_term/3`, `read_term/2`, `read/1-2` | read a term using the standardized read-option surface | covered | term-I/O corpus, Corrigendum 3 cases, strict success/error suite |
|
|
262
|
+
| 8.14.1 option/argument errors | stream/option instantiation, non-list options, invalid read option | covered | strict 8.14.1 individual-condition assertions |
|
|
263
|
+
| 8.14.1 stream/input errors | invalid/missing/output/binary stream, past-end state, invalid input character, syntax error | covered | strict and constructed-stream assertions |
|
|
264
|
+
| 8.14.1 conditional finite-number/arity representation branches | limits tied to finite selected processor bounds | not applicable where bound is unbounded | EyeProlog selects unbounded integers/`max_arity`; finite binary64 input limits remain documented separately |
|
|
265
|
+
| 8.14.1 Corrigendum options | `variables/1`, `variable_names/1`, `singletons/1` list traversal/unification behavior | covered | Corrigendum 3 metadata tests and STC #48 regression |
|
|
266
|
+
| 8.14.2 `write_term/3`, `write_term/2`, `write/1-2`, `writeq/1-2` | write terms under standardized write options | covered | term-I/O/write-back corpus and strict writer suite |
|
|
267
|
+
| 8.14.2 option/argument errors | stream/option instantiation, non-list options, invalid write option | covered | strict 8.14.2 assertions |
|
|
268
|
+
| 8.14.2 stream/output errors | invalid/missing/input/binary stream and character representation conditions | covered | strict and constructed-stream assertions |
|
|
269
|
+
| 8.14.2 contradictory write options | rightmost option applies | covered | writer option corpus |
|
|
270
|
+
| 8.14.3 `op/3` | add/remove operators subject to Part 1 restrictions | covered | operator corpus and preparation-time ordering tests |
|
|
271
|
+
| 8.14.3 errors | priority/specifier/name instantiation/type/domain plus protected-operator permission conditions | covered | strict `op/3` individual-condition suite |
|
|
272
|
+
| 8.14.4 `current_op/3` | enumerate/query current operator definitions | covered | operator corpus and strict success assertion |
|
|
273
|
+
| 8.14.4 errors | invalid priority/specifier/operator filters | covered | strict `current_op/3` individual-condition suite |
|
|
274
|
+
| 8.14.5 `char_conversion/2` | update character-conversion mapping | covered | preparation/runtime conversion tests and strict success assertion |
|
|
275
|
+
| 8.14.5 errors | input/output instantiation and processor-character representation conditions | covered | dedicated strict assertions |
|
|
276
|
+
| 8.14.6 `current_char_conversion/2` | enumerate/query current conversion mapping | covered | strict success assertion and conversion corpus |
|
|
277
|
+
| 8.14.6 errors | fixed input/output is not a character | covered | dedicated strict assertions |
|
|
278
|
+
|
|
105
279
|
## 8.15 — logic and control
|
|
106
280
|
|
|
107
281
|
| Clause / predicate | Prescribed row | Status | Executable evidence |
|
|
@@ -190,16 +364,15 @@ built-in matrix does not have a gap at 8.17.
|
|
|
190
364
|
| 8.17.4 variable status | instantiation error | covered | strict `halt(X)` |
|
|
191
365
|
| 8.17.4 non-integer status | integer type error | covered | strict `halt(a)` |
|
|
192
366
|
|
|
193
|
-
## Remaining
|
|
194
|
-
|
|
195
|
-
This file deliberately does not relabel the whole 8.2-8.17 family as complete.
|
|
196
|
-
The next row-by-row passes are:
|
|
367
|
+
## Remaining audit work
|
|
197
368
|
|
|
198
|
-
- 8.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
369
|
+
The built-in **8.2-8.17 row audit is complete** at the level tracked by this
|
|
370
|
+
file: prescribed modes, success/failure behavior, individual error conditions,
|
|
371
|
+
and conditional/not-applicable processor branches all have explicit outcomes.
|
|
372
|
+
ISO 7.12 simultaneous-error selection remains an implementation-dependent
|
|
373
|
+
processor choice unless more specific normative text constrains it.
|
|
203
374
|
|
|
204
|
-
|
|
205
|
-
|
|
375
|
+
The remaining #65 work is therefore above/below this built-in table: Clause 6
|
|
376
|
+
text/rejection mapping, Clause 7 processor/control semantics, Clause 9
|
|
377
|
+
exceptional-value rows, residual Clause 5 dependency rows, and the external
|
|
378
|
+
conversion/variable-name conformance corpora.
|
|
@@ -15,7 +15,7 @@ marked `covered` means EyeProlog has implementation and executable tests for
|
|
|
15
15
|
that family and no known open defect in the listed behavior. A row marked
|
|
16
16
|
`audit` means the family is implemented and tested, but the project has not yet
|
|
17
17
|
mapped every normative `shall`, option combination, prescribed error, and
|
|
18
|
-
|
|
18
|
+
relevant implementation-dependent overlap choice to an explicit audit outcome.
|
|
19
19
|
|
|
20
20
|
## Processor compliance requirements
|
|
21
21
|
|
|
@@ -36,14 +36,14 @@ error-ordering alternative to an individual executable assertion.
|
|
|
36
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 now closed; wider shall-by-shall lexical mapping remains open. |
|
|
37
37
|
| 7.1-7.3 — term types, term order, unification | audit | Standard-order, identity, finite-tree and occurs-check suites, Corrigendum 2 term predicates, plus strict checks for the required `variable < float < integer < atom < compound` type order, PCS-based atom collation, and the `max_arity=unbounded` compound-term model. The normal JavaScript API string term is now explicitly documented as a 5.5.4 extension and rejected at strict program/goal entry so it cannot add a sixth strict-core type. |
|
|
38
38
|
| 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
|
-
| 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.
|
|
39
|
+
| 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
40
|
| 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
41
|
| 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
42
|
| 7.9 — expression evaluation | audit | Arithmetic/evaluation/error suites, including Corrigenda. Strict mode now pins direct-variable precedence, 7.9.2 non-evaluable `F/N` errors (including STC #69), arithmetic numeric/integer type errors, float-only rounding conversions, the Part 1 mixed integer/float comparison conversion rule, I->F overflow before floating evaluable functors (STC #42), explicit `exp/1`/power underflow, and prescribed negative/zero power errors before later conversion overflow. Unbounded integer powers/shifts no longer leak host `RangeError`; finite-host exhaustion is normalized to `resource_error(memory)` in line with the Part 1 resource-error note and STC #21. The remaining exceptional-value/error-precedence rows are still being exhaustively enumerated. |
|
|
43
|
-
| 7.10 — input/output concepts | audit | Stream, character/byte I/O, read/write options, operator-sensitive write-back, and Corrigendum 3 writer cases. The
|
|
43
|
+
| 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
44
|
| 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
|
-
| 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
|
|
46
|
-
| 8.2-8.17 — built-in predicates |
|
|
45
|
+
| 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
|
+
| 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
47
|
| Clause 9 — evaluable functors | audit | Integer/float/rounding/transcendental/bitwise suites and corrigendum cases. Strict mode excludes the EyeProlog-only evaluable atom `e`, retains Corrigendum 2 arithmetic additions, reports unknown zero-arity evaluables with the required `F/0` culprit shape, distinguishes non-evaluable `F/N` errors from numeric/integer operand errors per 7.9.2 and STC #69, and enforces float-only rounding modes, performs I->F conversion before floating functors (including overflow), reports the explicit `exp/1`, `**/2`, and Corrigendum 2 `^/2` underflow conditions, preserves the power-specific undefined conditions ahead of conversion overflow, and uses the Part 1 integer-to-float rule for mixed arithmetic comparisons. Normal mode retains EyeProlog's exact mixed-type comparison and round-to-zero arithmetic behavior as extensions. Unbounded BigInt resource exhaustion is translated into the Prolog error model rather than leaking host exceptions. Host floating-point representation choices remain documented implementation-defined behavior; the remaining exceptional-value rows are still under audit. |
|
|
48
48
|
| Corrigendum 1 | covered | Double-quoted atom/operator-priority corrections have dedicated cases. |
|
|
49
49
|
| Corrigendum 2 | covered | Added predicates/functors, catch corrections, bar/operator and uninstantiation corrections have dedicated cases. |
|
|
@@ -82,7 +82,7 @@ removes the artificial 65535 checks from source parsing, `functor/3`, `=../2`,
|
|
|
82
82
|
predicate indicators, and Corrigendum 2 `call/N` closure expansion. Practical
|
|
83
83
|
host exhaustion remains a resource condition rather than a declared term-arity
|
|
84
84
|
boundary. Focused strict tests also lock the corrected 8.5 term-construction
|
|
85
|
-
errors, 8.8 clause-access
|
|
85
|
+
errors, selected 8.8 clause-access and 8.10 all-solutions overlap behavior,
|
|
86
86
|
database update errors, and Corrigendum 3 variable metadata traversal/write
|
|
87
87
|
naming.
|
|
88
88
|
|
|
@@ -97,8 +97,9 @@ standard value that is valid but not selectable from a value outside the
|
|
|
97
97
|
standard domain: attempts to change fixed `bounded` or
|
|
98
98
|
`integer_rounding_function` to another standard value therefore reach the
|
|
99
99
|
required permission error. `read_term/3`, `write_term/3`, `op/3`, and
|
|
100
|
-
`current_op/3` now
|
|
101
|
-
|
|
100
|
+
`current_op/3` now cover their required error conditions individually and keep
|
|
101
|
+
EyeProlog's chosen simultaneous-error behavior stable. Section 7.12 makes that
|
|
102
|
+
choice implementation dependent when several error conditions hold at once. Strict `write_term/2-3` accepts only
|
|
102
103
|
the Part 1 plus Corrigendum 3 option surface; the normal-profile
|
|
103
104
|
`double_quotes/1` write option remains an explicitly documented EyeProlog
|
|
104
105
|
extension.
|
|
@@ -115,7 +116,7 @@ EOF, close, and current-stream behavior. Corrigendum 2 `keysort/2` variable and
|
|
|
115
116
|
non-pair errors are corrected. Strict arithmetic no longer exposes the
|
|
116
117
|
EyeProlog-only evaluable atom `e`, while the Corrigendum arithmetic additions
|
|
117
118
|
remain available. These corrections narrow the remaining `audit` rows but do
|
|
118
|
-
not by themselves close the full shall-by-shall/error-
|
|
119
|
+
not by themselves close the full shall-by-shall/error-condition exit criteria.
|
|
119
120
|
|
|
120
121
|
The next Corrigendum 2 pass closed the prescribed `call/2..8` max-arity
|
|
121
122
|
branch for processors with a finite `max_arity`, and corrected reverse
|
|
@@ -128,8 +129,10 @@ expansion itself remains covered by strict regressions.
|
|
|
128
129
|
|
|
129
130
|
The following Part 1 pass tightens more of the still-open prescribed-error and
|
|
130
131
|
arithmetic matrix. `arg/3`, `atom_concat/3`, `sub_atom/5`, `number_chars/2`,
|
|
131
|
-
`number_codes/2`, and `char_conversion/2` now
|
|
132
|
-
|
|
132
|
+
`number_codes/2`, and `char_conversion/2` now cover their individual standard
|
|
133
|
+
error conditions and retain deterministic EyeProlog choices for overlapping
|
|
134
|
+
conditions; 7.12 explicitly leaves such simultaneous-error selection
|
|
135
|
+
implementation dependent unless another rule constrains it. Corrigendum 2 partial
|
|
133
136
|
versus improper list distinctions are applied consistently to atomic and
|
|
134
137
|
number conversion. Clause 9 strict evaluation now gives the prescribed
|
|
135
138
|
number/integer operand diagnostics, checks direct-variable instantiation first,
|
|
@@ -187,6 +190,29 @@ now documented under 5.5.4, while strict `Program` construction and strict
|
|
|
187
190
|
keeps the host extension available in normal mode without allowing it to become
|
|
188
191
|
a sixth term type in the Part 1 strict execution domain.
|
|
189
192
|
|
|
193
|
+
A row-level 8.6-8.10 pass then turns arithmetic predicates, clause/database
|
|
194
|
+
operations, and all-solutions predicates into explicit mode/error-condition
|
|
195
|
+
entries. During that audit, strict source preparation exposed a 7.6.2 defect:
|
|
196
|
+
a clause such as `foo(X) :- X.` was executed as a variable goal but was not
|
|
197
|
+
stored in the converted `call(X)` form, so `clause(foo(C),call(C))` and the
|
|
198
|
+
corresponding `retract/1` pattern lost the required head/body variable identity.
|
|
199
|
+
Strict preparation now performs the same recursive body conversion used by
|
|
200
|
+
runtime assertion while preserving the original variable objects. The pass
|
|
201
|
+
also records the 7.12 rule for simultaneous errors, so deterministic overlap
|
|
202
|
+
tests are treated as processor choices unless more specific normative text
|
|
203
|
+
constrains them.
|
|
204
|
+
|
|
205
|
+
The subsequent 8.11-8.14 pass completes the built-in row audit. Stream
|
|
206
|
+
selection/control, character/code input and output, byte I/O, term I/O,
|
|
207
|
+
operators, and character conversion now each have explicit success/mode and
|
|
208
|
+
individual-error outcomes in `ISO-BUILTIN-MODE-ERROR-MATRIX.md`. During this
|
|
209
|
+
pass `stream_property/2` exposed a lifecycle distinction: a syntactically valid
|
|
210
|
+
stream-term for a stream that has been closed denotes no currently open stream
|
|
211
|
+
property pair and therefore fails, whereas a term that is not a stream-term is
|
|
212
|
+
still a `domain_error(stream, ...)`. This leaves the remaining #65 checklist
|
|
213
|
+
focused on Clause 6/7/9 processor semantics and external corpora rather than
|
|
214
|
+
unmapped built-in tables.
|
|
215
|
+
|
|
190
216
|
## Post-Corrigendum STC cross-check
|
|
191
217
|
|
|
192
218
|
The public WG17 STC draft is tracked as useful defect-discovery material, but it
|
|
@@ -261,8 +287,9 @@ ISO/IEC 13211-1 processor” until all of the following are true:
|
|
|
261
287
|
3. the external WG17 conversion and variable-name conformity corpora have
|
|
262
288
|
joined the now-complete syntax corpus in strict core mode, with every
|
|
263
289
|
difference explained or fixed;
|
|
264
|
-
4. prescribed modes,
|
|
265
|
-
|
|
290
|
+
4. prescribed modes, individual error conditions, side effects, and any
|
|
291
|
+
precedence actually constrained by procedural rules or Corrigenda have
|
|
292
|
+
executable coverage, while 7.12 simultaneous-error choices are documented;
|
|
266
293
|
5. every `audit gap` recorded in the ISO 5.4 decision index is either fixed or
|
|
267
294
|
explicitly excluded from the strict-conformance claim; and
|
|
268
295
|
6. an external conformance run has found no unexplained deviations.
|
|
@@ -12,9 +12,9 @@ compliance audit and the remaining work before a full conformance claim.
|
|
|
12
12
|
| Clause 7 term order and unification | finite-tree unification, identity, standard order, errors | `unification_control_information`, `swipl_occurs_check`, `term_modes_and_ordering`, `logtalk_compare_standard_order` |
|
|
13
13
|
| 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
14
|
| 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
|
-
| 8.6-8.7 arithmetic predicates | `is/2` and all six arithmetic comparisons | `arithmetic`, comparison cases, isolated evaluation errors |
|
|
16
|
-
| 8.8-8.10 database and solutions | logical update view, dynamic mutation, all-solutions grouping | `dynamic_database`, `trealla_logical_update_view`, `corrigenda_retractall`, `grouped_solutions_and_clauses`,
|
|
17
|
-
| 8.11-8.14 streams and term I/O | text/binary streams, properties, units, read/write options and operators | `streams_and_term_io`, `operators`, Corrigendum 3 option cases, stream error cases,
|
|
15
|
+
| 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 |
|
|
16
|
+
| 8.8-8.10 database and solutions | logical update view, dynamic mutation, all-solutions grouping | `dynamic_database`, `trealla_logical_update_view`, `corrigenda_retractall`, `grouped_solutions_and_clauses`, the complete row-level 8.8-8.10 mode/error-condition audit, source/runtime 7.6.2 conversion through `,/2`, `;/2`, and `->/2` with preserved head/body variable sharing, selected deterministic overlap checks, runtime static/private protection for conjunction, and STC #56 `(:-)/1-2` database protection |
|
|
17
|
+
| 8.11-8.14 streams and term I/O | text/binary streams, properties, units, read/write options and operators | `streams_and_term_io`, `operators`, Corrigendum 3 option cases, stream error cases, the complete row-level 8.11-8.14 mode/error audit, Corrigendum 3 variable metadata/write naming checks, and issue #65 checks for stream lifecycle/property validation (including closed-stream failure), text-vs-binary permissions, EOF/flush/position, open/close semantics, presence-based `force(true)` close handling, late `get_code/peek_code` in-character-code representation errors, and the exact `alias(A)` collision culprit |
|
|
18
18
|
| 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
19
|
| 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
20
|
| 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` |
|
|
@@ -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 | Clause 7-9 suites plus the row-audited built-in
|
|
20
|
+
| 5.1(b) execute conforming Prolog goals | audit | Clause 7-9 suites plus the now-complete 8.2-8.17 row-audited built-in family in `ISO-BUILTIN-MODE-ERROR-MATRIX.md`; remaining Clause 7/9 processor-semantic rows are still being enumerated |
|
|
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 and Clause 7-9 regression suites;
|
|
30
|
+
| 5.3 conforming and strictly conforming Prolog goal boundary | audit | strict registry/control/evaluable filtering and Clause 7-9 regression suites; the built-in 8.2-8.17 mode/error rows are closed, while remaining general goal/control and Clause 9 semantic rows stay 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
|
|
@@ -43,7 +43,7 @@ certification claim.
|
|
|
43
43
|
| 5.5.6 additional side effects | audit | host/proof/statistics/library effects are outside the strict registry or documented normal-mode behavior; exhaustive side-effect preservation mapping remains part of the Clause 7.7/7.10 audit |
|
|
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
|
-
| 5.5.9 additional built-in predicates and error forms |
|
|
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
47
|
| 5.5.10 additional evaluable functors/types | audit | strict mode excludes normal-profile arithmetic extensions such as evaluable `e`; Clause 9 exceptional-value and error-precedence rows remain under audit |
|
|
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
|
|
|
@@ -23,10 +23,10 @@ profile and implementation extensions. The default registry covers the exact
|
|
|
23
23
|
predicate indicators listed in Appendix B of the book across the Part 1 strict-core
|
|
24
24
|
target and the normal-mode module/DCG compatibility families. [ISO-COMPLIANCE.md](ISO-COMPLIANCE.md) is the explicit
|
|
25
25
|
release-facing ledger for the Part 1 strict-core audit. This suite is
|
|
26
|
-
still not an independent certification of every processor requirement
|
|
27
|
-
edge
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
still not an independent certification of every processor requirement or lexical
|
|
27
|
+
edge. The complete 8.2-8.17 built-in family is now tracked one prescribed
|
|
28
|
+
mode/error row at a time; the remaining Clause 6/7/9 and processor semantics
|
|
29
|
+
stay explicitly open in the dedicated audit files. Cases under `iso/`
|
|
30
30
|
identify standards-derived behavior; other directories cover EyeProlog host
|
|
31
31
|
contracts and extensions. EyeProlog-only execution features such as automatic
|
|
32
32
|
tabling and `tnot/1` well-founded negation are outside the Part 1 strict-core
|
package/test/run-iso-strict.mjs
CHANGED
|
@@ -237,7 +237,7 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
237
237
|
includes(error.message, 'alias(user_input)', 'alias option culprit');
|
|
238
238
|
});
|
|
239
239
|
|
|
240
|
-
reporter.test('
|
|
240
|
+
reporter.test('covers ISO 8.14.1.3 read_term/3 errors and selected overlaps', () => {
|
|
241
241
|
equal(capture(() => run('', { isoStrict: true, goal: 'read_term(f(a),_,[X])' })).formal,
|
|
242
242
|
'instantiation_error', 'partial/variable option before stream domain');
|
|
243
243
|
equal(capture(() => run('', { isoStrict: true, goal: 'read_term(f(a),_,foo)' })).formal,
|
|
@@ -258,7 +258,7 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
258
258
|
equal(solver.io.resolve('user_input').position, 0, 'invalid options are rejected before input');
|
|
259
259
|
});
|
|
260
260
|
|
|
261
|
-
reporter.test('
|
|
261
|
+
reporter.test('covers ISO 8.14.2.3 write_term/3 errors and selected overlaps', () => {
|
|
262
262
|
equal(capture(() => run('', { isoStrict: true, goal: 'write_term(f(a),a,[X])' })).formal,
|
|
263
263
|
'instantiation_error', 'partial/variable option before stream domain');
|
|
264
264
|
equal(capture(() => run('', { isoStrict: true, goal: 'write_term(f(a),a,foo)' })).formal,
|
|
@@ -271,7 +271,7 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
271
271
|
'domain_error(write_option)', 'invalid option before stream permission');
|
|
272
272
|
});
|
|
273
273
|
|
|
274
|
-
reporter.test('
|
|
274
|
+
reporter.test('covers ISO 8.14.3.3 op/3 errors and selected overlaps', () => {
|
|
275
275
|
equal(capture(() => run('', { isoStrict: true, goal: 'op(a,X,0)' })).formal,
|
|
276
276
|
'instantiation_error', 'specifier variable before priority type');
|
|
277
277
|
equal(capture(() => run('', { isoStrict: true, goal: 'op(a,xfy,[X])' })).formal,
|
|
@@ -297,7 +297,7 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
297
297
|
'type_error(atom)', 'operator type');
|
|
298
298
|
});
|
|
299
299
|
|
|
300
|
-
reporter.test('
|
|
300
|
+
reporter.test('covers remaining Part 1 built-in error conditions and overlap choices', () => {
|
|
301
301
|
const cases = [
|
|
302
302
|
['arg(a,X,_)', 'instantiation_error', 'arg/3 second-argument instantiation before index type'],
|
|
303
303
|
['atom_concat(1,X,Y)', 'instantiation_error', 'atom_concat/3 second/whole under-instantiation before first type'],
|
|
@@ -317,9 +317,9 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
317
317
|
});
|
|
318
318
|
|
|
319
319
|
reporter.test('orders input-code representation errors after stream diagnostics', () => {
|
|
320
|
-
//
|
|
321
|
-
//
|
|
322
|
-
//
|
|
320
|
+
// Keep EyeProlog's selected 8.12 overlap behavior stable: integer type
|
|
321
|
+
// errors are detected before stream access, while a valid integer outside
|
|
322
|
+
// the in-character-code domain is diagnosed after stream/entity errors.
|
|
323
323
|
for (const predicate of ['get_code', 'peek_code']) {
|
|
324
324
|
equal(capture(() => run('', { isoStrict: true, goal: `${predicate}(user_output,-2)` })).formal,
|
|
325
325
|
'permission_error(input, stream)', `${predicate}/2 output stream before bad code`);
|
|
@@ -354,6 +354,216 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
354
354
|
'representation_error(in_character_code)', 'bad code once no earlier stream error applies');
|
|
355
355
|
});
|
|
356
356
|
|
|
357
|
+
reporter.test('closes the ISO 8.11 stream selection/control rows', () => {
|
|
358
|
+
const errors = [
|
|
359
|
+
['current_input(foo)', 'domain_error(stream)', 'current_input/1 stream term'],
|
|
360
|
+
['current_output(foo)', 'domain_error(stream)', 'current_output/1 stream term'],
|
|
361
|
+
['set_input(X)', 'instantiation_error', 'set_input/1 variable'],
|
|
362
|
+
['set_input(f(a))', 'domain_error(stream_or_alias)', 'set_input/1 stream-or-alias domain'],
|
|
363
|
+
['set_input(no_such_stream)', 'existence_error(stream)', 'set_input/1 closed/missing stream'],
|
|
364
|
+
['set_input(user_output)', 'permission_error(input, stream)', 'set_input/1 output stream'],
|
|
365
|
+
['set_output(X)', 'instantiation_error', 'set_output/1 variable'],
|
|
366
|
+
['set_output(f(a))', 'domain_error(stream_or_alias)', 'set_output/1 stream-or-alias domain'],
|
|
367
|
+
['set_output(no_such_stream)', 'existence_error(stream)', 'set_output/1 closed/missing stream'],
|
|
368
|
+
['set_output(user_input)', 'permission_error(output, stream)', 'set_output/1 input stream'],
|
|
369
|
+
['open(X,read,S,[])', 'instantiation_error', 'open/4 source instantiation'],
|
|
370
|
+
['open(dummy,X,S,[])', 'instantiation_error', 'open/4 mode instantiation'],
|
|
371
|
+
['open(dummy,read,S,[X])', 'instantiation_error', 'open/4 option instantiation'],
|
|
372
|
+
['open(dummy,1,S,[])', 'type_error(atom)', 'open/4 mode type'],
|
|
373
|
+
['open(dummy,read,S,foo)', 'type_error(list)', 'open/4 options list type'],
|
|
374
|
+
['open(dummy,read,already_bound,[])', 'uninstantiation_error', 'open/4 stream output mode'],
|
|
375
|
+
['open(4,read,S,[])', 'domain_error(source_sink)', 'open/4 source/sink domain'],
|
|
376
|
+
['open(dummy,bad,S,[])', 'domain_error(io_mode)', 'open/4 io mode domain'],
|
|
377
|
+
['open(dummy,write,S,[bogus])', 'domain_error(stream_option)', 'open/4 stream option domain'],
|
|
378
|
+
['close(X,[])', 'instantiation_error', 'close/2 stream instantiation'],
|
|
379
|
+
['close(no_such_stream,[X])', 'instantiation_error', 'close/2 option instantiation'],
|
|
380
|
+
['close(no_such_stream,foo)', 'type_error(list)', 'close/2 options list type'],
|
|
381
|
+
['close(f(a),[])', 'domain_error(stream_or_alias)', 'close/2 stream-or-alias domain'],
|
|
382
|
+
['close(no_such_stream,[bogus])', 'domain_error(close_option)', 'close/2 close option domain'],
|
|
383
|
+
['close(no_such_stream,[])', 'existence_error(stream)', 'close/2 missing stream'],
|
|
384
|
+
['flush_output(X)', 'instantiation_error', 'flush_output/1 variable'],
|
|
385
|
+
['flush_output(f(a))', 'domain_error(stream_or_alias)', 'flush_output/1 stream-or-alias domain'],
|
|
386
|
+
['flush_output(no_such_stream)', 'existence_error(stream)', 'flush_output/1 missing stream'],
|
|
387
|
+
['flush_output(user_input)', 'permission_error(output, stream)', 'flush_output/1 input stream'],
|
|
388
|
+
['stream_property(foo,P)', 'domain_error(stream)', 'stream_property/2 stream term domain'],
|
|
389
|
+
['stream_property(S,bogus)', 'domain_error(stream_property)', 'stream_property/2 property domain'],
|
|
390
|
+
['at_end_of_stream(X)', 'instantiation_error', 'at_end_of_stream/1 variable'],
|
|
391
|
+
['at_end_of_stream(f(a))', 'domain_error(stream_or_alias)', 'at_end_of_stream/1 stream-or-alias domain'],
|
|
392
|
+
['at_end_of_stream(no_such_stream)', 'existence_error(stream)', 'at_end_of_stream/1 missing stream'],
|
|
393
|
+
['set_stream_position(X,0)', 'instantiation_error', 'set_stream_position/2 stream instantiation'],
|
|
394
|
+
['set_stream_position(user_input,X)', 'instantiation_error', 'set_stream_position/2 position instantiation'],
|
|
395
|
+
['set_stream_position(f(a),0)', 'domain_error(stream_or_alias)', 'set_stream_position/2 stream-or-alias domain'],
|
|
396
|
+
['set_stream_position(user_input,foo)', 'domain_error(stream_position)', 'set_stream_position/2 position domain'],
|
|
397
|
+
['set_stream_position(no_such_stream,0)', 'existence_error(stream)', 'set_stream_position/2 missing stream'],
|
|
398
|
+
['set_stream_position(user_input,0)', 'permission_error(reposition, stream)', 'set_stream_position/2 non-repositionable stream'],
|
|
399
|
+
];
|
|
400
|
+
for (const [goal, formal, label] of errors) {
|
|
401
|
+
equal(capture(() => run('', { isoStrict: true, goal })).formal, formal, label);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
equal(run('', { isoStrict: true, goal: 'current_input(S),stream_property(S,input)' }).stats.completed_goal_lists, 1,
|
|
405
|
+
'current_input/1 successful mode');
|
|
406
|
+
equal(run('', { isoStrict: true, goal: 'current_output(S),stream_property(S,output)' }).stats.completed_goal_lists, 1,
|
|
407
|
+
'current_output/1 successful mode');
|
|
408
|
+
equal(run('', { isoStrict: true, goal: 'flush_output(user_output)' }).stats.completed_goal_lists, 1,
|
|
409
|
+
'flush_output/1 successful mode');
|
|
410
|
+
equal(run('', { isoStrict: true, goal: 'at_end_of_stream(user_input)' }).stats.completed_goal_lists, 1,
|
|
411
|
+
'at_end_of_stream/1 at empty standard input');
|
|
412
|
+
|
|
413
|
+
const openErrorSolver = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
414
|
+
openErrorSolver.io.open = () => { throw Object.assign(new Error('missing'), { code: 'ENOENT' }); };
|
|
415
|
+
equal(capture(() => [...openErrorSolver.solve([
|
|
416
|
+
parseGoalText('open(missing,read,S,[])', { isoStrict: true }),
|
|
417
|
+
], new Env(), 0)]).formal, 'existence_error(source_sink)', 'open/4 missing read source');
|
|
418
|
+
openErrorSolver.io.open = () => { throw new Error('denied'); };
|
|
419
|
+
equal(capture(() => [...openErrorSolver.solve([
|
|
420
|
+
parseGoalText('open(denied,write,S,[])', { isoStrict: true }),
|
|
421
|
+
], new Env(), 0)]).formal, 'permission_error(open, source_sink)', 'open/4 cannot open sink');
|
|
422
|
+
|
|
423
|
+
const closedSolver = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
424
|
+
const closed = closedSolver.io.add({
|
|
425
|
+
id: 2, alias: 'closed_stream', mode: 'read', type: 'text', content: 'a', position: 0, path: '',
|
|
426
|
+
reposition: true, eofAction: 'error', standard: false, pastEnd: false,
|
|
427
|
+
});
|
|
428
|
+
closedSolver.io.discard(closed);
|
|
429
|
+
equal([...closedSolver.solve([
|
|
430
|
+
parseGoalText("stream_property('$stream'(2),_)", { isoStrict: true }),
|
|
431
|
+
], new Env(), 0)].length, 0, 'closed valid stream-term has no current stream property');
|
|
432
|
+
|
|
433
|
+
const positionedSolver = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
434
|
+
positionedSolver.io.add({
|
|
435
|
+
id: 2, alias: 'positioned', mode: 'read', type: 'text', content: 'ab', position: 0, path: '',
|
|
436
|
+
reposition: true, eofAction: 'error', standard: false, pastEnd: false,
|
|
437
|
+
});
|
|
438
|
+
equal([...positionedSolver.solve([
|
|
439
|
+
parseGoalText('set_stream_position(positioned,1)', { isoStrict: true }),
|
|
440
|
+
parseGoalText("get_char(positioned,'b')", { isoStrict: true }),
|
|
441
|
+
], new Env(), 0)].length, 1, 'set_stream_position/2 successful mode');
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
reporter.test('closes the ISO 8.12-8.14 character, byte, and term-I/O rows', () => {
|
|
445
|
+
const errors = [
|
|
446
|
+
['get_char(S,C)', 'instantiation_error', 'get_char/2 stream instantiation'],
|
|
447
|
+
['get_char(user_input,ab)', 'type_error(in_character)', 'get_char/2 in-character type'],
|
|
448
|
+
['get_char(f(a),C)', 'domain_error(stream_or_alias)', 'get_char/2 stream-or-alias domain'],
|
|
449
|
+
['get_char(no_such_stream,C)', 'existence_error(stream)', 'get_char/2 missing stream'],
|
|
450
|
+
['get_char(user_output,C)', 'permission_error(input, stream)', 'get_char/2 output stream'],
|
|
451
|
+
['get_code(S,C)', 'instantiation_error', 'get_code/2 stream instantiation'],
|
|
452
|
+
['get_code(user_input,foo)', 'type_error(integer)', 'get_code/2 integer type'],
|
|
453
|
+
['get_code(f(a),C)', 'domain_error(stream_or_alias)', 'get_code/2 stream-or-alias domain'],
|
|
454
|
+
['get_code(no_such_stream,C)', 'existence_error(stream)', 'get_code/2 missing stream'],
|
|
455
|
+
['get_code(user_output,C)', 'permission_error(input, stream)', 'get_code/2 output stream'],
|
|
456
|
+
['get_code(-2)', 'representation_error(in_character_code)', 'get_code/1 in-character-code representation'],
|
|
457
|
+
['peek_char(S,C)', 'instantiation_error', 'peek_char/2 stream instantiation'],
|
|
458
|
+
['peek_char(user_input,ab)', 'type_error(in_character)', 'peek_char/2 in-character type'],
|
|
459
|
+
['peek_code(user_input,foo)', 'type_error(integer)', 'peek_code/2 integer type'],
|
|
460
|
+
['put_char(S,a)', 'instantiation_error', 'put_char/2 stream instantiation'],
|
|
461
|
+
['put_char(X)', 'instantiation_error', 'put_char/1 character instantiation'],
|
|
462
|
+
['put_char(ab)', 'type_error(character)', 'put_char/1 character type'],
|
|
463
|
+
['put_char(f(a),a)', 'domain_error(stream_or_alias)', 'put_char/2 stream-or-alias domain'],
|
|
464
|
+
['put_char(no_such_stream,a)', 'existence_error(stream)', 'put_char/2 missing stream'],
|
|
465
|
+
['put_char(user_input,a)', 'permission_error(output, stream)', 'put_char/2 input stream'],
|
|
466
|
+
['put_code(S,97)', 'instantiation_error', 'put_code/2 stream instantiation'],
|
|
467
|
+
['put_code(X)', 'instantiation_error', 'put_code/1 code instantiation'],
|
|
468
|
+
['put_code(foo)', 'type_error(integer)', 'put_code/1 integer type'],
|
|
469
|
+
['put_code(f(a),97)', 'domain_error(stream_or_alias)', 'put_code/2 stream-or-alias domain'],
|
|
470
|
+
['put_code(no_such_stream,97)', 'existence_error(stream)', 'put_code/2 missing stream'],
|
|
471
|
+
['put_code(user_input,97)', 'permission_error(output, stream)', 'put_code/2 input stream'],
|
|
472
|
+
['put_code(1114112)', 'representation_error(character_code)', 'put_code/1 character-code representation'],
|
|
473
|
+
['nl(S)', 'instantiation_error', 'nl/1 stream instantiation'],
|
|
474
|
+
['nl(f(a))', 'domain_error(stream_or_alias)', 'nl/1 stream-or-alias domain'],
|
|
475
|
+
['nl(no_such_stream)', 'existence_error(stream)', 'nl/1 missing stream'],
|
|
476
|
+
['nl(user_input)', 'permission_error(output, stream)', 'nl/1 input stream'],
|
|
477
|
+
['get_byte(S,B)', 'instantiation_error', 'get_byte/2 stream instantiation'],
|
|
478
|
+
['get_byte(256)', 'type_error(in_byte)', 'get_byte/1 in-byte type'],
|
|
479
|
+
['get_byte(f(a),B)', 'domain_error(stream_or_alias)', 'get_byte/2 stream-or-alias domain'],
|
|
480
|
+
['get_byte(no_such_stream,B)', 'existence_error(stream)', 'get_byte/2 missing stream'],
|
|
481
|
+
['get_byte(user_output,B)', 'permission_error(input, stream)', 'get_byte/2 output stream'],
|
|
482
|
+
['get_byte(B)', 'permission_error(input, text_stream)', 'get_byte/1 text stream'],
|
|
483
|
+
['peek_byte(S,B)', 'instantiation_error', 'peek_byte/2 stream instantiation'],
|
|
484
|
+
['peek_byte(256)', 'type_error(in_byte)', 'peek_byte/1 in-byte type'],
|
|
485
|
+
['put_byte(S,1)', 'instantiation_error', 'put_byte/2 stream instantiation'],
|
|
486
|
+
['put_byte(X)', 'instantiation_error', 'put_byte/1 byte instantiation'],
|
|
487
|
+
['put_byte(256)', 'type_error(byte)', 'put_byte/1 byte type'],
|
|
488
|
+
['put_byte(f(a),1)', 'domain_error(stream_or_alias)', 'put_byte/2 stream-or-alias domain'],
|
|
489
|
+
['put_byte(no_such_stream,1)', 'existence_error(stream)', 'put_byte/2 missing stream'],
|
|
490
|
+
['put_byte(user_input,1)', 'permission_error(output, stream)', 'put_byte/2 input stream'],
|
|
491
|
+
['put_byte(1)', 'permission_error(output, text_stream)', 'put_byte/1 text stream'],
|
|
492
|
+
['read_term(S,T,[])', 'instantiation_error', 'read_term/3 stream instantiation'],
|
|
493
|
+
['read_term(f(a),T,[])', 'domain_error(stream_or_alias)', 'read_term/3 stream-or-alias domain'],
|
|
494
|
+
['read_term(T,foo)', 'type_error(list)', 'read_term/2 options list type'],
|
|
495
|
+
['read_term(T,[bogus])', 'domain_error(read_option)', 'read_term/2 read option domain'],
|
|
496
|
+
['read_term(no_such_stream,T,[])', 'existence_error(stream)', 'read_term/3 missing stream'],
|
|
497
|
+
['read_term(user_output,T,[])', 'permission_error(input, stream)', 'read_term/3 output stream'],
|
|
498
|
+
['write_term(S,a,[])', 'instantiation_error', 'write_term/3 stream instantiation'],
|
|
499
|
+
['write_term(f(a),a,[])', 'domain_error(stream_or_alias)', 'write_term/3 stream-or-alias domain'],
|
|
500
|
+
['write_term(a,foo)', 'type_error(list)', 'write_term/2 options list type'],
|
|
501
|
+
['write_term(a,[bogus])', 'domain_error(write_option)', 'write_term/2 write option domain'],
|
|
502
|
+
['write_term(no_such_stream,a,[])', 'existence_error(stream)', 'write_term/3 missing stream'],
|
|
503
|
+
['write_term(user_input,a,[])', 'permission_error(output, stream)', 'write_term/3 input stream'],
|
|
504
|
+
["op(100,xfy,',')", 'permission_error(modify, operator)', 'op/3 protects comma'],
|
|
505
|
+
['current_op(a,_,_)', 'domain_error(operator_priority)', 'current_op/3 priority domain'],
|
|
506
|
+
['current_op(1,1,_)', 'domain_error(operator_specifier)', 'current_op/3 specifier domain'],
|
|
507
|
+
['current_op(1,fx,1)', 'type_error(atom)', 'current_op/3 operator type'],
|
|
508
|
+
['char_conversion(X,a)', 'instantiation_error', 'char_conversion/2 input instantiation'],
|
|
509
|
+
['char_conversion(a,X)', 'instantiation_error', 'char_conversion/2 output instantiation'],
|
|
510
|
+
['char_conversion(ab,a)', 'representation_error(character)', 'char_conversion/2 input representation'],
|
|
511
|
+
['char_conversion(a,ab)', 'representation_error(character)', 'char_conversion/2 output representation'],
|
|
512
|
+
['current_char_conversion(ab,X)', 'type_error(character)', 'current_char_conversion/2 input type'],
|
|
513
|
+
['current_char_conversion(a,ab)', 'type_error(character)', 'current_char_conversion/2 output type'],
|
|
514
|
+
];
|
|
515
|
+
for (const [goal, formal, label] of errors) {
|
|
516
|
+
equal(capture(() => run('', { isoStrict: true, goal })).formal, formal, label);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const binaryInput = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
520
|
+
binaryInput.io.add({
|
|
521
|
+
id: 2, alias: 'bin_in', mode: 'read', type: 'binary', content: [65], position: 0, path: '',
|
|
522
|
+
reposition: false, eofAction: 'error', standard: false, pastEnd: false,
|
|
523
|
+
});
|
|
524
|
+
for (const goal of ['get_char(bin_in,C)', 'get_code(bin_in,C)', 'peek_char(bin_in,C)', 'peek_code(bin_in,C)', 'read_term(bin_in,T,[])']) {
|
|
525
|
+
equal(capture(() => [...binaryInput.solve([parseGoalText(goal, { isoStrict: true })], new Env(), 0)]).formal,
|
|
526
|
+
'permission_error(input, binary_stream)', `${goal} binary stream`);
|
|
527
|
+
}
|
|
528
|
+
equal([...binaryInput.solve([parseGoalText('peek_byte(bin_in,65)', { isoStrict: true })], new Env(), 0)].length, 1,
|
|
529
|
+
'peek_byte/2 successful binary mode');
|
|
530
|
+
equal([...binaryInput.solve([parseGoalText('get_byte(bin_in,65)', { isoStrict: true })], new Env(), 0)].length, 1,
|
|
531
|
+
'get_byte/2 successful binary mode');
|
|
532
|
+
|
|
533
|
+
const binaryOutput = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
534
|
+
binaryOutput.io.add({
|
|
535
|
+
id: 2, alias: 'bin_out', mode: 'write', type: 'binary', content: [], position: 0, path: '',
|
|
536
|
+
reposition: false, eofAction: 'error', standard: false, pastEnd: false,
|
|
537
|
+
});
|
|
538
|
+
for (const goal of ['put_char(bin_out,a)', 'put_code(bin_out,97)', 'nl(bin_out)', 'write_term(bin_out,a,[])']) {
|
|
539
|
+
equal(capture(() => [...binaryOutput.solve([parseGoalText(goal, { isoStrict: true })], new Env(), 0)]).formal,
|
|
540
|
+
'permission_error(output, binary_stream)', `${goal} binary stream`);
|
|
541
|
+
}
|
|
542
|
+
equal([...binaryOutput.solve([parseGoalText('put_byte(bin_out,65)', { isoStrict: true })], new Env(), 0)].length, 1,
|
|
543
|
+
'put_byte/2 successful binary mode');
|
|
544
|
+
|
|
545
|
+
const pastInput = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
546
|
+
pastInput.io.add({
|
|
547
|
+
id: 2, alias: 'past_in', mode: 'read', type: 'text', content: '', position: 0, path: '',
|
|
548
|
+
reposition: false, eofAction: 'error', standard: false, pastEnd: true,
|
|
549
|
+
});
|
|
550
|
+
for (const goal of ['get_char(past_in,C)', 'get_code(past_in,C)', 'peek_char(past_in,C)', 'peek_code(past_in,C)', 'read_term(past_in,T,[])']) {
|
|
551
|
+
equal(capture(() => [...pastInput.solve([parseGoalText(goal, { isoStrict: true })], new Env(), 0)]).formal,
|
|
552
|
+
'permission_error(input, past_end_of_stream)', `${goal} past EOF`);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
equal(capture(() => run('', {
|
|
556
|
+
isoStrict: true,
|
|
557
|
+
goal: 'read_term(T,[])',
|
|
558
|
+
ioOptions: { input: "'unterminated." },
|
|
559
|
+
})).formal, 'syntax_error(read_term)', 'read_term/2 syntax error');
|
|
560
|
+
|
|
561
|
+
equal(run('', { isoStrict: true, goal: "char_conversion(a,b),current_char_conversion(a,b)" }).stats.completed_goal_lists, 1,
|
|
562
|
+
'char_conversion/2 and current_char_conversion/2 successful mode');
|
|
563
|
+
equal(run('', { isoStrict: true, goal: 'op(100,xf,zz),current_op(100,xf,zz)' }).stats.completed_goal_lists, 1,
|
|
564
|
+
'op/3 and current_op/3 successful mode');
|
|
565
|
+
});
|
|
566
|
+
|
|
357
567
|
reporter.test('treats close force(true) as presence-based', () => {
|
|
358
568
|
const closeWith = (options) => {
|
|
359
569
|
const solver = new Solver(Program.parse('', { isoStrict: true }), { isoStrict: true });
|
|
@@ -481,12 +691,12 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
481
691
|
}
|
|
482
692
|
});
|
|
483
693
|
|
|
484
|
-
reporter.test('
|
|
694
|
+
reporter.test('keeps the selected clause/2 private-procedure overlap behavior', () => {
|
|
485
695
|
equal(capture(() => run('p.\n', { isoStrict: true, goal: 'clause(atom(_),4)' })).formal,
|
|
486
696
|
'permission_error(access, private_procedure)', 'private procedure before body callability');
|
|
487
697
|
});
|
|
488
698
|
|
|
489
|
-
reporter.test('
|
|
699
|
+
reporter.test('keeps the selected all-solutions Goal-before-Instances overlap behavior', () => {
|
|
490
700
|
for (const predicate of ['findall', 'bagof', 'setof']) {
|
|
491
701
|
equal(capture(() => run('', { isoStrict: true, goal: `${predicate}(X,Y,foo)` })).formal,
|
|
492
702
|
'instantiation_error', `${predicate}/3 variable goal`);
|
|
@@ -700,6 +910,93 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
700
910
|
}
|
|
701
911
|
});
|
|
702
912
|
|
|
913
|
+
reporter.test('closes the ISO 8.6-8.10 prescribed mode/error rows', () => {
|
|
914
|
+
const errors = [
|
|
915
|
+
['X is Y', 'instantiation_error', 'is/2 variable expression'],
|
|
916
|
+
['X is foo', 'type_error(evaluable)', 'is/2 expression evaluation error'],
|
|
917
|
+
['X =:= 1', 'instantiation_error', '=:=/2 left variable'],
|
|
918
|
+
['1 =:= X', 'instantiation_error', '=:=/2 right variable'],
|
|
919
|
+
['X =\\= 1', 'instantiation_error', '=\\=/2 left variable'],
|
|
920
|
+
['1 < X', 'instantiation_error', '</2 right variable'],
|
|
921
|
+
['X =< 1', 'instantiation_error', '=</2 left variable'],
|
|
922
|
+
['1 > X', 'instantiation_error', '>/2 right variable'],
|
|
923
|
+
['X >= 1', 'instantiation_error', '>=/2 left variable'],
|
|
924
|
+
['foo =:= 1', 'type_error(evaluable)', 'arithmetic comparison evaluation error'],
|
|
925
|
+
['clause(X,_)', 'instantiation_error', 'clause/2 variable head'],
|
|
926
|
+
['clause(4,_)', 'type_error(callable)', 'clause/2 head type'],
|
|
927
|
+
['current_predicate(4)', 'type_error(predicate_indicator)', 'current_predicate/1 indicator type'],
|
|
928
|
+
['asserta(_)', 'instantiation_error', 'asserta/1 variable head'],
|
|
929
|
+
['asserta(4)', 'type_error(callable)', 'asserta/1 head type'],
|
|
930
|
+
['asserta((p:-4))', 'type_error(callable)', 'asserta/1 body conversion'],
|
|
931
|
+
['assertz(_)', 'instantiation_error', 'assertz/1 variable head'],
|
|
932
|
+
['assertz(4)', 'type_error(callable)', 'assertz/1 head type'],
|
|
933
|
+
['assertz((p:-4))', 'type_error(callable)', 'assertz/1 body conversion'],
|
|
934
|
+
['retract(_)', 'instantiation_error', 'retract/1 variable head'],
|
|
935
|
+
['retract(4)', 'type_error(callable)', 'retract/1 head type'],
|
|
936
|
+
['retractall(_)', 'instantiation_error', 'retractall/1 variable head'],
|
|
937
|
+
['retractall(4)', 'type_error(callable)', 'retractall/1 head type'],
|
|
938
|
+
['abolish(X)', 'instantiation_error', 'abolish/1 variable indicator'],
|
|
939
|
+
['abolish(foo/X)', 'instantiation_error', 'abolish/1 variable arity'],
|
|
940
|
+
['abolish(foo)', 'type_error(predicate_indicator)', 'abolish/1 indicator type'],
|
|
941
|
+
['abolish(foo/a)', 'type_error(integer)', 'abolish/1 arity type'],
|
|
942
|
+
['abolish(4/1)', 'type_error(atom)', 'abolish/1 name type'],
|
|
943
|
+
['abolish(foo/(-1))', 'domain_error(not_less_than_zero)', 'abolish/1 negative arity'],
|
|
944
|
+
['findall(X,Y,L)', 'instantiation_error', 'findall/3 variable goal'],
|
|
945
|
+
['findall(X,4,L)', 'type_error(callable)', 'findall/3 goal type'],
|
|
946
|
+
['findall(X,true,foo)', 'type_error(list)', 'findall/3 Instances type'],
|
|
947
|
+
['bagof(X,Y,L)', 'instantiation_error', 'bagof/3 variable iterated goal'],
|
|
948
|
+
['bagof(X,4,L)', 'type_error(callable)', 'bagof/3 iterated-goal type'],
|
|
949
|
+
['bagof(X,true,foo)', 'type_error(list)', 'bagof/3 Instances type'],
|
|
950
|
+
['setof(X,Y,L)', 'instantiation_error', 'setof/3 variable iterated goal'],
|
|
951
|
+
['setof(X,4,L)', 'type_error(callable)', 'setof/3 iterated-goal type'],
|
|
952
|
+
['setof(X,true,foo)', 'type_error(list)', 'setof/3 Instances type'],
|
|
953
|
+
];
|
|
954
|
+
for (const [goal, formal, label] of errors) {
|
|
955
|
+
equal(capture(() => run('', { isoStrict: true, goal })).formal, formal, label);
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
for (const goal of [
|
|
959
|
+
'X is 1+2, X=3',
|
|
960
|
+
'1 =:= 1',
|
|
961
|
+
'1 =\\= 2',
|
|
962
|
+
'1 < 2',
|
|
963
|
+
'1 =< 1',
|
|
964
|
+
'2 > 1',
|
|
965
|
+
'2 >= 2',
|
|
966
|
+
'findall(X,(X=1;X=2),[1,2])',
|
|
967
|
+
'bagof(X,(X=1;X=2),[1,2])',
|
|
968
|
+
'setof(X,(X=2;X=1;X=2),[1,2])',
|
|
969
|
+
]) {
|
|
970
|
+
equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists > 0, true, `${goal} successful mode`);
|
|
971
|
+
}
|
|
972
|
+
equal(run('', { isoStrict: true, goal: '4 is 1+2' }).stats.completed_goal_lists, 0, 'is/2 failed unification');
|
|
973
|
+
equal(run('', { isoStrict: true, goal: 'bagof(X,fail,L)' }).stats.completed_goal_lists, 0, 'bagof/3 empty solution set fails');
|
|
974
|
+
equal(run('', { isoStrict: true, goal: 'setof(X,fail,L)' }).stats.completed_goal_lists, 0, 'setof/3 empty solution set fails');
|
|
975
|
+
|
|
976
|
+
const current = run('p(a).\nq.\n', { isoStrict: true, goal: 'current_predicate(p/1)' });
|
|
977
|
+
equal(current.stats.completed_goal_lists, 1, 'current_predicate/1 finds a user procedure');
|
|
978
|
+
});
|
|
979
|
+
|
|
980
|
+
reporter.test('preserves 7.6.2 source-body conversion identity for clause/2 and retract/1', () => {
|
|
981
|
+
const source = [
|
|
982
|
+
':- dynamic(foo/1).',
|
|
983
|
+
'foo(X) :- X.',
|
|
984
|
+
':- dynamic(bar/1).',
|
|
985
|
+
'bar(X) :- (X ; true).',
|
|
986
|
+
':- dynamic(baz/1).',
|
|
987
|
+
'baz(X) :- (X -> true).',
|
|
988
|
+
'',
|
|
989
|
+
].join('\n');
|
|
990
|
+
equal(run(source, { isoStrict: true, goal: 'clause(foo(C),call(C))' }).stats.completed_goal_lists, 1,
|
|
991
|
+
'variable body converts to call/1 with head sharing');
|
|
992
|
+
equal(run(source, { isoStrict: true, goal: 'clause(bar(C),(call(C);true))' }).stats.completed_goal_lists, 1,
|
|
993
|
+
'disjunction recursively converts a variable branch');
|
|
994
|
+
equal(run(source, { isoStrict: true, goal: 'clause(baz(C),(call(C)->true))' }).stats.completed_goal_lists, 1,
|
|
995
|
+
'if-then recursively converts a variable branch');
|
|
996
|
+
equal(run(source, { isoStrict: true, goal: 'retract((foo(C):-call(C)))' }).stats.completed_goal_lists, 1,
|
|
997
|
+
'retract/1 sees the converted body with shared variables');
|
|
998
|
+
});
|
|
999
|
+
|
|
703
1000
|
reporter.test('closes the ISO 8.15-8.17 prescribed mode/error rows', () => {
|
|
704
1001
|
const cases = [
|
|
705
1002
|
['\\+(X)', 'instantiation_error', '\+/1 variable goal'],
|