eyeprolog 1.5.70 → 1.5.71
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 +4 -6
- package/test/regression/cases-regression.mjs +13 -0
- package/test/run-iso-strict.mjs +29 -0
package/package.json
CHANGED
package/src/iso.js
CHANGED
|
@@ -1345,9 +1345,9 @@ function* currentInputBuiltin({ solver, goal, env }) {
|
|
|
1345
1345
|
const value = deref(goal.args[0], env);
|
|
1346
1346
|
if (value.type !== VAR) {
|
|
1347
1347
|
const id = streamTermReference(goal.args[0], env);
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
if (
|
|
1348
|
+
// A closed handle is still a stream-term, but cannot be current (#107).
|
|
1349
|
+
// Validate its shape, then test identity rather than requiring an open stream.
|
|
1350
|
+
if (id === solver.io.currentInput) yield env;
|
|
1351
1351
|
return;
|
|
1352
1352
|
}
|
|
1353
1353
|
const next = env.clone();
|
|
@@ -1357,9 +1357,7 @@ function* currentOutputBuiltin({ solver, goal, env }) {
|
|
|
1357
1357
|
const value = deref(goal.args[0], env);
|
|
1358
1358
|
if (value.type !== VAR) {
|
|
1359
1359
|
const id = streamTermReference(goal.args[0], env);
|
|
1360
|
-
|
|
1361
|
-
if (!stream) throw new PrologError('domain_error(stream)', value);
|
|
1362
|
-
if (stream.id === solver.io.currentOutput) yield env;
|
|
1360
|
+
if (id === solver.io.currentOutput) yield env;
|
|
1363
1361
|
return;
|
|
1364
1362
|
}
|
|
1365
1363
|
const next = env.clone();
|
|
@@ -28,6 +28,19 @@ import {
|
|
|
28
28
|
|
|
29
29
|
export function regressionCases() {
|
|
30
30
|
return [
|
|
31
|
+
{
|
|
32
|
+
name: 'REPL current_input/1 and current_output/1 fail on closed stream handles (issue #107)',
|
|
33
|
+
run: () => {
|
|
34
|
+
const file = sourceAtom(path.join(temp.dir, 'closed-stream-107.txt'));
|
|
35
|
+
const result = runCli([], { input:
|
|
36
|
+
`open(${file},write,S),close(S),current_input(S).\n` +
|
|
37
|
+
`open(${file},write,S),close(S),current_output(S).\nhalt.\n`,
|
|
38
|
+
});
|
|
39
|
+
assertEqual(result.status, 0, result.stderr);
|
|
40
|
+
assertEqual((result.stdout.match(/false\./g) ?? []).length, 2, 'both closed-handle queries fail');
|
|
41
|
+
assertNotIncludes(result.stdout + result.stderr, 'error(', 'no stream domain error');
|
|
42
|
+
},
|
|
43
|
+
},
|
|
31
44
|
{
|
|
32
45
|
name: 'must_be/2 and can_be/2 reject invalid type descriptors before checking values (issue #106)',
|
|
33
46
|
run: () => {
|
package/test/run-iso-strict.mjs
CHANGED
|
@@ -23,6 +23,35 @@ import { TestReporter, isMainModule, runStandalone } from './test-style.mjs';
|
|
|
23
23
|
export function runIsoStrict(reporter = new TestReporter()) {
|
|
24
24
|
reporter.section('Strict ISO core');
|
|
25
25
|
|
|
26
|
+
reporter.test('current stream queries fail for closed handles while stream operations report existence errors (issue #107)', () => {
|
|
27
|
+
const directory = mkdtempSync(join(tmpdir(), 'eyeprolog-stream-107-'));
|
|
28
|
+
const file = `'${join(directory, 'stream.txt').replaceAll("'", "''")}'`;
|
|
29
|
+
try {
|
|
30
|
+
writeFileSync(join(directory, 'stream.txt'), '');
|
|
31
|
+
for (const isoStrict of [false, true]) {
|
|
32
|
+
for (const predicate of ['current_input', 'current_output']) {
|
|
33
|
+
equal(run('', { isoStrict, goal: `open(${file},write,S),close(S),${predicate}(S)` }).stdout,
|
|
34
|
+
'', `${predicate}/1 fails on the reported closed handle`);
|
|
35
|
+
const mode = predicate === 'current_input' ? 'read' : 'write';
|
|
36
|
+
const setter = mode === 'read' ? 'set_input' : 'set_output';
|
|
37
|
+
const source = `answer(ok) :- ${predicate}(Original),open(${file},${mode},S),` +
|
|
38
|
+
`\\+ ${predicate}(S),${setter}(S),${predicate}(S),close(S),` +
|
|
39
|
+
`\\+ ${predicate}(S),${predicate}(Original),` +
|
|
40
|
+
`catch((${setter}(S),fail),error(existence_error(stream,_),_),true),` +
|
|
41
|
+
'catch((close(S),fail),error(existence_error(stream,_),_),true).';
|
|
42
|
+
equal(run(source, { isoStrict, goal: 'answer(X)' }).stdout, 'answer(ok).\n',
|
|
43
|
+
`${predicate}/1 recognizes live handles and restores the standard stream after close`);
|
|
44
|
+
for (const term of ['foo', '42', "'$stream'(foo)"]) {
|
|
45
|
+
equal(capture(() => run('', { isoStrict, goal: `${predicate}(${term})` })).formal,
|
|
46
|
+
'domain_error(stream)', `${predicate}/1 rejects malformed stream term ${term}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} finally {
|
|
51
|
+
rmSync(directory, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
26
55
|
reporter.test('executes ordinary Part 1 clauses', () => {
|
|
27
56
|
const result = run('p(X) :- X = 1.\n', { isoStrict: true, goal: 'p(1)' });
|
|
28
57
|
equal(result.stdout, 'p(1).\n', 'stdout');
|