eyeprolog 1.3.90 → 1.3.91

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.3.90",
6
+ "version": "1.3.91",
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
@@ -224,12 +224,40 @@ function difConstraint(left, right) {
224
224
  })) return true;
225
225
  return identical(left, right, probe);
226
226
  },
227
- residualGoal() {
228
- return compound('dif', [left, right]);
227
+ residualGoal(env) {
228
+ const [projectedLeft, projectedRight] = projectDifSubterms(left, right, env);
229
+ return compound('dif', [projectedLeft, projectedRight]);
229
230
  },
230
231
  });
231
232
  }
232
233
 
234
+ function projectDifSubterms(left, right, env) {
235
+ left = deref(left, env);
236
+ right = deref(right, env);
237
+ while (left.type === COMPOUND && right.type === COMPOUND &&
238
+ left.name === right.name && left.arity === right.arity) {
239
+ let projectedIndex = -1;
240
+ for (let index = 0; index < left.arity; index++) {
241
+ if (identical(left.args[index], right.args[index], env)) continue;
242
+ const probe = env.clone();
243
+ if (unify(left.args[index], right.args[index], probe, {
244
+ skipVariableConstraints: true,
245
+ skipAttributeHooks: true,
246
+ }) && identical(left, right, probe)) {
247
+ projectedIndex = index;
248
+ break;
249
+ }
250
+ }
251
+ // If no single aligned subterm equality entails equality of the complete
252
+ // compounds, their disequality is a genuine disjunction. Keep it whole
253
+ // instead of inventing auxiliary terms or separate stronger constraints.
254
+ if (projectedIndex === -1) return [left, right];
255
+ left = deref(left.args[projectedIndex], env);
256
+ right = deref(right.args[projectedIndex], env);
257
+ }
258
+ return [left, right];
259
+ }
260
+
233
261
  function* difBuiltin({ goal, env }) {
234
262
  const left = goal.args[0];
235
263
  const right = goal.args[1];
@@ -340,8 +340,8 @@ function regressionCases() {
340
340
  });
341
341
  assertEqual(residuals.status, 0, 'dif/2 residual display status');
342
342
  assertEqual(residuals.stdout,
343
- '?- C = z, D = z, dif(A-z, B-z).\n' +
344
- '?- A = [[]], B = [], dif([[]], [C]).\n' +
343
+ '?- C = z, D = z, dif(A, B).\n' +
344
+ '?- A = [[]], B = [], dif([], C).\n' +
345
345
  '?- X = Y.\n' +
346
346
  '?- ',
347
347
  'dif/2 residual constraints are retained and discharged');
@@ -374,6 +374,12 @@ function regressionCases() {
374
374
  'dif(X-Y,Z-Z),dif(X,Y).\n' +
375
375
  'dif(X,a),dif(X,b).\n' +
376
376
  'dif(X,a),dif(Y,a),X=Y.\n' +
377
+ 'dif(-X,-Y).\n' +
378
+ 'dif(X,Y),X+Y= -XA+ -YA.\n' +
379
+ 'dif(f(X,a),f(Y,a)).\n' +
380
+ 'dif(f(X,X),f(Y,Y)).\n' +
381
+ 'dif(f(X,Y),f(Y,X)).\n' +
382
+ 'dif(f(X,A),f(Y,B)).\n' +
377
383
  'halt.\n',
378
384
  });
379
385
  assertEqual(residuals.status, 0, 'dif/2 normalization display status');
@@ -383,8 +389,14 @@ function regressionCases() {
383
389
  '?- dif(X, Y).\n' +
384
390
  '?- dif(X, a), dif(X, b).\n' +
385
391
  '?- X = Y, dif(Y, a).\n' +
392
+ '?- dif(X, Y).\n' +
393
+ '?- X = -XA, Y = -YA, dif(XA, YA).\n' +
394
+ '?- dif(X, Y).\n' +
395
+ '?- dif(X, Y).\n' +
396
+ '?- dif(X, Y).\n' +
397
+ '?- dif(f(X, A), f(Y, B)).\n' +
386
398
  '?- ',
387
- 'dif/2 residuals are minimal independent of insertion order');
399
+ 'dif/2 residuals are minimal without auxiliary terms');
388
400
  assertEqual(residuals.stderr, '', 'dif/2 normalization display stderr');
389
401
 
390
402
  const pendingDifCount = (text) => {