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.
- package/examples/snaf.srl +7 -0
- package/eyeling.js +98 -78
- package/package.json +1 -1
package/eyeling.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
/*
|
|
5
|
-
* eyeling.js —
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
1639
|
-
return new
|
|
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
|
|
1711
|
-
return
|
|
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
|
|
1779
|
-
return
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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
|
|
1842
|
-
return
|
|
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
|
|
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
|
|
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 (!
|
|
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
|
|
1913
|
+
if (a instanceof GraphTerm && b instanceof GraphTerm) {
|
|
1914
1914
|
// formulas are alpha-equivalent up to var/blank renaming
|
|
1915
|
-
return
|
|
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
|
|
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
|
|
2229
|
-
//
|
|
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) =>
|
|
2233
|
-
if (t instanceof
|
|
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
|
|
2239
|
-
return
|
|
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
|
|
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
|
|
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
|
|
2324
|
-
return new
|
|
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
|
|
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
|
-
//
|
|
2494
|
-
if (a instanceof
|
|
2495
|
-
if (
|
|
2496
|
-
return
|
|
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
|
|
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
|
|
4730
|
-
const concTerm = r0.isFuse ? internLiteral('false') : new
|
|
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
|
|
4759
|
-
const bodyF = new
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
5504
|
-
(instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof
|
|
5505
|
-
(instantiated.s instanceof
|
|
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
|
|
5510
|
-
(instantiated.s instanceof
|
|
5511
|
-
(instantiated.s instanceof Literal && instantiated.s.value === 'true' && instantiated.o instanceof
|
|
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
|
|
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
|
|
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
|
|
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')
|
|
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
|
-
|
|
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
|
-
|
|
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);
|