eyeprolog 1.3.53 → 1.3.54
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 +7 -7
- package/package.json +1 -1
- package/src/iso-arithmetic.js +6 -33
- package/src/iso-character.js +9 -11
- package/src/iso.js +4 -3
- package/src/parser.js +56 -20
- package/src/term.js +15 -2
- package/test/conformance/ISO-COMPLIANCE.md +14 -13
- package/test/conformance/ISO-IMPLEMENTATION-DEFINED.md +7 -7
- package/test/conformance/ISO-MATRIX.md +1 -1
- package/test/conformance/README.md +4 -4
- package/test/conformance/STC-DRAFT-STATUS.md +3 -0
- package/test/run-iso-strict.mjs +47 -24
- package/the-art-of-eyeprolog.md +18 -18
- package/why-eyeprolog.md +5 -4
package/README.md
CHANGED
|
@@ -210,13 +210,13 @@ expansion/`phrase/2-3`; it also removes the EyeProlog `occurs_check` flag,
|
|
|
210
210
|
Normal mode is unchanged and continues to support modules, DCGs, quads,
|
|
211
211
|
libraries, proofs, cleanup-aware control, and the other documented extensions.
|
|
212
212
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
213
|
+
The Part 1 processor character set is an implementation-defined processor
|
|
214
|
+
choice, so strict mode does not replace it with a smaller repertoire. EyeProlog
|
|
215
|
+
uses Unicode scalar values as its PCS in both normal and strict profiles, with
|
|
216
|
+
the Unicode scalar value as the collating-sequence integer. ASCII keeps the
|
|
217
|
+
standard lexical classes; extended Unicode letters participate in unquoted name
|
|
218
|
+
syntax and other non-ASCII symbols are treated as extended graphic characters.
|
|
219
|
+
Surrogates and values above U+10FFFF remain representation errors.
|
|
220
220
|
|
|
221
221
|
Strict term I/O likewise keeps the standardized option boundary: `read_term/2-3`
|
|
222
222
|
and `write_term/2-3` accept the Part 1 plus Corrigendum 3 options, while the
|
package/package.json
CHANGED
package/src/iso-arithmetic.js
CHANGED
|
@@ -41,7 +41,12 @@ function evaluate(term, env, options = {}) {
|
|
|
41
41
|
// arguments before selecting an implementation-dependent evaluation order.
|
|
42
42
|
const operands = term.args.map((arg) => deref(arg, env));
|
|
43
43
|
if (operands.some((arg) => arg.type === VAR)) throw new PrologError('instantiation_error');
|
|
44
|
-
|
|
44
|
+
// Once the direct-variable precedence is satisfied, each operand is
|
|
45
|
+
// itself an expression. An atom such as foo therefore fails as the
|
|
46
|
+
// non-evaluable functor foo/0 (7.9.2(c)); it is not a numeric value that
|
|
47
|
+
// can subsequently trigger type_error(number,...). STC #69 corrects the
|
|
48
|
+
// misleading 9.1.7 example accordingly.
|
|
49
|
+
args = operands.map((arg) => evaluate(arg, env, options));
|
|
45
50
|
} else {
|
|
46
51
|
// Preserve the normal EyeProlog profile's established left-to-right
|
|
47
52
|
// evaluator and diagnostics; the stricter prescribed errors belong to
|
|
@@ -51,38 +56,6 @@ function evaluate(term, env, options = {}) {
|
|
|
51
56
|
return evaluateOperation(term, args, options);
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
function evaluatesAtomDirectly(term, options) {
|
|
55
|
-
return term.type === ATOM && (term.name === 'pi' || (term.name === 'e' && options.isoStrict !== true));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function directOperandType(term) {
|
|
59
|
-
const name = term.name;
|
|
60
|
-
const arity = term.arity;
|
|
61
|
-
if ((arity === 1 && name === '\\') ||
|
|
62
|
-
(arity === 2 && ['>>', '<<', '/\\', '\\/', 'xor'].includes(name))) return 'integer';
|
|
63
|
-
|
|
64
|
-
if ((arity === 1 && ['+', '-', 'abs', 'sign', 'float', 'truncate', 'round', 'ceiling', 'floor',
|
|
65
|
-
'float_integer_part', 'float_fractional_part', 'sin', 'cos', 'atan', 'asin', 'acos', 'tan',
|
|
66
|
-
'exp', 'log', 'sqrt'].includes(name)) ||
|
|
67
|
-
(arity === 2 && ['+', '-', '*', '/', '//', 'div', 'mod', 'rem', '**', '^', 'max', 'min', 'atan2'].includes(name))) {
|
|
68
|
-
return 'number';
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function evaluateOperand(parent, operand, env, options) {
|
|
74
|
-
// The arithmetic-functor error clauses use the offending operand as the
|
|
75
|
-
// culprit when an atomic operand is not numeric (e.g. +(foo,77),
|
|
76
|
-
// truncate(foo), and the bitwise families). A nested compound still goes
|
|
77
|
-
// through ordinary expression evaluation so an unknown nested F/N retains
|
|
78
|
-
// type_error(evaluable,F/N).
|
|
79
|
-
if (operand.type === ATOM && !evaluatesAtomDirectly(operand, options)) {
|
|
80
|
-
const expected = directOperandType(parent);
|
|
81
|
-
if (expected) throw new PrologError(`type_error(${expected})`, operand);
|
|
82
|
-
}
|
|
83
|
-
return evaluate(operand, env, options);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
59
|
function evaluateOperation(term, args, options = {}) {
|
|
87
60
|
const name = term.name;
|
|
88
61
|
const arity = term.arity;
|
package/src/iso-character.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
// ISO/IEC 13211-1 processor-character-set choices used by
|
|
1
|
+
// ISO/IEC 13211-1 processor-character-set choices used by EyeProlog.
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
3
|
+
// The PCS is implementation defined (6.5), so --iso-strict must not replace
|
|
4
|
+
// the processor's ordinary character repertoire with a smaller one. EyeProlog
|
|
5
|
+
// uses Unicode scalar values in both normal and strict profiles. Strict mode
|
|
6
|
+
// still rejects implementation-specific language features; it does not alter
|
|
7
|
+
// implementation-defined character-set choices.
|
|
7
8
|
|
|
8
9
|
export class CharacterRepresentationError extends Error {
|
|
9
10
|
constructor(formal = 'representation_error(character)') {
|
|
@@ -13,13 +14,9 @@ export class CharacterRepresentationError extends Error {
|
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
// Strict PCS: the 128 ASCII characters U+0000..U+007F. Printable ASCII
|
|
17
|
-
// carries the Part 1 lexical classes; the remaining C0 controls plus DEL are
|
|
18
|
-
// implementation-defined extended layout characters. This lets every ISO
|
|
19
|
-
// octal/hexadecimal character escape in the ASCII range denote a PCS member.
|
|
20
|
-
// The collating-sequence integer is the Unicode/ASCII code point.
|
|
21
17
|
export function isStrictIsoPcsCodePoint(code) {
|
|
22
|
-
return Number.isInteger(code) && code >= 0 && code <=
|
|
18
|
+
return Number.isInteger(code) && code >= 0 && code <= 0x10ffff &&
|
|
19
|
+
!(code >= 0xd800 && code <= 0xdfff);
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
export function isStrictIsoPcsCharacter(character) {
|
|
@@ -27,6 +24,7 @@ export function isStrictIsoPcsCharacter(character) {
|
|
|
27
24
|
return isStrictIsoPcsCodePoint(character.codePointAt(0));
|
|
28
25
|
}
|
|
29
26
|
|
|
27
|
+
// EyeProlog chooses the Unicode scalar value as the collating-sequence integer.
|
|
30
28
|
export function strictIsoCollatingInteger(character) {
|
|
31
29
|
return isStrictIsoPcsCharacter(character) ? character.codePointAt(0) : null;
|
|
32
30
|
}
|
package/src/iso.js
CHANGED
|
@@ -1352,9 +1352,10 @@ function* termTextCandidates(stream, solver) {
|
|
|
1352
1352
|
let quote = null, lineComment = false, blockComment = false;
|
|
1353
1353
|
for (let i = stream.position; i < source.length; i++) {
|
|
1354
1354
|
const ch = source[i], next = source[i + 1];
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1355
|
+
// The PCS is shared by normal and strict modes (issue #67). UTF-16
|
|
1356
|
+
// source indexing here must not reject one half of a supplementary scalar.
|
|
1357
|
+
// Character/code predicates validate scalar boundaries where a character
|
|
1358
|
+
// value is actually required.
|
|
1358
1359
|
// Text streams preserve invalid UTF-8 bytes as an impossible Unicode
|
|
1359
1360
|
// sentinel. read/1-2 and read_term/2-3 must surface the same character
|
|
1360
1361
|
// representation error as get_char/1-2 instead of misclassifying the
|
package/src/parser.js
CHANGED
|
@@ -35,12 +35,27 @@ const TOK = {
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
function isWhitespaceCode(code) {
|
|
38
|
-
// EyeProlog classifies ASCII C0 controls and DEL as layout characters. In
|
|
39
|
-
// strict mode these are the implementation-defined extended-layout members
|
|
40
|
-
// of the ASCII processor character set.
|
|
41
38
|
return (code >= 0 && code <= 32) || code === 127;
|
|
42
39
|
}
|
|
43
40
|
|
|
41
|
+
function isWhitespaceCharacter(character) {
|
|
42
|
+
if (!character) return false;
|
|
43
|
+
const code = character.charCodeAt(0);
|
|
44
|
+
return isWhitespaceCode(code) || /\p{White_Space}/u.test(character);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isUnicodeUpperCharacter(character) {
|
|
48
|
+
return Boolean(character) && /[\p{Lu}\p{Lt}]/u.test(character);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function isUnicodeLetterCharacter(character) {
|
|
52
|
+
return Boolean(character) && /\p{L}/u.test(character);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function isUnicodeNameContinueCharacter(character) {
|
|
56
|
+
return Boolean(character) && /[\p{L}\p{M}\p{Nd}]/u.test(character);
|
|
57
|
+
}
|
|
58
|
+
|
|
44
59
|
function isDigitCode(code) {
|
|
45
60
|
return code >= 48 && code <= 57;
|
|
46
61
|
}
|
|
@@ -53,13 +68,22 @@ function isNameContinueCode(code) {
|
|
|
53
68
|
return code === 95 || isAsciiLetterCode(code) || isDigitCode(code);
|
|
54
69
|
}
|
|
55
70
|
|
|
71
|
+
function isNameContinueCharacter(character) {
|
|
72
|
+
return Boolean(character) && (isNameContinueCode(character.charCodeAt(0)) ||
|
|
73
|
+
isUnicodeNameContinueCharacter(character));
|
|
74
|
+
}
|
|
56
75
|
|
|
57
|
-
function
|
|
58
|
-
|
|
76
|
+
function isVariableStartCharacter(character) {
|
|
77
|
+
if (!character) return false;
|
|
78
|
+
const code = character.charCodeAt(0);
|
|
79
|
+
return code === 95 || (code >= 65 && code <= 90) || isUnicodeUpperCharacter(character);
|
|
59
80
|
}
|
|
60
81
|
|
|
61
|
-
function
|
|
62
|
-
|
|
82
|
+
function isPlainAtomStartCharacter(character) {
|
|
83
|
+
if (!character) return false;
|
|
84
|
+
const code = character.charCodeAt(0);
|
|
85
|
+
return (code >= 97 && code <= 122) ||
|
|
86
|
+
(isUnicodeLetterCharacter(character) && !isUnicodeUpperCharacter(character));
|
|
63
87
|
}
|
|
64
88
|
|
|
65
89
|
const graphicAtomChars = '#$&*+-./<=>?@^~\\:';
|
|
@@ -161,6 +185,19 @@ function isGraphicAtomCode(code) {
|
|
|
161
185
|
return graphicAtomChars.includes(String.fromCharCode(code));
|
|
162
186
|
}
|
|
163
187
|
|
|
188
|
+
function isGraphicAtomCharacter(character) {
|
|
189
|
+
if (!character) return false;
|
|
190
|
+
const code = character.charCodeAt(0);
|
|
191
|
+
if (isGraphicAtomCode(code)) return true;
|
|
192
|
+
if (code <= 0x7f || isWhitespaceCharacter(character) ||
|
|
193
|
+
isUnicodeNameContinueCharacter(character)) return false;
|
|
194
|
+
// Non-ASCII symbols/punctuation are EyeProlog extended graphic characters.
|
|
195
|
+
// Surrogate code units are kept together by the maximal-token scan, so a
|
|
196
|
+
// supplementary scalar remains one atom spelling even though source offsets
|
|
197
|
+
// are UTF-16 based.
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
|
|
164
201
|
function defineParserOperator(state, priority, specifier, name) {
|
|
165
202
|
const strength = operatorStrength(priority);
|
|
166
203
|
if (['xfx', 'xfy', 'yfx'].includes(specifier)) {
|
|
@@ -237,11 +274,10 @@ class Parser {
|
|
|
237
274
|
return this.parserFlagState.charConversions.get(character) ?? character;
|
|
238
275
|
}
|
|
239
276
|
rawPeek(offset = 0) {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return ch;
|
|
277
|
+
// The processor character set is an implementation-defined processor
|
|
278
|
+
// choice, shared by normal and strict profiles. Do not narrow it merely
|
|
279
|
+
// because ISO conformance checking is enabled (issue #67).
|
|
280
|
+
return this.source[this.pos + offset] ?? '';
|
|
245
281
|
}
|
|
246
282
|
rawTake() {
|
|
247
283
|
const ch = this.rawPeek();
|
|
@@ -367,7 +403,7 @@ class Parser {
|
|
|
367
403
|
while (true) {
|
|
368
404
|
while (this.rawPeek()) {
|
|
369
405
|
const ch = this.peek();
|
|
370
|
-
if (!
|
|
406
|
+
if (!isWhitespaceCharacter(ch)) break;
|
|
371
407
|
this.take();
|
|
372
408
|
}
|
|
373
409
|
if (this.peek() === '%') {
|
|
@@ -461,7 +497,7 @@ class Parser {
|
|
|
461
497
|
if (ch === '.' && !this.terminatingFullStop()) {
|
|
462
498
|
const start = this.pos;
|
|
463
499
|
this.take();
|
|
464
|
-
while (
|
|
500
|
+
while (isGraphicAtomCharacter(this.peek()) &&
|
|
465
501
|
!this.terminatingFullStop()) this.take();
|
|
466
502
|
return { type: TOK.ATOM, text: this.convertedSlice(start, this.pos), line };
|
|
467
503
|
}
|
|
@@ -627,25 +663,25 @@ class Parser {
|
|
|
627
663
|
return { type: TOK.NUMBER, text, line };
|
|
628
664
|
}
|
|
629
665
|
|
|
630
|
-
if (
|
|
666
|
+
if (isVariableStartCharacter(ch)) {
|
|
631
667
|
const start = this.pos;
|
|
632
668
|
this.take();
|
|
633
|
-
while (
|
|
669
|
+
while (isNameContinueCharacter(this.peek())) this.take();
|
|
634
670
|
const text = this.convertedSlice(start, this.pos);
|
|
635
671
|
return { type: TOK.VAR, text, line };
|
|
636
672
|
}
|
|
637
673
|
|
|
638
|
-
if (
|
|
674
|
+
if (isPlainAtomStartCharacter(ch)) {
|
|
639
675
|
const start = this.pos;
|
|
640
676
|
this.take();
|
|
641
|
-
while (
|
|
677
|
+
while (isNameContinueCharacter(this.peek())) this.take();
|
|
642
678
|
return { type: TOK.ATOM, text: this.convertedSlice(start, this.pos), line };
|
|
643
679
|
}
|
|
644
680
|
|
|
645
|
-
if (
|
|
681
|
+
if (isGraphicAtomCharacter(ch)) {
|
|
646
682
|
const start = this.pos;
|
|
647
683
|
this.take();
|
|
648
|
-
while (
|
|
684
|
+
while (isGraphicAtomCharacter(this.peek()) &&
|
|
649
685
|
!this.terminatingFullStop()) this.take();
|
|
650
686
|
return { type: TOK.ATOM, text: this.convertedSlice(start, this.pos), line };
|
|
651
687
|
}
|
package/src/term.js
CHANGED
|
@@ -664,6 +664,19 @@ export function variantTerms(left, leftEnv, right, rightEnv, pairs = new Map(),
|
|
|
664
664
|
return true;
|
|
665
665
|
}
|
|
666
666
|
|
|
667
|
+
|
|
668
|
+
function compareCharacterText(left, right) {
|
|
669
|
+
const a = Array.from(left);
|
|
670
|
+
const b = Array.from(right);
|
|
671
|
+
const length = Math.min(a.length, b.length);
|
|
672
|
+
for (let i = 0; i < length; i++) {
|
|
673
|
+
const ac = a[i].codePointAt(0);
|
|
674
|
+
const bc = b[i].codePointAt(0);
|
|
675
|
+
if (ac !== bc) return ac < bc ? -1 : 1;
|
|
676
|
+
}
|
|
677
|
+
return a.length < b.length ? -1 : a.length > b.length ? 1 : 0;
|
|
678
|
+
}
|
|
679
|
+
|
|
667
680
|
export function compareTerms(left, right, variableRanks = null) {
|
|
668
681
|
// ISO 7.2.1 deliberately leaves the order of distinct variables
|
|
669
682
|
// implementation dependent. Do not attach a permanent ordinal to a
|
|
@@ -703,9 +716,9 @@ function compareTermsWithRanks(left, right, variableRanks) {
|
|
|
703
716
|
const rightOrder = variableRank(right.name, variableRanks);
|
|
704
717
|
return leftOrder < rightOrder ? -1 : 1;
|
|
705
718
|
}
|
|
706
|
-
if (left.type === ATOM || left.type === STRING) return left.name
|
|
719
|
+
if (left.type === ATOM || left.type === STRING) return compareCharacterText(left.name, right.name);
|
|
707
720
|
if (left.arity !== right.arity) return left.arity < right.arity ? -1 : 1;
|
|
708
|
-
if (left.name !== right.name) return left.name
|
|
721
|
+
if (left.name !== right.name) return compareCharacterText(left.name, right.name);
|
|
709
722
|
for (let i = 0; i < left.arity; i++) {
|
|
710
723
|
const cmp = compareTermsWithRanks(left.args[i], right.args[i], variableRanks);
|
|
711
724
|
if (cmp) return cmp;
|
|
@@ -30,18 +30,18 @@ error-ordering alternative to an individual executable assertion.
|
|
|
30
30
|
|
|
31
31
|
| Standard area | Status | Current evidence |
|
|
32
32
|
| --- | --- | --- |
|
|
33
|
-
| 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
|
|
33
|
+
| 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. |
|
|
34
34
|
| 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. |
|
|
35
35
|
| 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. |
|
|
36
36
|
| 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 now cover `current_predicate/1`, `clause/2`, `asserta/1`, `assertz/1`, `retract/1`, Corrigendum 2 `retractall/1`, and `abolish/1` errors plus empty-procedure lifetime. Runtime protection includes the solver-native conjunction control construct `','/2` and, following STC #56's accepted-direction action item, the source syntax functors `(:-)/1-2` for database modification/private access while leaving their call behavior distinct. The remaining clause-conversion shall-by-shall mapping is still open. |
|
|
37
37
|
| 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. |
|
|
38
38
|
| 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. |
|
|
39
|
-
| 7.9 — expression evaluation | audit | Arithmetic/evaluation/error suites, including Corrigenda. Strict mode now pins direct-variable precedence, arithmetic
|
|
39
|
+
| 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. |
|
|
40
40
|
| 7.10 — input/output concepts | audit | Stream, character/byte I/O, read/write options, operator-sensitive write-back, and Corrigendum 3 writer cases. The audit now also covers write-mode creation/truncation, append creation, repositioned overwrite, flushing, EOF actions, close/current-stream handling, strict stream-position terms, stream-property validation, stream-term requirements, text-vs-binary permission errors, and the prescribed `alias(A)` culprit for `open/4` alias collisions. The full option/mode cross-product is still being mapped. |
|
|
41
|
-
| 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. Strict mode excludes the EyeProlog `occurs_check` extension. |
|
|
41
|
+
| 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. |
|
|
42
42
|
| 7.12 — errors | audit | ISO `error(Error, Context)` envelope, type/domain/permission/representation/evaluation/syntax/resource families and focused error cases. Exact ISO 8.14.1-8.14.4 error precedence is covered for `read_term/3`, `write_term/3`, `op/3`, and `current_op/3`; the continuing audit has corrected additional 8.11-8.13 stream/character/byte errors (including the complete `alias(A)` culprit for `open/4` alias collisions), Corrigendum 2 `keysort/2` errors, atomic-conversion list-shape precedence, `arg/3`, `atom_concat/3`, `sub_atom/5`, `char_conversion/2`, runtime control-construct/database protection, arithmetic culprit/precedence reporting, and host-resource normalization for unbounded term/integer operations. A complete one-row-per-prescribed-error ordering map remains open. |
|
|
43
43
|
| 8.2-8.17 — built-in predicates | audit | Predicate-family coverage is mapped in ISO-MATRIX.md; Corrigendum 2 additions (`subsumes_term/2`, `term_variables/2`, `call/2..8`, `false/0`) are in the strict registry. The audit now includes corrected `keysort/2` variable/non-pair errors, stricter 8.11-8.13 stream and character/byte modes/errors, the 8.14 option/error-order subfamily, closed 8.17 flags, additional prescribed precedence for `arg/3`, `atom_concat/3`, `sub_atom/5`, number/atom list conversions, and `char_conversion/2`, plus finite-host resource handling for unbounded `functor/3` construction. The remaining mode/error matrix is not yet one-row-per-standard-row. |
|
|
44
|
-
| 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,
|
|
44
|
+
| 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. |
|
|
45
45
|
| Corrigendum 1 | covered | Double-quoted atom/operator-priority corrections have dedicated cases. |
|
|
46
46
|
| Corrigendum 2 | covered | Added predicates/functors, catch corrections, bar/operator and uninstantiation corrections have dedicated cases. |
|
|
47
47
|
| Corrigendum 3 | covered | Writer options, `variable_names/1`, canonical list output and negative-power corrections have dedicated cases. |
|
|
@@ -59,15 +59,16 @@ conformance claims:
|
|
|
59
59
|
when the `char_conversion` flag is `on`, leaves quoted characters unchanged,
|
|
60
60
|
and feeds the same mapping into execution-time term input.
|
|
61
61
|
|
|
62
|
-
A follow-on audit
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
A follow-on audit made the processor-character-set/collation choices explicit.
|
|
63
|
+
Issue #67 then corrected an over-strict interpretation: because PCS membership
|
|
64
|
+
and extended-character classification are implementation defined by Part 1,
|
|
65
|
+
`--iso-strict` must not replace EyeProlog's ordinary processor choice. Both
|
|
66
|
+
profiles now use Unicode scalar values as PCS members and collating integers;
|
|
67
|
+
Unicode letters/white-space/graphics receive documented extended lexical
|
|
68
|
+
classes, while surrogates and values above U+10FFFF remain representation
|
|
69
|
+
errors. Strict mode continues to reject implementation-specific facilities
|
|
70
|
+
without changing these implementation-defined character choices. The complete
|
|
71
|
+
WG17 syntax matrix remains a release gate.
|
|
71
72
|
|
|
72
73
|
|
|
73
74
|
The subsequent arity audit originally selected a finite `max_arity=65535`, but
|
|
@@ -28,12 +28,12 @@ Status values are:
|
|
|
28
28
|
| Clause | Decision completed by ISO 5.4 documentation | EyeProlog choice | Status / implementation evidence |
|
|
29
29
|
| --- | --- | --- | --- |
|
|
30
30
|
| 5.5.11 | Reserved atoms and the effect of instantiating a variable to one | EyeProlog reserves no Prolog atom under 5.5.11. Atoms with implementation-looking names remain ordinary terms unless a particular predicate interprets them. | **defined** — term representation and built-ins in `src/term.js`, `src/iso.js`. |
|
|
31
|
-
| 6.5 | Processor character set (PCS) |
|
|
32
|
-
| 6.5 | Classification of additional/extended PCS characters | Printable ASCII uses the lexical classes specified by Part 1.
|
|
33
|
-
| 6.6 | Collating-sequence integers |
|
|
34
|
-
| 6.6 | Collating values of control escapes and extended characters |
|
|
31
|
+
| 6.5 | Processor character set (PCS) | EyeProlog's PCS is the Unicode scalar repertoire U+0000..U+10FFFF excluding surrogates. This implementation-defined processor choice is shared by normal and `--iso-strict` modes; strict conformance does not narrow it. | **defined** — `src/iso-character.js`, parser/character-I/O validation, and strict-core/WG17 coverage. |
|
|
32
|
+
| 6.5 | Classification of additional/extended PCS characters | Printable ASCII uses the lexical classes specified by Part 1. C0 controls and DEL are extended layout characters. Non-ASCII Unicode letters extend alphanumeric name syntax; Unicode white-space is layout; remaining non-ASCII symbols/punctuation are extended graphic characters. | **defined** — `src/parser.js`, `src/syntax-scan.js`, `src/iso-character.js`. |
|
|
33
|
+
| 6.6 | Collating-sequence integers | Each PCS character's collating-sequence integer is its Unicode scalar value. Atom/functor comparison is lexicographic by those scalar integers, satisfying the required monotonic ASCII capital-letter, small-letter, and contiguous decimal-digit constraints while remaining well-defined for supplementary characters. | **defined** — `src/iso-character.js`, `src/term.js` (`compareTerms`), `src/iso.js` character-code predicates. |
|
|
34
|
+
| 6.6 | Collating values of control escapes and extended characters | Control escapes, octal/hexadecimal escapes, character-code constants, and extended Unicode characters all use the denoted Unicode scalar value as collating integer. | **defined** — `src/iso-character.js`, parser escape handling, `char_code/2`, `atom_codes/2`, and WG17 escape cases. |
|
|
35
35
|
| 7.1.2.2 | Mapping between a character code and bytes | Text file streams decode and encode UTF-8. Binary streams expose bytes 0..255 directly. | **defined** — `src/io.js`. |
|
|
36
|
-
| 7.1.4.1 | Set `C` of characters represented by one-char atoms | In
|
|
36
|
+
| 7.1.4.1 | Set `C` of characters represented by one-char atoms | In both profiles `C` is the Unicode scalar repertoire U+0000..U+10FFFF excluding surrogates. | **defined** — `src/iso-character.js`, `src/iso.js` character-code validation. |
|
|
37
37
|
| 7.4.2.4 | Whether `op/3` directives affect other Prolog texts or execution | An `op/3` directive changes parsing of subsequent text loaded into the same `Program`; the resulting operator table is also used by execution-time term I/O. Separately created `Program` objects are independent. | **defined** — `src/parser.js`, `src/program.js`, `src/iso.js`. |
|
|
38
38
|
| 7.4.2.5 | Whether directive-created `Convc` affects other text/execution | Yes. A `char_conversion/2` directive updates preparation-time conversion for later unquoted source characters and the recorded mapping initializes execution-time term input. Quoted characters are not converted; `char_conversion=off` disables following preparation-time conversion. | **defined** — `src/parser.js`, `src/program.js`, `src/solver.js`; strict-core regression coverage. |
|
|
39
39
|
| 7.4.2.6 | Order of `initialization/1` goals | Initialization goals run once per prepared `Program`, in source/inclusion order, before requested goals; each must obtain a first solution. Reusing the same prepared program in another solver does not execute its initialization goals again. | **defined** — `Program.initializations`, preparation state, `Solver.runInitializations()`. |
|
|
@@ -68,7 +68,7 @@ Status values are:
|
|
|
68
68
|
| 7.11.2.3 | Default `max_arity` | `unbounded`: EyeProlog imposes no fixed semantic ceiling on compound-term arity. Practical host allocation exhaustion is a resource condition. This flag is distinct from any potential implementation-specific procedure-arity limit; EyeProlog currently declares no separate finite procedure limit. | **defined** — `src/iso-limits.js`, `src/solver.js`, `src/parser.js`, `src/iso.js`; issue #66 regression coverage. |
|
|
69
69
|
| 7.11.2.5 | Default `double_quotes` | `chars`. | **defined** — `src/solver.js`, parser flag state. |
|
|
70
70
|
| 7.12.1 | Second argument of `error/2` | The default context term is the atom `eyeprolog`. A few implementation-specific diagnostics may deliberately supply a more specific context term. | **defined** — `formalErrorTerm()` in `src/iso.js`. |
|
|
71
|
-
| 7.12.2(f) | Implementation-defined representation limits |
|
|
71
|
+
| 7.12.2(f) | Implementation-defined representation limits | Character and character-code operations are limited to Unicode scalar values; surrogates and values above U+10FFFF are representation errors. Arity/integer values are modeled as unbounded but may hit host/resource limits. Float input overflow uses the implementation-specific `max_float`/`min_float` representation names documented by the STC-oriented tests. | **defined** — parser/ISO numeric and character guards. |
|
|
72
72
|
| 8.17.1 | Implementation-defined flag value ranges | Strict mode exposes only Part 1 core flags and their standard value sets. Normal mode additionally exposes EyeProlog's `occurs_check` flag. With `bounded=false`, `max_integer` and `min_integer` have no current or selectable value and their `current_prolog_flag/2` queries fail. Valid alternative values of fixed standard flags are distinguished from invalid values so `set_prolog_flag/2` reports permission versus domain errors as prescribed. | **defined** — strict registry/flag filtering in `src/solver.js`; strict flag tests. |
|
|
73
73
|
| 8.17.3 | Other effects of `halt/0` | Terminates EyeProlog execution and returns host/process status `0`; it produces no Prolog solution. | **defined** — `HaltSignal`, `haltBuiltin()`, CLI/runner handling. |
|
|
74
74
|
| 8.17.4 | Meaning/effects of `halt(Status)` | Integer `Status` is converted to the host process/runner halt code; it produces no Prolog solution. | **defined** — `haltBuiltin()`, `src/execute.js`, `src/cli.js`. |
|
|
@@ -110,7 +110,7 @@ families; `--iso-strict` is intended to remove their Part 1 interpretation.
|
|
|
110
110
|
|
|
111
111
|
| Part 1 extension hook | EyeProlog normal-profile feature | Strict-core disposition |
|
|
112
112
|
| --- | --- | --- |
|
|
113
|
-
| 5.5.1 Syntax | Part 2 modules, Part 3 grammar-rule expansion, embedded quad syntax
|
|
113
|
+
| 5.5.1 Syntax | Part 2 modules, Part 3 grammar-rule expansion, and embedded quad syntax | Module directives are rejected; grammar rules remain ordinary `-->/2` terms rather than being expanded; quad syntax is rejected. Unicode PCS membership/classification is implementation defined and therefore shared with normal mode rather than treated as an extension. |
|
|
114
114
|
| 5.5.2 Predefined operators | Part 3 `|` and EyeProlog's labelable infix `(?-)/2`; CLP(Z) operators when that library is imported | Only the Part 1 operator table is predefined; a conforming `op/3` may still add permitted operators. |
|
|
115
115
|
| 5.5.3 Character-conversion mapping | No non-identity initial `Convc` extension | Identity initial mapping. |
|
|
116
116
|
| 5.5.4 Types | No additional runtime Prolog term type is exposed by the core solver | Only variable, integer, float, atom, and compound term ordering participates in strict mode. |
|
|
@@ -8,7 +8,7 @@ compliance audit and the remaining work before a full conformance claim.
|
|
|
8
8
|
|
|
9
9
|
| Standard area | Implementation | Representative executable coverage |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
-
| Clause 6 lexical and term syntax | tokenizer, operator parser, lists, curly terms, quotes, numeric syntax, comments,
|
|
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
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, Corrigendum 2 `keysort/2` variable/non-pair errors, and strict `arg/3`, `functor/3` / `=../2` error-order plus unbounded-arity/resource checks |
|
|
@@ -29,10 +29,10 @@ identify standards-derived behavior; other directories cover EyeProlog host
|
|
|
29
29
|
contracts and extensions. EyeProlog-only execution features such as automatic
|
|
30
30
|
tabling and `tnot/1` well-founded negation are outside the Part 1 strict-core
|
|
31
31
|
claim. Their focused semantic coverage lives primarily in regression tests;
|
|
32
|
-
`tnot/1` is absent from the strict ISO registry. The
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
`tnot/1` is absent from the strict ISO registry. The processor character set is documented as the Unicode scalar repertoire with
|
|
33
|
+
scalar-value collation in both normal and strict profiles; `--iso-strict`
|
|
34
|
+
therefore changes only implementation-specific language facilities, not this
|
|
35
|
+
implementation-defined processor choice.
|
|
36
36
|
|
|
37
37
|
All conformance files live under topic directories such as `arithmetic/`, `lists/`, `syntax/`, or `variables/`; new top-level numbered files should not be added. The report uses those directories as coverage categories.
|
|
38
38
|
|
|
@@ -35,6 +35,9 @@ regressions.
|
|
|
35
35
|
| [#56](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#56) | protect `(:-)/1` and `(:-)/2` from database modification | **Found a gap during the #65 audit.** Strict database operations now treat both functors as static/private for `assert*`, `retract*`, `abolish/1`, declarations, and `clause/2`, while ordinary calls still follow the separate procedure-existence behavior described by the STC item. |
|
|
36
36
|
| [#58](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#58) | `set_prolog_flag/2` instantiation error | Existing strict/error coverage requires an instantiation error when a required flag value is a variable. |
|
|
37
37
|
| [#67](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#67) | `bagof/3` answer-order example | `stc/bagof_answer_order` verifies the proposed clarifying example produces `[2,1]`. |
|
|
38
|
+
| [#68](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#68) | division examples | Existing arithmetic coverage evaluates signed integer `/` through the floating operation; no implementation-defined signed-division result is used. |
|
|
39
|
+
| [#69](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#69) | arithmetic example culprit | **Found a #65 gap.** Strict expression evaluation now applies 7.9.2(c) to an atomic subexpression such as `foo`: it reports `type_error(evaluable,foo/0)` rather than the misleading `type_error(number,foo)` shown by the old 9.1.7 example. |
|
|
40
|
+
| [#70](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#70) | optional `max_procedure_arity` | Reviewed after issue #66 corrected the earlier #71 pointer. EyeProlog has no declared procedure-arity limit smaller than its `max_arity=unbounded` term model, so the implementation-defined optional flag is intentionally absent. |
|
|
38
41
|
| [#73](https://www.complang.tuwien.ac.at/ulrich/iso-prolog/stc#73) | float-reading limits discussed from issue #54 | Positive/negative literal and `number_chars/2` overflow are kept as explicit draft cases; underflow is tested separately. See the note below. |
|
|
39
42
|
|
|
40
43
|
## Float-reading note for #73
|
package/test/run-iso-strict.mjs
CHANGED
|
@@ -99,6 +99,14 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
99
99
|
1, 'large nonexistent predicate indicator');
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
+
reporter.test('does not invent max_procedure_arity without a separate procedure ceiling', () => {
|
|
103
|
+
// STC #70 makes max_procedure_arity implementation defined and needed
|
|
104
|
+
// only when a processor has a smaller procedure-arity ceiling. EyeProlog
|
|
105
|
+
// has no such separate declared ceiling, so the optional flag is absent.
|
|
106
|
+
equal(capture(() => run('', { isoStrict: true, goal: 'current_prolog_flag(max_procedure_arity,_)' })).formal,
|
|
107
|
+
'domain_error(prolog_flag)', 'STC #70 optional flag absent');
|
|
108
|
+
});
|
|
109
|
+
|
|
102
110
|
reporter.test('preparation-time char_conversion affects later unquoted source only', () => {
|
|
103
111
|
const program = Program.parse(
|
|
104
112
|
":- char_conversion(x,y).\np(x).\nquoted('x').\n:- set_prolog_flag(char_conversion,off).\nraw(x).\n",
|
|
@@ -110,18 +118,19 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
110
118
|
});
|
|
111
119
|
|
|
112
120
|
|
|
113
|
-
reporter.test('uses
|
|
121
|
+
reporter.test('uses the implementation-defined Unicode scalar PCS and collation', () => {
|
|
114
122
|
const program = Program.parse('', { isoStrict: true });
|
|
115
123
|
const solver = new Solver(program, { isoStrict: true });
|
|
116
124
|
const answers = (text) => [...solver.solve([parseGoalText(text, { isoStrict: true })], new Env(), 0)].length;
|
|
117
125
|
equal(answers("char_code('\\0\\',0)"), 1, 'NUL collating integer');
|
|
118
126
|
equal(answers("char_code('A',65)"), 1, 'A collating integer');
|
|
119
|
-
equal(answers("char_code('
|
|
127
|
+
equal(answers("char_code('ä',228)"), 1, 'extended Latin character');
|
|
128
|
+
equal(answers("char_code('😀',128512)"), 1, 'supplementary Unicode scalar');
|
|
120
129
|
equal(answers("'\\0\\' @< 'A'"), 1, 'control before capital');
|
|
121
130
|
equal(answers("'A' @< 'a'"), 1, 'capital before small letter');
|
|
131
|
+
equal(answers("'\\xe000\\' @< '\\x10000\\'"), 1, 'atom order follows scalar collating integers');
|
|
122
132
|
});
|
|
123
133
|
|
|
124
|
-
|
|
125
134
|
reporter.test('follows the Part 1 standard term-type and atom ordering', () => {
|
|
126
135
|
const program = Program.parse('', { isoStrict: true });
|
|
127
136
|
const solver = new Solver(program, { isoStrict: true });
|
|
@@ -134,30 +143,38 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
134
143
|
equal(answers("'A' @< 'B'"), 1, 'atom collation');
|
|
135
144
|
});
|
|
136
145
|
|
|
137
|
-
reporter.test('
|
|
138
|
-
const
|
|
139
|
-
equal(
|
|
146
|
+
reporter.test('does not narrow implementation-defined character choices in strict mode', () => {
|
|
147
|
+
const program = Program.parse("p('é').\nä.\n", { isoStrict: true });
|
|
148
|
+
equal(Boolean(program.findGroup('p', 1)), true, 'quoted extended character in source');
|
|
149
|
+
equal(Boolean(program.findGroup('ä', 0)), true, 'extended small-letter atom in source');
|
|
140
150
|
|
|
141
|
-
const
|
|
151
|
+
const readResult = run('', {
|
|
142
152
|
isoStrict: true,
|
|
143
|
-
goal:
|
|
153
|
+
goal: "read('é')",
|
|
144
154
|
ioOptions: { input: "'é'." },
|
|
145
|
-
})
|
|
146
|
-
equal(
|
|
155
|
+
});
|
|
156
|
+
equal(readResult.stats.completed_goal_lists, 1, 'extended character through strict text input');
|
|
157
|
+
|
|
158
|
+
const written = run('', { isoStrict: true, goal: 'writeq("ä")' });
|
|
159
|
+
includes(written.stdout, 'ä', 'issue #67 writeq example');
|
|
147
160
|
});
|
|
148
161
|
|
|
149
|
-
reporter.test('restricts
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
162
|
+
reporter.test('restricts character codes only to the Unicode scalar PCS boundary', () => {
|
|
163
|
+
equal(run('', { isoStrict: true, goal: 'char_code(_,128)' }).stats.completed_goal_lists, 1,
|
|
164
|
+
'code 128 is a PCS member');
|
|
165
|
+
equal(capture(() => run('', { isoStrict: true, goal: 'char_code(_,55296)' })).formal,
|
|
166
|
+
'representation_error(character_code)', 'surrogate is not a scalar');
|
|
167
|
+
equal(capture(() => run('', { isoStrict: true, goal: 'atom_codes(_, [1114112])' })).formal,
|
|
168
|
+
'representation_error(character_code)', 'above Unicode scalar range');
|
|
169
|
+
equal(capture(() => run('', { isoStrict: true, goal: 'put_code(1114112)' })).formal,
|
|
170
|
+
'representation_error(character_code)', 'put_code/1 above scalar range');
|
|
156
171
|
});
|
|
157
172
|
|
|
158
|
-
reporter.test('
|
|
159
|
-
const
|
|
160
|
-
|
|
173
|
+
reporter.test('uses the same processor character repertoire in normal and strict profiles', () => {
|
|
174
|
+
const normal = run('', { goal: "char_code('é',233)" });
|
|
175
|
+
const strict = run('', { isoStrict: true, goal: "char_code('é',233)" });
|
|
176
|
+
equal(normal.stats.completed_goal_lists, 1, 'normal Unicode char_code/2');
|
|
177
|
+
equal(strict.stats.completed_goal_lists, 1, 'strict Unicode char_code/2');
|
|
161
178
|
});
|
|
162
179
|
|
|
163
180
|
reporter.test('keeps the strict write-option surface to Part 1 plus Corrigendum 3', () => {
|
|
@@ -282,11 +299,11 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
282
299
|
|
|
283
300
|
reporter.test('follows Part 1 arithmetic type and exceptional errors', () => {
|
|
284
301
|
const cases = [
|
|
285
|
-
["X is '+'(foo,77)", 'type_error(
|
|
286
|
-
['X is mod(foo,77)', 'type_error(
|
|
302
|
+
["X is '+'(foo,77)", 'type_error(evaluable)', 'STC #69 simple arithmetic atom is foo/0'],
|
|
303
|
+
['X is mod(foo,77)', 'type_error(evaluable)', 'integer arithmetic atom is non-evaluable'],
|
|
287
304
|
['X is mod(7.5,2)', 'type_error(integer)', 'integer arithmetic numeric type'],
|
|
288
|
-
['X is truncate(foo)', 'type_error(
|
|
289
|
-
['X is sin(foo)', 'type_error(
|
|
305
|
+
['X is truncate(foo)', 'type_error(evaluable)', 'rounding atom is non-evaluable'],
|
|
306
|
+
['X is sin(foo)', 'type_error(evaluable)', 'transcendental atom is non-evaluable'],
|
|
290
307
|
['X is foo+Y', 'instantiation_error', 'direct variable before another operand error'],
|
|
291
308
|
['X is floor(7)', 'type_error(float)', 'floor integer operand'],
|
|
292
309
|
['X is truncate(7)', 'type_error(float)', 'truncate integer operand'],
|
|
@@ -300,6 +317,12 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
300
317
|
}
|
|
301
318
|
});
|
|
302
319
|
|
|
320
|
+
reporter.test('uses the STC #69 evaluable culprit for atomic arithmetic expressions', () => {
|
|
321
|
+
const error = capture(() => run('', { isoStrict: true, goal: "X is '+'(foo,77)" }));
|
|
322
|
+
equal(error.formal, 'type_error(evaluable)', 'formal error');
|
|
323
|
+
includes(error.message, '/(foo, 0)', 'foo/0 culprit');
|
|
324
|
+
});
|
|
325
|
+
|
|
303
326
|
reporter.test('applies integer-to-float conversion before floating evaluable functors', () => {
|
|
304
327
|
const huge = `1${'0'.repeat(400)}`;
|
|
305
328
|
for (const functor of ['float', 'sin', 'cos', 'atan', 'asin', 'acos', 'tan', 'exp', 'log', 'sqrt']) {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -5119,12 +5119,11 @@ this part makes control, reflection, state, operators, and streams explicit.
|
|
|
5119
5119
|
For Part 1 portability work, EyeProlog also provides a strict core mode:
|
|
5120
5120
|
`--iso-strict` on the CLI or `isoStrict: true` in the JavaScript API restricts
|
|
5121
5121
|
the language/runtime surface to ISO/IEC 13211-1:1995 plus Technical Corrigenda
|
|
5122
|
-
1–3.
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
extension. Isolated mode and error cases live in `test/conformance/cases/iso/`.
|
|
5122
|
+
1–3. The processor character set is an implementation-defined choice shared by
|
|
5123
|
+
normal and strict profiles: EyeProlog uses Unicode scalar values U+0000..U+10FFFF
|
|
5124
|
+
excluding surrogates, with the scalar value as the collating-sequence integer.
|
|
5125
|
+
Strict mode restricts implementation-specific language facilities, but it does
|
|
5126
|
+
not narrow this processor-defined character repertoire. Isolated mode and error cases live in `test/conformance/cases/iso/`.
|
|
5128
5127
|
The examples here compose those operations into programs worth changing and
|
|
5129
5128
|
rerunning.
|
|
5130
5129
|
|
|
@@ -5510,13 +5509,14 @@ lowercase ASCII letter. Variables begin with uppercase or underscore. The bare
|
|
|
5510
5509
|
ISO double-quoted-list notation. Integers, decimals, scientific notation,
|
|
5511
5510
|
binary/octal/hexadecimal integers, and character-code constants are accepted.
|
|
5512
5511
|
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5512
|
+
The processor character set is shared by normal and `--iso-strict` modes because
|
|
5513
|
+
Part 1 makes it implementation defined rather than an extension boundary.
|
|
5514
|
+
EyeProlog's PCS is the Unicode scalar repertoire. Printable ASCII keeps the Part
|
|
5515
|
+
1 lexical classes; Unicode letters extend alphanumeric name syntax, Unicode
|
|
5516
|
+
white-space characters are layout, and remaining non-ASCII symbols/punctuation
|
|
5517
|
+
are extended graphic characters. Character-code and collation values are the
|
|
5518
|
+
corresponding Unicode scalar integers. Quoting remains available for any atom
|
|
5519
|
+
spelling that should not depend on an extended lexical class:
|
|
5520
5520
|
|
|
5521
5521
|
```eyeprolog
|
|
5522
5522
|
|
|
@@ -6049,8 +6049,8 @@ quoted_atom("ab"). % quoted_atom(ab)
|
|
|
6049
6049
|
| `atom_length(+Atom,?Length)` | Counts Unicode code points, not UTF-16 code units. A supplied length must be a nonnegative integer. |
|
|
6050
6050
|
| `atom_concat(?Prefix,?Suffix,?Whole)` | Concatenates two atoms, removes a supplied prefix or suffix, or enumerates every split when only `Whole` is bound. At least `Whole`, or both parts, must determine the operation. |
|
|
6051
6051
|
| `sub_atom(+Atom,?Before,?Length,?After,?SubAtom)` | Enumerates substrings and their Unicode-code-point offsets. Supplied counts must be nonnegative integers. |
|
|
6052
|
-
| `atom_chars(?Atom,?Chars)`, `atom_codes(?Atom,?Codes)` | Convert between an atom and a proper list of one-character atoms or character codes.
|
|
6053
|
-
| `char_code(?Character,?Code)` | Converts one character atom and its collating/code value.
|
|
6052
|
+
| `atom_chars(?Atom,?Chars)`, `atom_codes(?Atom,?Codes)` | Convert between an atom and a proper list of one-character atoms or character codes. Both profiles use EyeProlog's Unicode scalar PCS/codes; surrogates and values above U+10FFFF are rejected. At least one side must be instantiated. |
|
|
6053
|
+
| `char_code(?Character,?Code)` | Converts one character atom and its collating/code value. Both profiles accept Unicode scalar codes and reject surrogates/out-of-range values. |
|
|
6054
6054
|
| `number_chars(?Number,?Chars)`, `number_codes(?Number,?Codes)` | Convert finite numbers to canonical text or parse a proper character/code list using ISO number and negative-number syntax, including radix integers, character-code constants, and leading layout. The input is not parsed as a general term: grouping such as `(0)` is a syntax error. At least one side must be instantiated; malformed numeric input raises *syntax_error(number)*. |
|
|
6055
6055
|
|
|
6056
6056
|
Conversions accept partial output lists when the atomic input is known, but
|
|
@@ -6091,12 +6091,12 @@ input or output.
|
|
|
6091
6091
|
| `at_end_of_stream`, `at_end_of_stream(+Stream)` | Succeeds when the current or selected input position is at or beyond its content. |
|
|
6092
6092
|
| `get_char(?Character)`, `get_char(+Stream,?Character)` | Reads one text character; end of input is `end_of_file`. |
|
|
6093
6093
|
| `peek_char(?Character)`, `peek_char(+Stream,?Character)` | Observes the next text character without advancing. |
|
|
6094
|
-
| `get_code(?Code)`, `get_code(+Stream,?Code)` | Reads a character code; end of input is `-1`.
|
|
6095
|
-
| `peek_code(?Code)`, `peek_code(+Stream,?Code)` | Observes the next character code without advancing
|
|
6094
|
+
| `get_code(?Code)`, `get_code(+Stream,?Code)` | Reads a character code; end of input is `-1`. Both profiles return codes from EyeProlog's Unicode scalar PCS. |
|
|
6095
|
+
| `peek_code(?Code)`, `peek_code(+Stream,?Code)` | Observes the next Unicode scalar character code without advancing. |
|
|
6096
6096
|
| `get_byte(?Byte)`, `get_byte(+Stream,?Byte)` | Reads one unit from a binary stream; end of input is `-1`. |
|
|
6097
6097
|
| `peek_byte(?Byte)`, `peek_byte(+Stream,?Byte)` | Observes the next binary unit without advancing. |
|
|
6098
6098
|
| `put_char(+Character)`, `put_char(+Stream,+Character)` | Writes one character atom to a text stream. |
|
|
6099
|
-
| `put_code(+Code)`, `put_code(+Stream,+Code)` | Writes one character code to a text stream.
|
|
6099
|
+
| `put_code(+Code)`, `put_code(+Stream,+Code)` | Writes one character code to a text stream. Both profiles accept Unicode scalar codes. |
|
|
6100
6100
|
| `put_byte(+Byte)`, `put_byte(+Stream,+Byte)` | Writes an integer in `0..255` to a binary stream. |
|
|
6101
6101
|
| `nl`, `nl(+Stream)` | Writes a newline to a text stream. |
|
|
6102
6102
|
|
package/why-eyeprolog.md
CHANGED
|
@@ -19,10 +19,11 @@ syntax.
|
|
|
19
19
|
|
|
20
20
|
EyeProlog targets the Part 1 core together with Technical Corrigenda 1, 2,
|
|
21
21
|
and 3, and provides documented module and definite-clause-grammar compatibility
|
|
22
|
-
profiles for normal-mode programs.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
profiles for normal-mode programs. The processor character model is explicitly
|
|
23
|
+
implementation defined: EyeProlog uses Unicode scalar values as the PCS and as
|
|
24
|
+
collating-sequence integers in both normal and strict profiles. Strict mode
|
|
25
|
+
therefore rejects implementation-specific language extensions without changing
|
|
26
|
+
that processor choice. Its executable conformance matrix and tests
|
|
26
27
|
document the supported behavior, including an executable trace of the vendored
|
|
27
28
|
active WG17 syntax cases. This is extensive implementation evidence, not a
|
|
28
29
|
claim that every Part 1, Part 2, or Part 3 normative requirement has already
|