eyeprolog 1.5.104 → 1.5.106
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 +23 -15
- package/test/run-iso-strict.mjs +31 -6
package/package.json
CHANGED
package/src/iso.js
CHANGED
|
@@ -674,21 +674,29 @@ function* termVariablesBuiltin({ goal, env }) {
|
|
|
674
674
|
}
|
|
675
675
|
|
|
676
676
|
function validPredicateIndicator(term) {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
//
|
|
680
|
-
//
|
|
681
|
-
//
|
|
682
|
-
//
|
|
683
|
-
//
|
|
684
|
-
//
|
|
685
|
-
//
|
|
686
|
-
//
|
|
687
|
-
//
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
677
|
+
// ISO 13211-1 8.8.2.3's sole error condition is "PI is neither a variable
|
|
678
|
+
// nor a predicate indicator -> type_error(predicate_indicator, PI)", and
|
|
679
|
+
// 8.8.2.4's own worked example -- current_predicate(Name/1) succeeds,
|
|
680
|
+
// backtracking through every matching Name -- shows that a compound whose
|
|
681
|
+
// Name is merely a variable already counts as "a predicate indicator" for
|
|
682
|
+
// this check, not just one whose Name and Arity are already bound to an
|
|
683
|
+
// atom and a non-negative integer as 7.1.6.6 defines the type. So each
|
|
684
|
+
// position is checked independently here, not "could some single
|
|
685
|
+
// instantiation satisfy both at once": current_predicate(X/X) (issue #115)
|
|
686
|
+
// passes this check exactly like current_predicate(X/Y) does, and is left
|
|
687
|
+
// to the ordinary group search below (8.8.2.1 a-c), which unifies
|
|
688
|
+
// goal.args[0] (still X/X, the two positions aliased) against each
|
|
689
|
+
// candidate Name/Arity in turn. Name and Arity are never the same type, so
|
|
690
|
+
// that unification always fails for every candidate and the goal simply
|
|
691
|
+
// finds no solutions -- 8.8.2.1's own procedure gives no other outcome for
|
|
692
|
+
// an empty candidate set than "the goal fails" (step c), with no separate
|
|
693
|
+
// provision for an argument that turned out unable to ever unify. A
|
|
694
|
+
// predicate_indicator type error remains for a term that cannot look like
|
|
695
|
+
// a Name/Arity pair at all (a bare atom, a negative arity, ...).
|
|
696
|
+
return term.type === COMPOUND && term.name === '/' && term.arity === 2 &&
|
|
697
|
+
(term.args[0].type === VAR || term.args[0].type === ATOM) &&
|
|
698
|
+
(term.args[1].type === VAR ||
|
|
699
|
+
(term.args[1].type === NUMBER && isDecimalInteger(term.args[1].name) && BigInt(term.args[1].name) >= 0n));
|
|
692
700
|
}
|
|
693
701
|
|
|
694
702
|
const currentPredicateBuiltin = pendingBuiltin(currentPredicateSolutions);
|
package/test/run-iso-strict.mjs
CHANGED
|
@@ -1541,12 +1541,6 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
1541
1541
|
['clause(X,_)', 'instantiation_error', 'clause/2 variable head'],
|
|
1542
1542
|
['clause(4,_)', 'type_error(callable)', 'clause/2 head type'],
|
|
1543
1543
|
['current_predicate(4)', 'type_error(predicate_indicator)', 'current_predicate/1 indicator type'],
|
|
1544
|
-
// The same variable filling both Name and Arity (issue #115, stc#79)
|
|
1545
|
-
// looks valid position-by-position -- each alone accepts an unbound
|
|
1546
|
-
// variable -- but no instantiation can satisfy both at once, since
|
|
1547
|
-
// binding it to an atom makes Arity an atom too, not an integer.
|
|
1548
|
-
['current_predicate(X/X)', 'type_error(predicate_indicator)', 'current_predicate/1 aliased name/arity variable'],
|
|
1549
|
-
['X = Y, current_predicate(X/Y)', 'type_error(predicate_indicator)', 'current_predicate/1 previously unified name/arity variables'],
|
|
1550
1544
|
['asserta(_)', 'instantiation_error', 'asserta/1 variable head'],
|
|
1551
1545
|
['asserta(4)', 'type_error(callable)', 'asserta/1 head type'],
|
|
1552
1546
|
['asserta((p:-4))', 'type_error(callable)', 'asserta/1 body conversion'],
|
|
@@ -1597,6 +1591,37 @@ export function runIsoStrict(reporter = new TestReporter()) {
|
|
|
1597
1591
|
|
|
1598
1592
|
const current = run('p(a).\nq.\n', { isoStrict: true, goal: 'current_predicate(p/1)' });
|
|
1599
1593
|
equal(current.stats.completed_goal_lists, 1, 'current_predicate/1 finds a user procedure');
|
|
1594
|
+
|
|
1595
|
+
// ISO 13211-1 8.8.2.4's own worked example: current_predicate(Name/1)
|
|
1596
|
+
// succeeds with an unbound Name, backtracking through every arity-1
|
|
1597
|
+
// predicate. A compound with an unbound component already counts as "a
|
|
1598
|
+
// predicate indicator" for 8.8.2.3's error check, not only one whose
|
|
1599
|
+
// Name and Arity are already bound to an atom and a non-negative
|
|
1600
|
+
// integer as 7.1.6.6 defines the type.
|
|
1601
|
+
equal(
|
|
1602
|
+
run('elk(a).\ninsect(b).\n', { isoStrict: true, goal: 'current_predicate(Name/1)' }).stats.completed_goal_lists,
|
|
1603
|
+
2,
|
|
1604
|
+
'current_predicate/1 enumerates every matching Name with Arity fixed and Name unbound',
|
|
1605
|
+
);
|
|
1606
|
+
|
|
1607
|
+
// The same variable filling both Name and Arity (issue #115) looks
|
|
1608
|
+
// valid position-by-position by that same per-component check -- each
|
|
1609
|
+
// position alone accepts an unbound variable, and current_predicate/1
|
|
1610
|
+
// must support both fully unbound (current_predicate(X/Y), a generator,
|
|
1611
|
+
// just demonstrated above) -- but no instantiation can satisfy both
|
|
1612
|
+
// positions of one shared variable at once, since binding it to an atom
|
|
1613
|
+
// makes Arity an atom too, not an integer. 8.8.2.3 has only the one
|
|
1614
|
+
// error condition above, and 8.8.2.1's procedure gives no outcome for an
|
|
1615
|
+
// empty candidate set (step a-c) besides "the goal fails" (step c) --
|
|
1616
|
+
// there is no separate provision for an argument that turned out unable
|
|
1617
|
+
// to ever unify with anything. current_predicate/1 follows that: it
|
|
1618
|
+
// fails rather than raising an error.
|
|
1619
|
+
for (const [goal, label] of [
|
|
1620
|
+
['current_predicate(X/X)', 'current_predicate/1 aliased name/arity variable fails'],
|
|
1621
|
+
['X = Y, current_predicate(X/Y)', 'current_predicate/1 previously unified name/arity variables fails'],
|
|
1622
|
+
]) {
|
|
1623
|
+
equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 0, label);
|
|
1624
|
+
}
|
|
1600
1625
|
});
|
|
1601
1626
|
|
|
1602
1627
|
reporter.test('preserves 7.6.2 source-body conversion identity for clause/2 and retract/1', () => {
|