eyeling 1.8.6 → 1.8.7

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/eyeling.js +135 -35
  2. package/package.json +1 -1
package/eyeling.js CHANGED
@@ -6049,47 +6049,125 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
6049
6049
  }
6050
6050
 
6051
6051
  // log:includes
6052
- // Schema: $s+ log:includes $o+
6052
+ // Schema: $s? log:includes $o+
6053
6053
  // Object may be a concrete formula or the literal `true` (empty formula).
6054
+ //
6055
+ // Priority / closure semantics (subject-driven):
6056
+ // - subject = GraphTerm: explicit scope, run immediately (no closure gating)
6057
+ // - subject = positive integer literal N (>= 1): delay until saturated closure level >= N
6058
+ // - subject = Var: treat as priority 1 (do not bind)
6059
+ // - any other subject: backward-compatible default priority 1
6054
6060
  if (pv === LOG_NS + 'includes') {
6055
- if (!(g.s instanceof GraphTerm)) return [];
6061
+ let scopeFacts = null;
6062
+ let scopeBackRules = backRules;
6056
6063
 
6057
- // Empty formula is always included.
6064
+ if (g.s instanceof GraphTerm) {
6065
+ // Explicit scope graph: immediate, and do not use rules outside the quoted graph.
6066
+ scopeFacts = g.s.triples.slice();
6067
+ ensureFactIndexes(scopeFacts);
6068
+ Object.defineProperty(scopeFacts, '__scopedSnapshot', {
6069
+ value: scopeFacts,
6070
+ enumerable: false,
6071
+ writable: true,
6072
+ });
6073
+ const lvlHere = facts && typeof facts.__scopedClosureLevel === 'number' ? facts.__scopedClosureLevel : 0;
6074
+ Object.defineProperty(scopeFacts, '__scopedClosureLevel', {
6075
+ value: lvlHere,
6076
+ enumerable: false,
6077
+ writable: true,
6078
+ });
6079
+ scopeBackRules = [];
6080
+ } else {
6081
+ // Priority-gated scope: query the frozen snapshot for the requested closure level.
6082
+ let prio = 1;
6083
+ if (g.s instanceof Var) {
6084
+ prio = 1; // do not bind
6085
+ } else {
6086
+ const p0 = __logNaturalPriorityFromTerm(g.s);
6087
+ if (p0 !== null) prio = p0;
6088
+ }
6089
+
6090
+ const snap = facts.__scopedSnapshot || null;
6091
+ const lvl = (facts && typeof facts.__scopedClosureLevel === 'number' && facts.__scopedClosureLevel) || 0;
6092
+ if (!snap) return []; // DELAY until snapshot exists
6093
+ if (lvl < prio) return []; // DELAY until saturated closure prio exists
6094
+ scopeFacts = snap;
6095
+ }
6096
+
6097
+ // Empty formula is always included (but may be priority-gated above).
6058
6098
  if (g.o instanceof Literal && g.o.value === 'true') return [{ ...subst }];
6059
6099
  if (!(g.o instanceof GraphTerm)) return [];
6060
6100
 
6061
- const scopeFacts = g.s.triples.slice();
6062
- ensureFactIndexes(scopeFacts);
6063
- Object.defineProperty(scopeFacts, '__scopedSnapshot', {
6064
- value: scopeFacts,
6065
- enumerable: false,
6066
- writable: true,
6067
- });
6068
-
6069
6101
  const visited2 = [];
6070
6102
  // Start from the incoming substitution so bindings flow outward.
6071
- return proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen, maxResults);
6103
+ return proveGoals(
6104
+ Array.from(g.o.triples),
6105
+ { ...subst },
6106
+ scopeFacts,
6107
+ scopeBackRules,
6108
+ depth + 1,
6109
+ visited2,
6110
+ varGen,
6111
+ maxResults,
6112
+ );
6072
6113
  }
6073
6114
 
6074
6115
  // log:notIncludes
