eyeprolog 1.3.44 → 1.3.46
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 +6 -1
- package/package.json +1 -1
- package/src/io.js +33 -10
- package/src/iso-arithmetic.js +12 -10
- package/src/iso-limits.js +8 -0
- package/src/iso.js +259 -81
- package/src/parser.js +2 -0
- package/src/program.js +130 -19
- package/src/solver.js +6 -1
- package/test/conformance/ISO-COMPLIANCE.md +36 -7
- package/test/conformance/ISO-IMPLEMENTATION-DEFINED.md +2 -2
- package/test/conformance/ISO-MATRIX.md +4 -4
- package/test/conformance/README.md +3 -2
- package/test/conformance/expected/iso/exceptions_and_flags.pl +1 -1
- package/test/conformance/expected-errors/iso/get_byte_text_stream.txt +1 -1
- package/test/conformance/expected-errors/iso/logtalk_functor_compound_name.txt +1 -1
- package/test/run-iso-strict.mjs +97 -3
- package/the-art-of-eyeprolog.md +8 -2
package/README.md
CHANGED
|
@@ -223,7 +223,12 @@ and `write_term/2-3` accept the Part 1 plus Corrigendum 3 options, while the
|
|
|
223
223
|
normal-profile `write_term(...,[double_quotes(...)])` option remains an
|
|
224
224
|
EyeProlog extension. The strict gate also checks the prescribed ISO error
|
|
225
225
|
precedence for `read_term/3`, `write_term/3`, `op/3`, and `current_op/3`, and
|
|
226
|
-
the complete Part 1 flag defaults/value domains/changeability rules.
|
|
226
|
+
the complete Part 1 flag defaults/value domains/changeability rules. The
|
|
227
|
+
ongoing issue #65 audit additionally tightens Prolog-text declaration ordering,
|
|
228
|
+
initialization lifetime, stream/open/close behavior, character/byte stream
|
|
229
|
+
errors, `keysort/2` error cases, and strict arithmetic-extension boundaries.
|
|
230
|
+
Those additions improve the Part 1 surface without turning the remaining audit
|
|
231
|
+
rows into a blanket conformance claim.
|
|
227
232
|
|
|
228
233
|
The auditable processor-requirement checklist lives in
|
|
229
234
|
[`test/conformance/ISO-COMPLIANCE.md`](test/conformance/ISO-COMPLIANCE.md).
|
package/package.json
CHANGED
package/src/io.js
CHANGED
|
@@ -88,8 +88,13 @@ export class StreamManager {
|
|
|
88
88
|
const raw = fs.readFileSync(path);
|
|
89
89
|
if (type === 'binary') content = raw;
|
|
90
90
|
else { content = decodeUtf8ForTextStream(raw); strictUtf8 = true; }
|
|
91
|
-
} else if (mode === '
|
|
92
|
-
|
|
91
|
+
} else if (mode === 'write') {
|
|
92
|
+
// ISO 7.10.1.1: opening an existing sink in write mode empties it,
|
|
93
|
+
// while a missing sink is created at open time (not deferred to close).
|
|
94
|
+
fs.writeFileSync(path, type === 'binary' ? BufferCtor.from([]) : '');
|
|
95
|
+
} else if (mode === 'append') {
|
|
96
|
+
if (fs.existsSync(path)) content = fs.readFileSync(path, type === 'binary' ? null : 'utf8');
|
|
97
|
+
else fs.writeFileSync(path, type === 'binary' ? BufferCtor.from([]) : '');
|
|
93
98
|
}
|
|
94
99
|
if (BufferCtor?.isBuffer(content)) content = [...content];
|
|
95
100
|
return this.add({
|
|
@@ -100,13 +105,18 @@ export class StreamManager {
|
|
|
100
105
|
pastEnd: false,
|
|
101
106
|
});
|
|
102
107
|
}
|
|
103
|
-
|
|
104
|
-
if (!stream.standard
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
flush(stream) {
|
|
109
|
+
if (!stream || stream.standard || stream.mode === 'read') return;
|
|
110
|
+
fs.writeFileSync(stream.path, stream.type === 'binary' ? BufferCtor.from(stream.content) : stream.content);
|
|
111
|
+
}
|
|
112
|
+
discard(stream) {
|
|
107
113
|
if (stream.alias) this.aliases.delete(stream.alias);
|
|
108
114
|
this.streams.delete(stream.id);
|
|
109
115
|
}
|
|
116
|
+
close(stream) {
|
|
117
|
+
this.flush(stream);
|
|
118
|
+
this.discard(stream);
|
|
119
|
+
}
|
|
110
120
|
readUnit(stream, peek = false) {
|
|
111
121
|
if (stream.position >= stream.content.length) return null;
|
|
112
122
|
if (stream.type === 'binary') {
|
|
@@ -126,9 +136,22 @@ export class StreamManager {
|
|
|
126
136
|
return value;
|
|
127
137
|
}
|
|
128
138
|
writeUnit(stream, value) {
|
|
129
|
-
if (stream.standard && stream.write)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
if (stream.standard && stream.write) {
|
|
140
|
+
stream.write(String(value));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// 7.10.2.8: output after repositioning overwrites the existing sink
|
|
144
|
+
// contents at the selected stream position rather than always appending.
|
|
145
|
+
if (stream.type === 'binary') {
|
|
146
|
+
if (stream.position < stream.content.length) stream.content[stream.position] = value;
|
|
147
|
+
else stream.content.push(value);
|
|
148
|
+
stream.position++;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const text = String(value);
|
|
152
|
+
const content = String(stream.content);
|
|
153
|
+
const end = Math.min(content.length, stream.position + text.length);
|
|
154
|
+
stream.content = `${content.slice(0, stream.position)}${text}${content.slice(end)}`;
|
|
155
|
+
stream.position += text.length;
|
|
133
156
|
}
|
|
134
157
|
}
|
package/src/iso-arithmetic.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from './term.js';
|
|
6
6
|
import { PrologError } from './errors.js';
|
|
7
7
|
|
|
8
|
-
function evaluate(term, env) {
|
|
8
|
+
function evaluate(term, env, options = {}) {
|
|
9
9
|
term = deref(term, env);
|
|
10
10
|
if (term.type === VAR) throw new PrologError('instantiation_error');
|
|
11
11
|
if (term.type === NUMBER) {
|
|
@@ -16,10 +16,11 @@ function evaluate(term, env) {
|
|
|
16
16
|
}
|
|
17
17
|
if (term.type === ATOM) {
|
|
18
18
|
if (term.name === 'pi') return { integer: false, value: Math.PI };
|
|
19
|
-
if (term.name === 'e') return { integer: false, value: Math.E };
|
|
19
|
+
if (term.name === 'e' && options.isoStrict !== true) return { integer: false, value: Math.E };
|
|
20
|
+
throw new PrologError('type_error(evaluable)', compound('/', [atom(term.name), numberTerm(0)]));
|
|
20
21
|
}
|
|
21
22
|
if (term.type !== COMPOUND) throw new PrologError('type_error(evaluable)', term);
|
|
22
|
-
const args = term.args.map((arg) => evaluate(arg, env));
|
|
23
|
+
const args = term.args.map((arg) => evaluate(arg, env, options));
|
|
23
24
|
return evaluateOperation(term, args);
|
|
24
25
|
}
|
|
25
26
|
function evaluateOperation(term, args) {
|
|
@@ -120,8 +121,8 @@ export function arithmeticValueTerm(value) {
|
|
|
120
121
|
function numericTerm(value) {
|
|
121
122
|
return arithmeticValueTerm(value);
|
|
122
123
|
}
|
|
123
|
-
export function evaluateArithmetic(term, env) {
|
|
124
|
-
return evaluate(term, env);
|
|
124
|
+
export function evaluateArithmetic(term, env, options = {}) {
|
|
125
|
+
return evaluate(term, env, options);
|
|
125
126
|
}
|
|
126
127
|
function compareIntegerToFloat(integerValue, floatValue) {
|
|
127
128
|
if (!Number.isFinite(floatValue)) throw new PrologError('evaluation_error(float_overflow)');
|
|
@@ -151,15 +152,16 @@ export function compareArithmeticValues(left, right) {
|
|
|
151
152
|
if (right.integer) return -compareIntegerToFloat(b, a);
|
|
152
153
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
153
154
|
}
|
|
154
|
-
export function* isBuiltin({ goal, env }) {
|
|
155
|
-
const result = arithmeticValueTerm(evaluateArithmetic(goal.args[1], env));
|
|
155
|
+
export function* isBuiltin({ solver, goal, env }) {
|
|
156
|
+
const result = arithmeticValueTerm(evaluateArithmetic(goal.args[1], env, { isoStrict: solver?.isoStrict === true }));
|
|
156
157
|
const next = env.clone();
|
|
157
158
|
if (unify(goal.args[0], result, next)) yield next;
|
|
158
159
|
}
|
|
159
160
|
export function arithmeticComparison(test) {
|
|
160
|
-
return function* ({ goal, env }) {
|
|
161
|
-
const
|
|
162
|
-
const
|
|
161
|
+
return function* ({ solver, goal, env }) {
|
|
162
|
+
const options = { isoStrict: solver?.isoStrict === true };
|
|
163
|
+
const left = evaluateArithmetic(goal.args[0], env, options);
|
|
164
|
+
const right = evaluateArithmetic(goal.args[1], env, options);
|
|
163
165
|
const cmp = compareArithmeticValues(left, right);
|
|
164
166
|
if (test(cmp)) yield env;
|
|
165
167
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// ISO/IEC 13211-1 implementation-defined processor limits.
|
|
2
|
+
// Keep these values in one place so Prolog flags and all predicates that
|
|
3
|
+
// expose representation limits cannot drift apart.
|
|
4
|
+
|
|
5
|
+
// A finite arity limit keeps the Part 1 max_arity flag truthful. 65,535 is
|
|
6
|
+
// comfortably representable by the JavaScript term model while giving source
|
|
7
|
+
// parsing and term construction one stable ISO-visible boundary.
|
|
8
|
+
export const ISO_MAX_ARITY = 65535;
|