eyeling 1.6.32 → 1.7.0

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.
@@ -0,0 +1,7 @@
1
+ PREFIX log: <http://www.w3.org/2000/10/swap/log#>
2
+ PREFIX : <http://example.org/>
3
+
4
+ :Alice :loves :Bob.
5
+ :Bob a :Person.
6
+
7
+ RULE { :Alice :hates :Nobody. } WHERE { NOT { :Alice :hates ?X } ?X a :Person. }
package/eyeling.js CHANGED
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  /*
5
- * eyeling.js — a minimal Notation3 (N3) reasoner in JavaScript
5
+ * eyeling.js — A Notation3 (N3) reasoner in JavaScript
6
6
  *
7
7
  * High-level pipeline:
8
8
  * 1) Read an N3 file from disk.
@@ -84,6 +84,8 @@ const jsonPointerCache = new Map();
84
84
 
85
85
  // Controls whether human-readable proof comments are printed.
86
86
  let proofCommentsEnabled = false;
87
+ // Super restricted mode: disable *all* builtins except => / <= (log:implies / log:impliedBy)
88
+ let superRestrictedMode = false;
87
89
 
88
90
  // ----------------------------------------------------------------------------
89
91
  // Deterministic time support
@@ -273,7 +275,7 @@ class OpenListTerm extends Term {
273
275
  }
274
276
  }
275
277
 
276
- class FormulaTerm extends Term {
278
+ class GraphTerm extends Term {
277
279
  constructor(triples) {
278
280
  super();
279
281
  this.triples = triples; // Triple[]
@@ -891,7 +893,7 @@ function collectIrisInTerm(t) {
891
893
  for (const x of t.elems) out.push(...collectIrisInTerm(x));
892
894
  } else if (t instanceof OpenListTerm) {
893
895
  for (const x of t.prefix) out.push(...collectIrisInTerm(x));
894
- } else if (t instanceof FormulaTerm) {
896
+ } else if (t instanceof GraphTerm) {
895
897
  for (const tr of t.triples) {
896
898
  out.push(...collectIrisInTerm(tr.s));
897
899
  out.push(...collectIrisInTerm(tr.p));
@@ -909,7 +911,7 @@ function collectVarsInTerm(t, acc) {
909
911
  } else if (t instanceof OpenListTerm) {
910
912
  for (const x of t.prefix) collectVarsInTerm(x, acc);
911
913
  acc.add(t.tailVar);
912
- } else if (t instanceof FormulaTerm) {
914
+ } else if (t instanceof GraphTerm) {
913
915
  for (const tr of t.triples) {
914
916
  collectVarsInTerm(tr.s, acc);
915
917
  collectVarsInTerm(tr.p, acc);
@@ -940,7 +942,7 @@ function collectBlankLabelsInTerm(t, acc) {
940
942
  for (const x of t.elems) collectBlankLabelsInTerm(x, acc);
941
943
  } else if (t instanceof OpenListTerm) {
942
944
  for (const x of t.prefix) collectBlankLabelsInTerm(x, acc);
943
- } else if (t instanceof FormulaTerm) {
945
+ } else if (t instanceof GraphTerm) {
944
946
  for (const tr of t.triples) {
945
947
  collectBlankLabelsInTerm(tr.s, acc);
946
948
  collectBlankLabelsInTerm(tr.p, acc);
@@ -1059,9 +1061,9 @@ class Parser {
1059
1061
 
1060
1062
  // normalize explicit log:implies / log:impliedBy at top-level
1061
1063
  for (const tr of more) {
1062
- if (isLogImplies(tr.p) && tr.s instanceof FormulaTerm && tr.o instanceof FormulaTerm) {
1064
+ if (isLogImplies(tr.p) && tr.s instanceof GraphTerm && tr.o instanceof GraphTerm) {
1063
1065
  forwardRules.push(this.makeRule(tr.s, tr.o, true));
1064
- } else if (isLogImpliedBy(tr.p) && tr.s instanceof FormulaTerm && tr.o instanceof FormulaTerm) {
1066
+ } else if (isLogImpliedBy(tr.p) && tr.s instanceof GraphTerm && tr.o instanceof GraphTerm) {
1065
1067
  backwardRules.push(this.makeRule(tr.s, tr.o, false));
1066
1068
  } else {
1067
1069
  triples.push(tr);
@@ -1244,7 +1246,7 @@ class Parser {
1244
1246
  if (typ === 'Var') return new Var(val || '');
1245
1247
  if (typ === 'LParen') return this.parseList();
1246
1248
  if (typ === 'LBracket') return this.parseBlank();
1247
- if (typ === 'LBrace') return this.parseFormula();
1249
+ if (typ === 'LBrace') return this.parseGraph();
1248
1250
 
1249
1251
  throw new Error(`Unexpected term token: ${tok.toString()}`);
1250
1252
  }
@@ -1374,7 +1376,7 @@ class Parser {
1374
1376
  return new Blank(id);
1375
1377
  }
1376
1378
 
1377
- parseFormula() {
1379
+ parseGraph() {
1378
1380
  const triples = [];
1379
1381
  while (this.peek().typ !== 'RBrace') {
1380
1382
  const left = this.parseTerm();
@@ -1422,7 +1424,7 @@ class Parser {
1422
1424
  }
1423
1425
  }
1424
1426
  this.next(); // consume '}'
1425
- return new FormulaTerm(triples);
1427
+ return new GraphTerm(triples);
1426
1428
  }
1427
1429
 
1428
1430
  parsePredicateObjectList(subject) {
@@ -1514,7 +1516,7 @@ class Parser {
1514
1516
  }
1515
1517
 
1516
1518
  let rawPremise;
1517
- if (premiseTerm instanceof FormulaTerm) {
1519
+ if (premiseTerm instanceof GraphTerm) {
1518
1520
  rawPremise = premiseTerm.triples;
1519
1521
  } else if (premiseTerm instanceof Literal && premiseTerm.value === 'true') {
1520
1522
  rawPremise = [];
@@ -1523,7 +1525,7 @@ class Parser {
1523
1525
  }
1524
1526
 
1525
1527
  let rawConclusion;
1526
- if (conclTerm instanceof FormulaTerm) {
1528
+ if (conclTerm instanceof GraphTerm) {
1527
1529
  rawConclusion = conclTerm.triples;
1528
1530
  } else if (conclTerm instanceof Literal && conclTerm.value === 'false') {
1529
1531
  rawConclusion = [];
@@ -1566,11 +1568,11 @@ function liftBlankRuleVars(premise, conclusion) {
1566
1568
  t.tailVar,
1567
1569
  );
1568
1570
  }
1569
- if (t instanceof FormulaTerm) {
1571
+ if (t instanceof GraphTerm) {
1570
1572
  const triples = t.triples.map(
1571
1573
  (tr) => new Triple(convertTerm(tr.s, mapping, counter), convertTerm(tr.p, mapping, counter), convertTerm(tr.o, mapping, counter)),
1572
1574
  );
1573
- return new FormulaTerm(triples);
1575
+ return new GraphTerm(triples);
1574
1576
  }
1575
1577
  return t;
1576
1578
  }
@@ -1635,8 +1637,8 @@ function skolemizeTermForHeadBlanks(t, headBlankLabels, mapping, skCounter, firi
1635
1637
  );
1636
1638
  }
1637
1639
 
1638
- if (t instanceof FormulaTerm) {
1639
- return new FormulaTerm(
1640
+ if (t instanceof GraphTerm) {
1641
+ return new GraphTerm(
1640
1642
  t.triples.map((tr) => skolemizeTripleForHeadBlanks(tr, headBlankLabels, mapping, skCounter, firingKey, globalMap)),
1641
1643
  );
1642
1644
  }
@@ -1707,8 +1709,8 @@ function termsEqual(a, b) {
1707
1709
  return true;
1708
1710
  }
1709
1711
 
1710
- if (a instanceof FormulaTerm) {
1711
- return alphaEqFormulaTriples(a.triples, b.triples);
1712
+ if (a instanceof GraphTerm) {
1713
+ return alphaEqGraphTriples(a.triples, b.triples);
1712
1714
  }
1713
1715
 
1714
1716
  return false;
@@ -1775,8 +1777,8 @@ function termsEqualNoIntDecimal(a, b) {
1775
1777
  return true;
1776
1778
  }
1777
1779
 
1778
- if (a instanceof FormulaTerm) {
1779
- return alphaEqFormulaTriples(a.triples, b.triples);
1780
+ if (a instanceof GraphTerm) {
1781
+ return alphaEqGraphTriples(a.triples, b.triples);
1780
1782
  }
1781
1783
 
1782
1784
  return false;
@@ -1802,7 +1804,7 @@ function alphaEqVarName(x, y, vmap) {
1802
1804
  return true;
1803
1805
  }
1804
1806
 
1805
- function alphaEqTermInFormula(a, b, vmap, bmap) {
1807
+ function alphaEqTermInGraph(a, b, vmap, bmap) {
1806
1808
  // Blank nodes: renamable
1807
1809
  if (a instanceof Blank && b instanceof Blank) {
1808
1810
  const x = a.label;
@@ -1823,7 +1825,7 @@ function alphaEqTermInFormula(a, b, vmap, bmap) {
1823
1825
  if (a instanceof ListTerm && b instanceof ListTerm) {
1824
1826
  if (a.elems.length !== b.elems.length) return false;
1825
1827
  for (let i = 0; i < a.elems.length; i++) {
1826
- if (!alphaEqTermInFormula(a.elems[i], b.elems[i], vmap, bmap)) return false;
1828
+ if (!alphaEqTermInGraph(a.elems[i], b.elems[i], vmap, bmap)) return false;
1827
1829
  }
1828
1830
  return true;
1829
1831
  }
@@ -1831,27 +1833,25 @@ function alphaEqTermInFormula(a, b, vmap, bmap) {
1831
1833
  if (a instanceof OpenListTerm && b instanceof OpenListTerm) {
1832
1834
  if (a.prefix.length !== b.prefix.length) return false;
1833
1835
  for (let i = 0; i < a.prefix.length; i++) {
1834
- if (!alphaEqTermInFormula(a.prefix[i], b.prefix[i], vmap, bmap)) return false;
1836
+ if (!alphaEqTermInGraph(a.prefix[i], b.prefix[i], vmap, bmap)) return false;
1835
1837
  }
1836
1838
  // tailVar is a var-name string, so treat it as renamable too
1837
1839
  return alphaEqVarName(a.tailVar, b.tailVar, vmap);
1838
1840
  }
1839
1841
 
1840
1842
  // Nested formulas: compare with fresh maps (separate scope)
1841
- if (a instanceof FormulaTerm && b instanceof FormulaTerm) {
1842
- return alphaEqFormulaTriples(a.triples, b.triples);
1843
+ if (a instanceof GraphTerm && b instanceof GraphTerm) {
1844
+ return alphaEqGraphTriples(a.triples, b.triples);
1843
1845
  }
1844
1846
 
1845
1847
  return false;
1846
1848
  }
1847
1849
 
1848
- function alphaEqTripleInFormula(a, b, vmap, bmap) {
1849
- return (
1850
- alphaEqTermInFormula(a.s, b.s, vmap, bmap) && alphaEqTermInFormula(a.p, b.p, vmap, bmap) && alphaEqTermInFormula(a.o, b.o, vmap, bmap)
1851
- );
1850
+ function alphaEqTripleInGraph(a, b, vmap, bmap) {
1851
+ return alphaEqTermInGraph(a.s, b.s, vmap, bmap) && alphaEqTermInGraph(a.p, b.p, vmap, bmap) && alphaEqTermInGraph(a.o, b.o, vmap, bmap);
1852
1852
  }
1853
1853
 
1854
- function alphaEqFormulaTriples(xs, ys) {
1854
+ function alphaEqGraphTriples(xs, ys) {
1855
1855
  if (xs.length !== ys.length) return false;
1856
1856
  // Fast path: exact same sequence.
1857
1857
  if (triplesListEqual(xs, ys)) return true;
@@ -1870,7 +1870,7 @@ function alphaEqFormulaTriples(xs, ys) {
1870
1870
 
1871
1871
  const v2 = { ...vmap };
1872
1872
  const b2 = { ...bmap };
1873
- if (!alphaEqTripleInFormula(x, y, v2, b2)) continue;
1873
+ if (!alphaEqTripleInGraph(x, y, v2, b2)) continue;
1874
1874
 
1875
1875
  used[j] = true;
1876
1876
  if (step(i + 1, v2, b2)) return true;
@@ -1910,9 +1910,9 @@ function alphaEqTerm(a, b, bmap) {
1910
1910
  }
1911
1911
  return true;
1912
1912
  }
1913
- if (a instanceof FormulaTerm && b instanceof FormulaTerm) {
1913
+ if (a instanceof GraphTerm && b instanceof GraphTerm) {
1914
1914
  // formulas are alpha-equivalent up to var/blank renaming
1915
- return alphaEqFormulaTriples(a.triples, b.triples);
1915
+ return alphaEqGraphTriples(a.triples, b.triples);
1916
1916
  }
1917
1917
  return false;
1918
1918
  }
@@ -2220,30 +2220,30 @@ function containsVarTerm(t, v) {
2220
2220
  if (t instanceof Var) return t.name === v;
2221
2221
  if (t instanceof ListTerm) return t.elems.some((e) => containsVarTerm(e, v));
2222
2222
  if (t instanceof OpenListTerm) return t.prefix.some((e) => containsVarTerm(e, v)) || t.tailVar === v;
2223
- if (t instanceof FormulaTerm)
2223
+ if (t instanceof GraphTerm)
2224
2224
  return t.triples.some((tr) => containsVarTerm(tr.s, v) || containsVarTerm(tr.p, v) || containsVarTerm(tr.o, v));
2225
2225
  return false;
2226
2226
  }
2227
2227
 
2228
- function isGroundTermInFormula(t) {
2229
- // EYE-style: variables inside formula terms are treated as local placeholders,
2228
+ function isGroundTermInGraph(t) {
2229
+ // variables inside graph terms are treated as local placeholders,
2230
2230
  // so they don't make the *surrounding triple* non-ground.
2231
2231
  if (t instanceof OpenListTerm) return false;
2232
- if (t instanceof ListTerm) return t.elems.every((e) => isGroundTermInFormula(e));
2233
- if (t instanceof FormulaTerm) return t.triples.every((tr) => isGroundTripleInFormula(tr));
2232
+ if (t instanceof ListTerm) return t.elems.every((e) => isGroundTermInGraph(e));
2233
+ if (t instanceof GraphTerm) return t.triples.every((tr) => isGroundTripleInGraph(tr));
2234
2234
  // Iri/Literal/Blank/Var are all OK inside formulas
2235
2235
  return true;
2236
2236
  }
2237
2237
 
2238
- function isGroundTripleInFormula(tr) {
2239
- return isGroundTermInFormula(tr.s) && isGroundTermInFormula(tr.p) && isGroundTermInFormula(tr.o);
2238
+ function isGroundTripleInGraph(tr) {
2239
+ return isGroundTermInGraph(tr.s) && isGroundTermInGraph(tr.p) && isGroundTermInGraph(tr.o);
2240
2240
  }
2241
2241
 
2242
2242
  function isGroundTerm(t) {
2243
2243
  if (t instanceof Var) return false;
2244
2244
  if (t instanceof ListTerm) return t.elems.every((e) => isGroundTerm(e));
2245
2245
  if (t instanceof OpenListTerm) return false;
2246
- if (t instanceof FormulaTerm) return t.triples.every((tr) => isGroundTripleInFormula(tr));
2246
+ if (t instanceof GraphTerm) return t.triples.every((tr) => isGroundTripleInGraph(tr));
2247
2247
  return true;
2248
2248
  }
2249
2249
 
@@ -2262,7 +2262,7 @@ function skolemKeyFromTerm(t) {
2262
2262
  if (u instanceof Var) return ['V', u.name];
2263
2263
  if (u instanceof ListTerm) return ['List', u.elems.map(enc)];
2264
2264
  if (u instanceof OpenListTerm) return ['OpenList', u.prefix.map(enc), u.tailVar];
2265
- if (u instanceof FormulaTerm) return ['Formula', u.triples.map((tr) => [enc(tr.s), enc(tr.p), enc(tr.o)])];
2265
+ if (u instanceof GraphTerm) return ['Graph', u.triples.map((tr) => [enc(tr.s), enc(tr.p), enc(tr.o)])];
2266
2266
  return ['Other', String(u)];
2267
2267
  }
2268
2268
  return JSON.stringify(enc(t));
@@ -2320,8 +2320,8 @@ function applySubstTerm(t, s) {
2320
2320
  }
2321
2321
  }
2322
2322
 
2323
- if (t instanceof FormulaTerm) {
2324
- return new FormulaTerm(t.triples.map((tr) => applySubstTriple(tr, s)));
2323
+ if (t instanceof GraphTerm) {
2324
+ return new GraphTerm(t.triples.map((tr) => applySubstTriple(tr, s)));
2325
2325
  }
2326
2326
 
2327
2327
  return t;
@@ -2348,7 +2348,7 @@ function unifyOpenWithList(prefix, tailv, ys, subst) {
2348
2348
  return s2;
2349
2349
  }
2350
2350
 
2351
- function unifyFormulaTriples(xs, ys, subst) {
2351
+ function unifyGraphTriples(xs, ys, subst) {
2352
2352
  if (xs.length !== ys.length) return null;
2353
2353
 
2354
2354
  // Fast path: exact same sequence.
@@ -2490,10 +2490,10 @@ function unifyTermWithOptions(a, b, subst, opts) {
2490
2490
  return s2;
2491
2491
  }
2492
2492
 
2493
- // Formulas
2494
- if (a instanceof FormulaTerm && b instanceof FormulaTerm) {
2495
- if (alphaEqFormulaTriples(a.triples, b.triples)) return { ...subst };
2496
- return unifyFormulaTriples(a.triples, b.triples, subst);
2493
+ // Graphs
2494
+ if (a instanceof GraphTerm && b instanceof GraphTerm) {
2495
+ if (alphaEqGraphTriples(a.triples, b.triples)) return { ...subst };
2496
+ return unifyGraphTriples(a.triples, b.triples, subst);
2497
2497
  }
2498
2498
 
2499
2499
  return null;
@@ -3635,7 +3635,7 @@ function materializeRdfLists(triples, forwardRules, backwardRules) {
3635
3635
  });
3636
3636
  return changed ? new OpenListTerm(prefix, t.tailVar) : t;
3637
3637
  }
3638
- if (t instanceof FormulaTerm) {
3638
+ if (t instanceof GraphTerm) {
3639
3639
  for (const tr of t.triples) rewriteTriple(tr);
3640
3640
  return t;
3641
3641
  }
@@ -3701,6 +3701,13 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3701
3701
  const pv = iriValue(g.p);
3702
3702
  if (pv === null) return null;
3703
3703
 
3704
+ // Super restricted mode: disable *all* builtins except => / <= (log:implies / log:impliedBy)
3705
+ if (superRestrictedMode) {
3706
+ const allow1 = LOG_NS + 'implies';
3707
+ const allow2 = LOG_NS + 'impliedBy';
3708
+ if (pv !== allow1 && pv !== allow2) return [];
3709
+ }
3710
+
3704
3711
  // -----------------------------------------------------------------
3705
3712
  // 4.1 crypto: builtins
3706
3713
  // -----------------------------------------------------------------
@@ -4726,8 +4733,8 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4726
4733
  // fresh copy of the rule with fresh variable names
4727
4734
  const r = standardizeRule(r0, varGen);
4728
4735
 
4729
- const premF = new FormulaTerm(r.premise);
4730
- const concTerm = r0.isFuse ? internLiteral('false') : new FormulaTerm(r.conclusion);
4736
+ const premF = new GraphTerm(r.premise);
4737
+ const concTerm = r0.isFuse ? internLiteral('false') : new GraphTerm(r.conclusion);
4731
4738
 
4732
4739
  // unify subject with the premise formula
4733
4740
  let s2 = unifyTerm(goal.s, premF, subst);
@@ -4755,8 +4762,8 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4755
4762
  const r = standardizeRule(r0, varGen);
4756
4763
 
4757
4764
  // For backward rules, r.conclusion is the head, r.premise is the body
4758
- const headF = new FormulaTerm(r.conclusion);
4759
- const bodyF = new FormulaTerm(r.premise);
4765
+ const headF = new GraphTerm(r.conclusion);
4766
+ const bodyF = new GraphTerm(r.premise);
4760
4767
 
4761
4768
  // unify subject with the head formula
4762
4769
  let s2 = unifyTerm(goal.s, headF, subst);
@@ -4772,16 +4779,16 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4772
4779
  return results;
4773
4780
  }
4774
4781
 
4775
- // log:notIncludes (EYE-style: "not provable in scope")
4782
+ // log:notIncludes (not provable in scope)
4776
4783
  // Delay until we have a frozen scope snapshot to avoid early success.
4777
4784
  if (pv === LOG_NS + 'notIncludes') {
4778
- if (!(g.o instanceof FormulaTerm)) return [];
4785
+ if (!(g.o instanceof GraphTerm)) return [];
4779
4786
 
4780
4787
  let scopeFacts = null;
4781
4788
  let scopeBackRules = backRules;
4782
4789
 
4783
4790
  // If the subject is a formula, treat it as the concrete scope graph
4784
- if (g.s instanceof FormulaTerm) {
4791
+ if (g.s instanceof GraphTerm) {
4785
4792
  scopeFacts = g.s.triples.slice();
4786
4793
  ensureFactIndexes(scopeFacts);
4787
4794
  Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
@@ -4800,12 +4807,12 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4800
4807
  if (pv === LOG_NS + 'collectAllIn') {
4801
4808
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 3) return [];
4802
4809
  const [valueTempl, clauseTerm, listTerm] = g.s.elems;
4803
- if (!(clauseTerm instanceof FormulaTerm)) return [];
4810
+ if (!(clauseTerm instanceof GraphTerm)) return [];
4804
4811
 
4805
4812
  let scopeFacts = null;
4806
4813
  let scopeBackRules = backRules;
4807
4814
 
4808
- if (g.o instanceof FormulaTerm) {
4815
+ if (g.o instanceof GraphTerm) {
4809
4816
  scopeFacts = g.o.triples.slice();
4810
4817
  ensureFactIndexes(scopeFacts);
4811
4818
  Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
@@ -4829,12 +4836,12 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4829
4836
  if (pv === LOG_NS + 'forAllIn') {
4830
4837
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
4831
4838
  const [whereClause, thenClause] = g.s.elems;
4832
- if (!(whereClause instanceof FormulaTerm) || !(thenClause instanceof FormulaTerm)) return [];
4839
+ if (!(whereClause instanceof GraphTerm) || !(thenClause instanceof GraphTerm)) return [];
4833
4840
 
4834
4841
  let scopeFacts = null;
4835
4842
  let scopeBackRules = backRules;
4836
4843
 
4837
- if (g.o instanceof FormulaTerm) {
4844
+ if (g.o instanceof GraphTerm) {
4838
4845
  scopeFacts = g.o.triples.slice();
4839
4846
  ensureFactIndexes(scopeFacts);
4840
4847
  Object.defineProperty(scopeFacts, '__scopedSnapshot', { value: scopeFacts, enumerable: false, writable: true });
@@ -5120,6 +5127,13 @@ function isBuiltinPred(p) {
5120
5127
  if (!(p instanceof Iri)) return false;
5121
5128
  const v = p.value;
5122
5129
 
5130
+ // Super restricted mode: only treat => / <= as builtins.
5131
+ // Everything else should be handled as ordinary predicates (and thus must be
5132
+ // provided explicitly as facts/rules, without builtin evaluation).
5133
+ if (superRestrictedMode) {
5134
+ return v === LOG_NS + 'implies' || v === LOG_NS + 'impliedBy';
5135
+ }
5136
+
5123
5137
  // Treat RDF Collections as list-term builtins too.
5124
5138
  if (v === RDF_NS + 'first' || v === RDF_NS + 'rest') {
5125
5139
  return true;
@@ -5174,7 +5188,7 @@ function standardizeRule(rule, gen) {
5174
5188
  if (newTail !== t.tailVar) changed = true;
5175
5189
  return changed ? new OpenListTerm(newXs, newTail) : t;
5176
5190
  }
5177
- if (t instanceof FormulaTerm) {
5191
+ if (t instanceof GraphTerm) {
5178
5192
  let changed = false;
5179
5193
  const triples2 = t.triples.map((tr) => {
5180
5194
  const s2 = renameTerm(tr.s, vmap, genArr);
@@ -5183,7 +5197,7 @@ function standardizeRule(rule, gen) {
5183
5197
  if (s2 !== tr.s || p2 !== tr.p || o2 !== tr.o) changed = true;
5184
5198
  return s2 === tr.s && p2 === tr.p && o2 === tr.o ? tr : new Triple(s2, p2, o2);
5185
5199
  });
5186
- return changed ? new FormulaTerm(triples2) : t;
5200
+ return changed ? new GraphTerm(triples2) : t;
5187
5201
  }
5188
5202
  return t;
5189
5203
  }
@@ -5238,7 +5252,7 @@ function gcCollectVarsInTerm(t, out) {
5238
5252
  out.add(t.tailVar);
5239
5253
  return;
5240
5254
  }
5241
- if (t instanceof FormulaTerm) {
5255
+ if (t instanceof GraphTerm) {
5242
5256
  for (const tr of t.triples) gcCollectVarsInTriple(tr, out);
5243
5257
  return;
5244
5258
  }
@@ -5500,15 +5514,15 @@ function forwardChain(facts, forwardRules, backRules) {
5500
5514
 
5501
5515
  const isFwRuleTriple =
5502
5516
  isLogImplies(instantiated.p) &&
5503
- ((instantiated.s instanceof FormulaTerm && instantiated.o instanceof FormulaTerm) ||
5504
- (instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof FormulaTerm) ||
5505
- (instantiated.s instanceof FormulaTerm && instantiated.o instanceof Literal && instantiated.o.value === 'true'));
5517
+ ((instantiated.s instanceof GraphTerm && instantiated.o instanceof GraphTerm) ||
5518
+ (instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof GraphTerm) ||
5519
+ (instantiated.s instanceof GraphTerm && instantiated.o instanceof Literal && instantiated.o.value === 'true'));
5506
5520
 
5507
5521
  const isBwRuleTriple =
5508
5522
  isLogImpliedBy(instantiated.p) &&
5509
- ((instantiated.s instanceof FormulaTerm && instantiated.o instanceof FormulaTerm) ||
5510
- (instantiated.s instanceof FormulaTerm && instantiated.o instanceof Literal && instantiated.o.value === 'true') ||
5511
- (instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof FormulaTerm));
5523
+ ((instantiated.s instanceof GraphTerm && instantiated.o instanceof GraphTerm) ||
5524
+ (instantiated.s instanceof GraphTerm && instantiated.o instanceof Literal && instantiated.o.value === 'true') ||
5525
+ (instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof GraphTerm));
5512
5526
 
5513
5527
  if (isFwRuleTriple || isBwRuleTriple) {
5514
5528
  if (!hasFactIndexed(facts, instantiated)) {
@@ -5520,14 +5534,14 @@ function forwardChain(facts, forwardRules, backRules) {
5520
5534
 
5521
5535
  // Promote rule-producing triples to live rules, treating literal true as {}.
5522
5536
  const left =
5523
- instantiated.s instanceof FormulaTerm
5537
+ instantiated.s instanceof GraphTerm
5524
5538
  ? instantiated.s.triples
5525
5539
  : instantiated.s instanceof Literal && instantiated.s.value === 'true'
5526
5540
  ? []
5527
5541
  : null;
5528
5542
 
5529
5543
  const right =
5530
- instantiated.o instanceof FormulaTerm
5544
+ instantiated.o instanceof GraphTerm
5531
5545
  ? instantiated.o.triples
5532
5546
  : instantiated.o instanceof Literal && instantiated.o.value === 'true'
5533
5547
  ? []
@@ -5651,7 +5665,7 @@ function termToN3(t, pref) {
5651
5665
  inside.push('?' + t.tailVar);
5652
5666
  return '(' + inside.join(' ') + ')';
5653
5667
  }
5654
- if (t instanceof FormulaTerm) {
5668
+ if (t instanceof GraphTerm) {
5655
5669
  let s = '{\n';
5656
5670
  for (const tr of t.triples) {
5657
5671
  let line = tripleToN3(tr, pref).trimEnd();
@@ -5786,7 +5800,9 @@ function printExplanation(df, prefixes) {
5786
5800
  function main() {
5787
5801
  // Drop "node" and script name; keep only user-provided args
5788
5802
  const argv = process.argv.slice(2);
5789
- const prog = String(process.argv[1] || 'eyeling').split(/[\/]/).pop();
5803
+ const prog = String(process.argv[1] || 'eyeling')
5804
+ .split(/[\/]/)
5805
+ .pop();
5790
5806
 
5791
5807
  function printHelp(toStderr = false) {
5792
5808
  const msg =
@@ -5796,16 +5812,16 @@ function main() {
5796
5812
  ` -v, --version Print version and exit.\n` +
5797
5813
  ` -p, --proof-comments Enable proof explanations.\n` +
5798
5814
  ` -n, --no-proof-comments Disable proof explanations (default).\n` +
5815
+ ` -s, --super-restricted Disable all builtins except => and <=.\n` +
5799
5816
  ` -a, --ast Print parsed AST as JSON and exit.\n`;
5800
5817
  (toStderr ? console.error : console.log)(msg);
5801
5818
  }
5802
5819
 
5803
-
5804
5820
  // --------------------------------------------------------------------------
5805
5821
  // Global options
5806
5822
  // --------------------------------------------------------------------------
5807
5823
  // --help / -h: print help and exit
5808
- if (argv.includes('--help') || argv.includes('-h')) {
5824
+ if (argv.includes('--help') || argv.includes('-h')) {
5809
5825
  printHelp(false);
5810
5826
  process.exit(0);
5811
5827
  }
@@ -5818,7 +5834,6 @@ function main() {
5818
5834
 
5819
5835
  const showAst = argv.includes('--ast') || argv.includes('-a');
5820
5836
 
5821
-
5822
5837
  // --proof-comments / -p: enable proof explanations
5823
5838
  if (argv.includes('--proof-comments') || argv.includes('-p')) {
5824
5839
  proofCommentsEnabled = true;
@@ -5830,10 +5845,15 @@ function main() {
5830
5845
  proofCommentsEnabled = false;
5831
5846
  }
5832
5847
 
5848
+ // --super-restricted / -s: disable all builtins except => / <=
5849
+ if (argv.includes('--super-restricted') || argv.includes('-s')) {
5850
+ superRestrictedMode = true;
5851
+ }
5852
+
5833
5853
  // --------------------------------------------------------------------------
5834
5854
  // Positional args (the N3 file)
5835
5855
  // --------------------------------------------------------------------------
5836
- const positional = argv.filter((a) => !a.startsWith('-'));
5856
+ const positional = argv.filter((a) => !a.startsWith('-'));
5837
5857
  if (positional.length === 0) {
5838
5858
  // No args: show help like many CLI tools do.
5839
5859
  printHelp(false);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.6.32",
3
+ "version": "1.7.0",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [