eyeprolog 1.5.103 → 1.5.105

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.103",
6
+ "version": "1.5.105",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/iso.js CHANGED
@@ -674,21 +674,26 @@ function* termVariablesBuiltin({ goal, env }) {
674
674
  }
675
675
 
676
676
  function validPredicateIndicator(term) {
677
- if (term.type !== COMPOUND || term.name !== '/' || term.arity !== 2) return false;
678
- const [name, arity] = term.args;
679
- // Name/Arity denotes a predicate indicator only when some instance of it
680
- // could be one: Name an atom, Arity a non-negative integer. The same
681
- // shared variable in both positions (current_predicate(X/X), issue #115)
682
- // looks valid argument-by-argument -- each position individually accepts
683
- // an unbound variable -- but no instantiation can satisfy both at once,
684
- // since binding that one variable to an atom makes Arity an atom too, not
685
- // an integer. stc#79 treats this as no valid instance existing at all,
686
- // the same as a bare atom argument, so it must raise
687
- // type_error(predicate_indicator, _) rather than just finding no matches.
688
- if (name.type === VAR && arity.type === VAR && name.name === arity.name) return false;
689
- return (name.type === VAR || name.type === ATOM) &&
690
- (arity.type === VAR ||
691
- (arity.type === NUMBER && isDecimalInteger(arity.name) && BigInt(arity.name) >= 0n));
677
+ // Each position is checked independently, not "could some single
678
+ // instantiation satisfy both at once" -- so current_predicate(X/X)
679
+ // (issue #115) passes this check exactly like current_predicate(X/Y)
680
+ // does, and is then left to the ordinary group search below, which
681
+ // unifies goal.args[0] (still X/X, the two positions aliased) against
682
+ // each candidate Name/Arity in turn. Name and Arity are never the same
683
+ // type, so that unification always fails and the goal simply finds no
684
+ // solutions, the same way ISO's own current_op/3 (8.14.4.1) is specified:
685
+ // its candidate set is built by unifying a triple's priority (an integer)
686
+ // and specifier (an atom) against Priority and Op-specifier, so aliasing
687
+ // those two arguments the same way makes every candidate fail to unify
688
+ // and the set come up empty -- current_op/3's own Errors subclause
689
+ // (8.14.4.3) has no special case for it, only domain errors for an
690
+ // argument that is instantiated and outright wrong on its own. A
691
+ // predicate_indicator type error remains for a term that cannot look
692
+ // like a Name/Arity pair at all (a bare atom, a negative arity, ...).
693
+ return term.type === COMPOUND && term.name === '/' && term.arity === 2 &&
694
+ (term.args[0].type === VAR || term.args[0].type === ATOM) &&
695
+ (term.args[1].type === VAR ||
696
+ (term.args[1].type === NUMBER && isDecimalInteger(term.args[1].name) && BigInt(term.args[1].name) >= 0n));
692
697
  }
693
698
 
694
699
  const currentPredicateBuiltin = pendingBuiltin(currentPredicateSolutions);
@@ -1541,11 +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
1544
  ['asserta(_)', 'instantiation_error', 'asserta/1 variable head'],
1550
1545
  ['asserta(4)', 'type_error(callable)', 'asserta/1 head type'],
1551
1546
  ['asserta((p:-4))', 'type_error(callable)', 'asserta/1 body conversion'],
@@ -1596,6 +1591,26 @@ export function runIsoStrict(reporter = new TestReporter()) {
1596
1591
 
1597
1592
  const current = run('p(a).\nq.\n', { isoStrict: true, goal: 'current_predicate(p/1)' });
1598
1593
  equal(current.stats.completed_goal_lists, 1, 'current_predicate/1 finds a user procedure');
1594
+
1595
+ // The same variable filling both Name and Arity (issue #115, stc#79)
1596
+ // looks valid position-by-position -- each alone accepts an unbound
1597
+ // variable, and current_predicate/1 must support both fully unbound
1598
+ // (current_predicate(X/Y), a generator) -- but no instantiation can
1599
+ // satisfy both positions of one shared variable at once, since binding
1600
+ // it to an atom makes Arity an atom too, not an integer. ISO does not
1601
+ // special-case this for the structurally identical current_op/3
1602
+ // (8.14.4.1): its candidate set is built by unifying a triple's integer
1603
+ // priority and atom specifier against Priority and Op-specifier, so
1604
+ // aliasing those two arguments the same way simply makes every
1605
+ // candidate fail to unify and the set come up empty, and current_op/3's
1606
+ // own Errors subclause (8.14.4.3) has no case for it. current_predicate
1607
+ // /1 follows that precedent: it fails rather than raising an error.
1608
+ for (const [goal, label] of [
1609
+ ['current_predicate(X/X)', 'current_predicate/1 aliased name/arity variable fails'],
1610
+ ['X = Y, current_predicate(X/Y)', 'current_predicate/1 previously unified name/arity variables fails'],
1611
+ ]) {
1612
+ equal(run('', { isoStrict: true, goal }).stats.completed_goal_lists, 0, label);
1613
+ }
1599
1614
  });
1600
1615
 
1601
1616
  reporter.test('preserves 7.6.2 source-body conversion identity for clause/2 and retract/1', () => {