eyeprolog 1.2.8 → 1.2.9

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.2.8",
6
+ "version": "1.2.9",
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
@@ -47,7 +47,10 @@ export class Solver {
47
47
  this.maxInferences = options.maxInferences ?? Infinity;
48
48
  this.inferences = 0;
49
49
  this.inferenceLimitExceeded = false;
50
- this.solutionLimit = options.solutionLimit ?? 10000000;
50
+ // Do not impose an implicit answer cap. Infinite and very large searches are
51
+ // part of normal Prolog semantics; callers that need a resource bound can
52
+ // still supply solutionLimit explicitly.
53
+ this.solutionLimit = options.solutionLimit ?? Infinity;
51
54
  this.solutionsSeen = 0;
52
55
  this.prologFlags = options.prologFlags ?? defaultPrologFlags('error', this.isoStrict);
53
56
  if (this.isoStrict) {
@@ -2063,6 +2063,21 @@ open(X) :- candidate(X), \\+ closed(X).
2063
2063
  assertEqual(answers.join('\n'), 'p(a)\np(b)', 'answers');
2064
2064
  },
2065
2065
  },
2066
+ {
2067
+ name: 'solver has no implicit solution limit',
2068
+ run: () => {
2069
+ const program = Program.parse('p(a).\n');
2070
+ const solver = new Solver(program);
2071
+ assertEqual(String(solver.solutionLimit), 'Infinity', 'default solution limit');
2072
+ // Crossing the former 10,000,000-answer ceiling must not make an
2073
+ // otherwise available answer disappear. This exercises the boundary
2074
+ // without making the regression suite enumerate ten million answers.
2075
+ solver.solutionsSeen = 10_000_000;
2076
+ const goal = parseGoalText('p(X)');
2077
+ const answers = [...solver.solve([goal], new Env(), 0)].map((env) => termToString(goal, env, true));
2078
+ assertEqual(answers.join('\n'), 'p(a)', 'answer beyond former default ceiling');
2079
+ },
2080
+ },
2066
2081
  {
2067
2082
  name: 'solver honors solution limits',
2068
2083
  run: () => {
@@ -1805,7 +1805,13 @@ const solver = new Solver(program, {
1805
1805
  ```
1806
1806
 
1807
1807
  The limits are safety ceilings, not logical declarations. Reaching one may
1808
- truncate search; it does not prove that no further answer exists.
1808
+ truncate search; it does not prove that no further answer exists. At the `Solver`
1809
+ API boundary, `solutionLimit` is opt-in: if it is omitted, ordinary solving and
1810
+ child searches that inherit the solver limit do not stop after a fixed number of
1811
+ solutions. This matters for re-executable goals such as `repeat/0` and for
1812
+ library relations such as `call_nth/2`; an implementation safety threshold must
1813
+ not turn a still re-executable search into logical failure. Embedders that need
1814
+ a finite answer budget should pass `solutionLimit` explicitly.
1809
1815
 
1810
1816
  ### Implementation boundary
1811
1817