eyeprolog 1.5.29 → 1.5.30

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/solver.js +13 -5
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.5.29",
6
+ "version": "1.5.30",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
package/src/solver.js CHANGED
@@ -848,15 +848,15 @@ export class Solver {
848
848
  if (!entry.computing) {
849
849
  if (!this.tableCoordinator) {
850
850
  this.tableCoordinator = { entry, cycleSeen: false, entries: new Set([entry]) };
851
- scheduleTableFixpointRound(stack, this, { entry, group, goal, rest, env, depth, active });
851
+ scheduleTableFixpointRound(stack, this, { entry, group, goal, rest, env, depth, active, mapKey });
852
852
  } else {
853
853
  entry.computing = true;
854
854
  stack.push({ kind: 'completeMemo', entry, revision: this.programRevision });
855
- pushUserGoalUncachedFrames(stack, this, group, goal, [{ kind: 'memoStore', entry, goal, revision: this.programRevision }, ...rest], env, depth, active);
855
+ pushUserGoalUncachedFrames(stack, this, group, goal, [{ kind: 'memoStore', entry, goal, revision: this.programRevision }, ...rest], env, depth, active, mapKey);
856
856
  }
857
857
  break;
858
858
  }
859
- if (this.tableCoordinator && (usingBroadTable || activeVariantIn(goal, env, active))) {
859
+ if (this.tableCoordinator && (usingBroadTable || activeTableKeyIn(mapKey, active))) {
860
860
  this.tableCoordinator.cycleSeen = true;
861
861
  }
862
862
  pushMemoAnswerFrames(stack, entry, goal, rest, env, depth, active, this);
@@ -1252,6 +1252,7 @@ function scheduleTableFixpointRound(stack, solver, frame) {
1252
1252
  frame.env,
1253
1253
  frame.depth,
1254
1254
  frame.active,
1255
+ frame.mapKey,
1255
1256
  );
1256
1257
  }
1257
1258
 
@@ -1289,13 +1290,13 @@ function pushMemoAnswerFrames(stack, entry, goal, rest, env, depth, active, solv
1289
1290
  for (let answerIndex = entry.answers.length - 1; answerIndex >= 0; answerIndex--) pushReplay(answerIndex);
1290
1291
  }
1291
1292
 
1292
- function pushUserGoalUncachedFrames(stack, solver, group, goal, rest, env, depth, active) {
1293
+ function pushUserGoalUncachedFrames(stack, solver, group, goal, rest, env, depth, active, tableMapKey = null) {
1293
1294
  if (group.fastPi && pushFastPiFrames(stack, goal, rest, env, depth, active)) return;
1294
1295
  if (tryPushGroundScalarRuleFrame(stack, solver, group, goal, rest, env, depth, active)) return;
1295
1296
  if (tryPushGroundChainFrames(stack, solver, group, goal, rest, env, depth, active)) return;
1296
1297
  const candidates = selectClauseCandidates(group, goal, env);
1297
1298
  const frames = [];
1298
- const invocation = { goal, env: env._snapshotForSolverRead() };
1299
+ const invocation = { goal, env: env._snapshotForSolverRead(), tableMapKey };
1299
1300
  // Active frames serve two purposes: they delimit cut and detect variants in
1300
1301
  // recursive user predicates. Cut-free, non-recursive library helpers need
1301
1302
  // neither. Copying their full active stack at every recursive step made
@@ -3015,6 +3016,13 @@ function rememberMemoAnswer(entry, goal, env) {
3015
3016
  }
3016
3017
  }
3017
3018
 
3019
+ function activeTableKeyIn(mapKey, active) {
3020
+ for (let index = active.length - 1; index >= 0; index--) {
3021
+ if (active[index]?.tableMapKey === mapKey) return true;
3022
+ }
3023
+ return false;
3024
+ }
3025
+
3018
3026
  function activeVariantIn(goal, env, active) {
3019
3027
  if (active.length === 0) return false;
3020
3028
  let goalShape = null;