6075
- // Schema: $s+ log:notIncludes $o+
6116
+ // Schema: $s? log:notIncludes $o+
6117
+ //
6118
+ // Priority / closure semantics (subject-driven): same as log:includes above.
6076
6119
  if (pv === LOG_NS + 'notIncludes') {
6077
- if (!(g.s instanceof GraphTerm)) return [];
6120
+ let scopeFacts = null;
6121
+ let scopeBackRules = backRules;
6078
6122
 
6079
- // Empty formula is always included, so it is never "not included".
6123
+ if (g.s instanceof GraphTerm) {
6124
+ // Explicit scope graph: immediate, and do not use rules outside the quoted graph.
6125
+ scopeFacts = g.s.triples.slice();
6126
+ ensureFactIndexes(scopeFacts);
6127
+ Object.defineProperty(scopeFacts, '__scopedSnapshot', {
6128
+ value: scopeFacts,
6129
+ enumerable: false,
6130
+ writable: true,
6131
+ });
6132
+ const lvlHere = facts && typeof facts.__scopedClosureLevel === 'number' ? facts.__scopedClosureLevel : 0;
6133
+ Object.defineProperty(scopeFacts, '__scopedClosureLevel', {
6134
+ value: lvlHere,
6135
+ enumerable: false,
6136
+ writable: true,
6137
+ });
6138
+ scopeBackRules = [];
6139
+ } else {
6140
+ // Priority-gated scope: query the frozen snapshot for the requested closure level.
6141
+ let prio = 1;
6142
+ if (g.s instanceof Var) {
6143
+ prio = 1; // do not bind
6144
+ } else {
6145
+ const p0 = __logNaturalPriorityFromTerm(g.s);
6146
+ if (p0 !== null) prio = p0;
6147
+ }
6148
+
6149
+ const snap = facts.__scopedSnapshot || null;
6150
+ const lvl = (facts && typeof facts.__scopedClosureLevel === 'number' && facts.__scopedClosureLevel) || 0;
6151
+ if (!snap) return []; // DELAY until snapshot exists
6152
+ if (lvl < prio) return []; // DELAY until saturated closure prio exists
6153
+ scopeFacts = snap;
6154
+ }
6155
+
6156
+ // Empty formula is always included, so it is never "not included" (but may be priority-gated above).
6080
6157
  if (g.o instanceof Literal && g.o.value === 'true') return [];
6081
6158
  if (!(g.o instanceof GraphTerm)) return [];
6082
6159
 
6083
- const scopeFacts = g.s.triples.slice();
6084
- ensureFactIndexes(scopeFacts);
6085
- Object.defineProperty(scopeFacts, '__scopedSnapshot', {
6086
- value: scopeFacts,
6087
- enumerable: false,
6088
- writable: true,
6089
- });
6090
-
6091
6160
  const visited2 = [];
6092
- const sols = proveGoals(Array.from(g.o.triples), { ...subst }, scopeFacts, [], depth + 1, visited2, varGen, 1);
6161
+ const sols = proveGoals(
6162
+ Array.from(g.o.triples),
6163
+ { ...subst },
6164
+ scopeFacts,
6165
+ scopeBackRules,
6166
+ depth + 1,
6167
+ visited2,
6168
+ varGen,
6169
+ 1,
6170
+ );
6093
6171
  return sols.length ? [] : [{ ...subst }];
6094
6172
  }
6095
6173
 
@@ -6925,22 +7003,44 @@ function forwardChain(facts, forwardRules, backRules, onDerived /* optional */)
6925
7003
  function scanTriple(tr) {
6926
7004
  if (!(tr && tr.p instanceof Iri)) return;
6927
7005
  const pv = tr.p.value;
6928
- if (pv !== LOG_NS + 'collectAllIn' && pv !== LOG_NS + 'forAllIn') return;
6929
- // Explicit scope graphs are immediate and do not require a closure.
6930
- if (tr.o instanceof GraphTerm) return;
6931
- // Variable or non-numeric object => default priority 1 (if used).
6932
- if (tr.o instanceof Var) {
6933
- if (maxP < 1) maxP = 1;
7006
+
7007
+ // log:collectAllIn / log:forAllIn use the object position for the priority.
7008
+ if (pv === LOG_NS + 'collectAllIn' || pv === LOG_NS + 'forAllIn') {
7009
+ // Explicit scope graphs are immediate and do not require a closure.
7010
+ if (tr.o instanceof GraphTerm) return;
7011
+ // Variable or non-numeric object => default priority 1 (if used).
7012
+ if (tr.o instanceof Var) {
7013
+ if (maxP < 1) maxP = 1;
7014
+ return;
7015
+ }
7016
+ const p0 = __logNaturalPriorityFromTerm(tr.o);
7017
+ if (p0 !== null) {
7018
+ if (p0 > maxP) maxP = p0;
7019
+ } else {
7020
+ if (maxP < 1) maxP = 1;
7021
+ }
6934
7022
  return;
6935
7023
  }
6936
- const p0 = __logNaturalPriorityFromTerm(tr.o);
6937
- if (p0 !== null) {
6938
- if (p0 > maxP) maxP = p0;
6939
- } else {
6940
- if (maxP < 1) maxP = 1;
7024
+
7025
+ // log:includes / log:notIncludes use the subject position for the priority.
7026
+ if (pv === LOG_NS + 'includes' || pv === LOG_NS + 'notIncludes') {
7027
+ // Explicit scope graphs are immediate and do not require a closure.
7028
+ if (tr.s instanceof GraphTerm) return;
7029
+ // Variable or non-numeric subject => default priority 1 (if used).
7030
+ if (tr.s instanceof Var) {
7031
+ if (maxP < 1) maxP = 1;
7032
+ return;
7033
+ }
7034
+ const p0 = __logNaturalPriorityFromTerm(tr.s);
7035
+ if (p0 !== null) {
7036
+ if (p0 > maxP) maxP = p0;
7037
+ } else {
7038
+ if (maxP < 1) maxP = 1;
7039
+ }
6941
7040
  }
6942
7041
  }
6943
7042
 
7043
+
6944
7044
  for (const r of forwardRules) {
6945
7045
  for (const tr of r.premise) scanTriple(tr);
6946
7046
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.8.6",
3
+ "version": "1.8.7",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [