eyeling 1.26.0 → 1.26.1
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/dist/browser/eyeling.browser.js +251 -317
- package/examples/proof/age.n3 +14 -5
- package/examples/proof/socrates.n3 +7 -2
- package/examples/proof/witch.n3 +27 -9
- package/eyeling.js +251 -317
- package/lib/cli.js +2 -2
- package/lib/engine.js +134 -219
- package/lib/explain.js +98 -79
- package/lib/multisource.js +17 -17
- package/package.json +1 -1
|
@@ -4826,8 +4826,8 @@ function main() {
|
|
|
4826
4826
|
baseIri: __sourceLabelToBaseIri(sourceLabel),
|
|
4827
4827
|
label: sourceLabel,
|
|
4828
4828
|
collectUsedPrefixes: streamMode,
|
|
4829
|
-
collectSourceLocations: engine.getProofCommentsEnabled(),
|
|
4830
4829
|
keepSourceArtifacts: false,
|
|
4830
|
+
sourceLocations: engine.getProofCommentsEnabled(),
|
|
4831
4831
|
rdf: rdfMode,
|
|
4832
4832
|
}),
|
|
4833
4833
|
);
|
|
@@ -4983,7 +4983,7 @@ function main() {
|
|
|
4983
4983
|
}
|
|
4984
4984
|
|
|
4985
4985
|
if (engine.getProofCommentsEnabled()) {
|
|
4986
|
-
process.stdout.write(engine.renderProofDocument(outDerived, derived, triples, prefixes, brules));
|
|
4986
|
+
process.stdout.write(engine.renderProofDocument(outDerived, derived.concat(outDerived || []), triples, prefixes, brules));
|
|
4987
4987
|
return;
|
|
4988
4988
|
}
|
|
4989
4989
|
|
|
@@ -5520,6 +5520,7 @@ const {
|
|
|
5520
5520
|
Triple,
|
|
5521
5521
|
Rule,
|
|
5522
5522
|
DerivedFact,
|
|
5523
|
+
varsInRule,
|
|
5523
5524
|
internIri,
|
|
5524
5525
|
collectBlankLabelsInTriples,
|
|
5525
5526
|
copyQuotedGraphMetadata,
|
|
@@ -5537,7 +5538,7 @@ const EMPTY_LIST_TERM = new ListTerm([]);
|
|
|
5537
5538
|
const { lex, N3SyntaxError } = require('./lexer');
|
|
5538
5539
|
const { Parser } = require('./parser');
|
|
5539
5540
|
const { liftBlankRuleVars } = require('./rules');
|
|
5540
|
-
const { parseN3SourceList } = require('./multisource');
|
|
5541
|
+
const { parseN3Text, parseN3SourceList } = require('./multisource');
|
|
5541
5542
|
|
|
5542
5543
|
const {
|
|
5543
5544
|
makeBuiltins,
|
|
@@ -7930,217 +7931,6 @@ function unifyTriple(pat, fact, subst) {
|
|
|
7930
7931
|
return s3;
|
|
7931
7932
|
}
|
|
7932
7933
|
|
|
7933
|
-
|
|
7934
|
-
function __copyProofSourceMetadata(from, to) {
|
|
7935
|
-
if (!from || !to) return to;
|
|
7936
|
-
for (const key of ['__sourceOffset', '__source']) {
|
|
7937
|
-
if (hasOwn.call(from, key)) {
|
|
7938
|
-
Object.defineProperty(to, key, {
|
|
7939
|
-
value: from[key],
|
|
7940
|
-
enumerable: false,
|
|
7941
|
-
writable: false,
|
|
7942
|
-
configurable: true,
|
|
7943
|
-
});
|
|
7944
|
-
}
|
|
7945
|
-
}
|
|
7946
|
-
return to;
|
|
7947
|
-
}
|
|
7948
|
-
|
|
7949
|
-
function __standardizeRuleForProof(rule, gen) {
|
|
7950
|
-
const proofVarNames = Object.create(null);
|
|
7951
|
-
|
|
7952
|
-
function renameTerm(t, vmapName, vmapVar, genArr) {
|
|
7953
|
-
if (t instanceof Var) {
|
|
7954
|
-
if (!hasOwn.call(vmapVar, t.name)) {
|
|
7955
|
-
const name = `${t.name}__proof_${genArr[0]}`;
|
|
7956
|
-
genArr[0] += 1;
|
|
7957
|
-
vmapName[t.name] = name;
|
|
7958
|
-
vmapVar[t.name] = new Var(name);
|
|
7959
|
-
proofVarNames[name] = t.name;
|
|
7960
|
-
}
|
|
7961
|
-
return vmapVar[t.name];
|
|
7962
|
-
}
|
|
7963
|
-
if (t instanceof ListTerm) {
|
|
7964
|
-
let changed = false;
|
|
7965
|
-
const elems2 = t.elems.map((e) => {
|
|
7966
|
-
const e2 = renameTerm(e, vmapName, vmapVar, genArr);
|
|
7967
|
-
if (e2 !== e) changed = true;
|
|
7968
|
-
return e2;
|
|
7969
|
-
});
|
|
7970
|
-
return changed ? new ListTerm(elems2) : t;
|
|
7971
|
-
}
|
|
7972
|
-
if (t instanceof OpenListTerm) {
|
|
7973
|
-
let changed = false;
|
|
7974
|
-
const newXs = t.prefix.map((e) => {
|
|
7975
|
-
const e2 = renameTerm(e, vmapName, vmapVar, genArr);
|
|
7976
|
-
if (e2 !== e) changed = true;
|
|
7977
|
-
return e2;
|
|
7978
|
-
});
|
|
7979
|
-
if (!hasOwn.call(vmapName, t.tailVar)) {
|
|
7980
|
-
const name = `${t.tailVar}__proof_${genArr[0]}`;
|
|
7981
|
-
genArr[0] += 1;
|
|
7982
|
-
vmapName[t.tailVar] = name;
|
|
7983
|
-
vmapVar[t.tailVar] = new Var(name);
|
|
7984
|
-
proofVarNames[name] = t.tailVar;
|
|
7985
|
-
}
|
|
7986
|
-
const newTail = vmapName[t.tailVar];
|
|
7987
|
-
if (newTail !== t.tailVar) changed = true;
|
|
7988
|
-
return changed ? new OpenListTerm(newXs, newTail) : t;
|
|
7989
|
-
}
|
|
7990
|
-
if (t instanceof GraphTerm) {
|
|
7991
|
-
let changed = false;
|
|
7992
|
-
const triples2 = t.triples.map((tr) => {
|
|
7993
|
-
const s2 = renameTerm(tr.s, vmapName, vmapVar, genArr);
|
|
7994
|
-
const p2 = renameTerm(tr.p, vmapName, vmapVar, genArr);
|
|
7995
|
-
const o2 = renameTerm(tr.o, vmapName, vmapVar, genArr);
|
|
7996
|
-
if (s2 !== tr.s || p2 !== tr.p || o2 !== tr.o) changed = true;
|
|
7997
|
-
return s2 === tr.s && p2 === tr.p && o2 === tr.o ? tr : new Triple(s2, p2, o2);
|
|
7998
|
-
});
|
|
7999
|
-
return changed ? copyQuotedGraphMetadata(t, new GraphTerm(triples2)) : t;
|
|
8000
|
-
}
|
|
8001
|
-
return t;
|
|
8002
|
-
}
|
|
8003
|
-
|
|
8004
|
-
const vmapName = Object.create(null);
|
|
8005
|
-
const vmapVar = Object.create(null);
|
|
8006
|
-
const premise = rule.premise.map((tr) => {
|
|
8007
|
-
const s2 = renameTerm(tr.s, vmapName, vmapVar, gen);
|
|
8008
|
-
const p2 = renameTerm(tr.p, vmapName, vmapVar, gen);
|
|
8009
|
-
const o2 = renameTerm(tr.o, vmapName, vmapVar, gen);
|
|
8010
|
-
return s2 === tr.s && p2 === tr.p && o2 === tr.o ? tr : new Triple(s2, p2, o2);
|
|
8011
|
-
});
|
|
8012
|
-
const conclusion = rule.conclusion.map((tr) => {
|
|
8013
|
-
const s2 = renameTerm(tr.s, vmapName, vmapVar, gen);
|
|
8014
|
-
const p2 = renameTerm(tr.p, vmapName, vmapVar, gen);
|
|
8015
|
-
const o2 = renameTerm(tr.o, vmapName, vmapVar, gen);
|
|
8016
|
-
return s2 === tr.s && p2 === tr.p && o2 === tr.o ? tr : new Triple(s2, p2, o2);
|
|
8017
|
-
});
|
|
8018
|
-
const out = new Rule(premise, conclusion, rule.isForward, rule.isFuse, rule.headBlankLabels);
|
|
8019
|
-
Object.defineProperty(out, '__proofVarSourceNames', {
|
|
8020
|
-
value: proofVarNames,
|
|
8021
|
-
enumerable: false,
|
|
8022
|
-
writable: false,
|
|
8023
|
-
configurable: true,
|
|
8024
|
-
});
|
|
8025
|
-
return __copyProofSourceMetadata(rule, out);
|
|
8026
|
-
}
|
|
8027
|
-
|
|
8028
|
-
function __mergeProofSubst(base, delta) {
|
|
8029
|
-
const out = __cloneSubst(base);
|
|
8030
|
-
for (const k in delta || {}) {
|
|
8031
|
-
if (!hasOwn.call(delta, k)) continue;
|
|
8032
|
-
const v = applySubstTerm(delta[k], out);
|
|
8033
|
-
if (hasOwn.call(out, k)) {
|
|
8034
|
-
if (!termsEqual(applySubstTerm(out[k], out), v)) return null;
|
|
8035
|
-
} else {
|
|
8036
|
-
out[k] = v;
|
|
8037
|
-
}
|
|
8038
|
-
}
|
|
8039
|
-
return out;
|
|
8040
|
-
}
|
|
8041
|
-
|
|
8042
|
-
function __sourceSortKey(obj) {
|
|
8043
|
-
const src = obj && obj.__source;
|
|
8044
|
-
const label = src && typeof src.label === 'string' ? src.label : '';
|
|
8045
|
-
const line = src && Number.isInteger(src.line) ? src.line : 0;
|
|
8046
|
-
return `${label}\t${line}`;
|
|
8047
|
-
}
|
|
8048
|
-
|
|
8049
|
-
function __candidateFactsForProof(facts, goal) {
|
|
8050
|
-
if (!Array.isArray(facts)) return [];
|
|
8051
|
-
ensureFactIndexes(facts);
|
|
8052
|
-
const candidates = candidateFacts(facts, goal);
|
|
8053
|
-
if (!candidates) return facts;
|
|
8054
|
-
const out = [];
|
|
8055
|
-
for (let i = 0; i < candidates.exactLen; i++) out.push(facts[candidates.exact[i]]);
|
|
8056
|
-
for (let i = 0; i < candidates.wildLen; i++) out.push(facts[candidates.wild[i]]);
|
|
8057
|
-
return out;
|
|
8058
|
-
}
|
|
8059
|
-
|
|
8060
|
-
function findBackwardProofForGoal(goal, facts, backRules, opts = {}) {
|
|
8061
|
-
const maxDepth = Number.isInteger(opts.maxDepth) && opts.maxDepth > 0 ? opts.maxDepth : 64;
|
|
8062
|
-
const varGen = [0];
|
|
8063
|
-
|
|
8064
|
-
function proofKey(tr) {
|
|
8065
|
-
return `${skolemKeyFromTerm(tr.s)}\t${skolemKeyFromTerm(tr.p)}\t${skolemKeyFromTerm(tr.o)}`;
|
|
8066
|
-
}
|
|
8067
|
-
|
|
8068
|
-
function proveGoal(goal0, subst, depth, visited) {
|
|
8069
|
-
if (depth > maxDepth) return [];
|
|
8070
|
-
const g = applySubstTriple(goal0, subst);
|
|
8071
|
-
const key = proofKey(g);
|
|
8072
|
-
if (visited.has(key)) return [];
|
|
8073
|
-
|
|
8074
|
-
if (isBuiltinPred(g.p)) {
|
|
8075
|
-
const builtinGoalForEval = g.p instanceof Iri && g.p.value === LOG_NS + 'rawType' ? goal0 : g;
|
|
8076
|
-
const builtinSubstForEval = g.p instanceof Iri && g.p.value === LOG_NS + 'rawType' ? subst : __emptySubst();
|
|
8077
|
-
const deltas = evalBuiltin(builtinGoalForEval, builtinSubstForEval, facts, backRules, depth, varGen, 1) || [];
|
|
8078
|
-
const out = [];
|
|
8079
|
-
for (const delta of deltas) {
|
|
8080
|
-
const subst2 = __mergeProofSubst(subst, delta);
|
|
8081
|
-
if (subst2 === null) continue;
|
|
8082
|
-
const fact = applySubstTriple(g, subst2);
|
|
8083
|
-
out.push({ subst: subst2, proof: { kind: 'builtin', fact, builtin: fact.p } });
|
|
8084
|
-
break;
|
|
8085
|
-
}
|
|
8086
|
-
return out;
|
|
8087
|
-
}
|
|
8088
|
-
|
|
8089
|
-
const factResults = [];
|
|
8090
|
-
for (const f of __candidateFactsForProof(facts, g)) {
|
|
8091
|
-
const subst2 = unifyTriple(g, f, subst);
|
|
8092
|
-
if (subst2 === null) continue;
|
|
8093
|
-
factResults.push({ subst: subst2, proof: { kind: 'fact', fact: applySubstTriple(f, subst2), source: f.__source } });
|
|
8094
|
-
break;
|
|
8095
|
-
}
|
|
8096
|
-
if (factResults.length) return factResults;
|
|
8097
|
-
|
|
8098
|
-
if (!(g.p instanceof Iri)) return [];
|
|
8099
|
-
ensureBackRuleIndexes(backRules);
|
|
8100
|
-
const rules = (backRules.__byHeadPred.get(g.p.__tid) || []).concat(backRules.__wildHeadPred || []);
|
|
8101
|
-
rules.sort((a, b) => (__sourceSortKey(a) < __sourceSortKey(b) ? -1 : __sourceSortKey(a) > __sourceSortKey(b) ? 1 : 0));
|
|
8102
|
-
|
|
8103
|
-
const visited2 = new Set(visited);
|
|
8104
|
-
visited2.add(key);
|
|
8105
|
-
|
|
8106
|
-
for (const r of rules) {
|
|
8107
|
-
if (!r || !Array.isArray(r.conclusion) || r.conclusion.length !== 1) continue;
|
|
8108
|
-
const rStd = __standardizeRuleForProof(r, varGen);
|
|
8109
|
-
const head = rStd.conclusion[0];
|
|
8110
|
-
if (head.p instanceof Iri && head.p.__tid !== g.p.__tid) continue;
|
|
8111
|
-
const subst1 = unifyTriple(head, g, subst);
|
|
8112
|
-
if (subst1 === null) continue;
|
|
8113
|
-
const bodyProof = proveGoalList(rStd.premise || [], subst1, depth + 1, visited2);
|
|
8114
|
-
if (!bodyProof) continue;
|
|
8115
|
-
const fact = applySubstTriple(g, bodyProof.subst);
|
|
8116
|
-
const premises = (rStd.premise || []).map((prem) => applySubstTriple(prem, bodyProof.subst));
|
|
8117
|
-
const df = new DerivedFact(fact, rStd, premises, bodyProof.subst);
|
|
8118
|
-
return [{ subst: bodyProof.subst, proof: { kind: 'rule', df, children: bodyProof.proofs } }];
|
|
8119
|
-
}
|
|
8120
|
-
|
|
8121
|
-
return [];
|
|
8122
|
-
}
|
|
8123
|
-
|
|
8124
|
-
function proveGoalList(goals, subst, depth, visited) {
|
|
8125
|
-
let states = [{ subst, proofs: [] }];
|
|
8126
|
-
for (const goal1 of goals || []) {
|
|
8127
|
-
const next = [];
|
|
8128
|
-
for (const state of states) {
|
|
8129
|
-
const proofs = proveGoal(goal1, state.subst, depth, visited);
|
|
8130
|
-
for (const pr of proofs) next.push({ subst: pr.subst, proofs: state.proofs.concat([pr.proof]) });
|
|
8131
|
-
}
|
|
8132
|
-
if (!next.length) return null;
|
|
8133
|
-
// Keep proof reconstruction deterministic and cheap: one proof is enough
|
|
8134
|
-
// for an explanation of the already-derived enclosing fact.
|
|
8135
|
-
states = [next[0]];
|
|
8136
|
-
}
|
|
8137
|
-
return states[0] || { subst, proofs: [] };
|
|
8138
|
-
}
|
|
8139
|
-
|
|
8140
|
-
const found = proveGoal(goal, __emptySubst(), 0, new Set());
|
|
8141
|
-
return found.length ? found[0].proof : null;
|
|
8142
|
-
}
|
|
8143
|
-
|
|
8144
7934
|
// Strategy: when the substitution is "large" or search depth is high,
|
|
8145
7935
|
// keep only bindings that are still relevant to:
|
|
8146
7936
|
// - variables appearing in the remaining goals
|
|
@@ -8862,6 +8652,120 @@ function proveGoals(goals, subst, facts, backRules, depth, visited, varGen, maxR
|
|
|
8862
8652
|
return results;
|
|
8863
8653
|
}
|
|
8864
8654
|
|
|
8655
|
+
|
|
8656
|
+
// Reconstruct one backward proof for N3 proof output. This is intentionally
|
|
8657
|
+
// called only by renderProofDocument(), so normal reasoning does not pay for it.
|
|
8658
|
+
function __proofTripleKey(tr) {
|
|
8659
|
+
if (!tr) return '';
|
|
8660
|
+
return `${skolemKeyFromTerm(tr.s)}\t${skolemKeyFromTerm(tr.p)}\t${skolemKeyFromTerm(tr.o)}`;
|
|
8661
|
+
}
|
|
8662
|
+
|
|
8663
|
+
function __copyProofSource(from, to) {
|
|
8664
|
+
if (from && to && Object.prototype.hasOwnProperty.call(from, '__source')) {
|
|
8665
|
+
Object.defineProperty(to, '__source', {
|
|
8666
|
+
value: from.__source,
|
|
8667
|
+
enumerable: false,
|
|
8668
|
+
writable: false,
|
|
8669
|
+
configurable: true,
|
|
8670
|
+
});
|
|
8671
|
+
}
|
|
8672
|
+
return to;
|
|
8673
|
+
}
|
|
8674
|
+
|
|
8675
|
+
function __annotateProofVarSourceNames(rule) {
|
|
8676
|
+
if (!rule) return rule;
|
|
8677
|
+
const sourceNames = Object.create(null);
|
|
8678
|
+
for (const name of varsInRule(rule)) {
|
|
8679
|
+
const m = /^(.*)__\d+$/.exec(name);
|
|
8680
|
+
sourceNames[name] = m ? m[1] : name;
|
|
8681
|
+
}
|
|
8682
|
+
Object.defineProperty(rule, '__proofVarSourceNames', {
|
|
8683
|
+
value: sourceNames,
|
|
8684
|
+
enumerable: false,
|
|
8685
|
+
writable: false,
|
|
8686
|
+
configurable: true,
|
|
8687
|
+
});
|
|
8688
|
+
return rule;
|
|
8689
|
+
}
|
|
8690
|
+
|
|
8691
|
+
function findBackwardProofForGoal(goal, facts, backRules, opts = {}) {
|
|
8692
|
+
const maxDepth = Number.isInteger(opts.maxDepth) && opts.maxDepth >= 0 ? opts.maxDepth : 64;
|
|
8693
|
+
const varGen = Array.isArray(opts.varGen) ? opts.varGen : [1];
|
|
8694
|
+
const visited = opts.visited instanceof Set ? opts.visited : new Set();
|
|
8695
|
+
const factList = Array.isArray(facts) ? facts : [];
|
|
8696
|
+
const ruleList = Array.isArray(backRules) ? backRules : [];
|
|
8697
|
+
|
|
8698
|
+
function matchingBaseFact(g) {
|
|
8699
|
+
const candidates = g && g.p instanceof Iri ? candidateFacts(factList, g) : null;
|
|
8700
|
+
const total = candidates ? candidates.totalLen : factList.length;
|
|
8701
|
+
for (let i = 0; i < total; i++) {
|
|
8702
|
+
let f;
|
|
8703
|
+
if (candidates) {
|
|
8704
|
+
if (i < candidates.exactLen) f = factList[candidates.exact[i]];
|
|
8705
|
+
else f = factList[candidates.wild[i - candidates.exactLen]];
|
|
8706
|
+
} else {
|
|
8707
|
+
f = factList[i];
|
|
8708
|
+
}
|
|
8709
|
+
if (unifyTriple(g, f, __emptySubst()) !== null) return f;
|
|
8710
|
+
}
|
|
8711
|
+
return null;
|
|
8712
|
+
}
|
|
8713
|
+
|
|
8714
|
+
function builtinProof(g) {
|
|
8715
|
+
if (!(g && isBuiltinPred(g.p))) return null;
|
|
8716
|
+
return { kind: 'builtin', fact: g, builtin: g.p };
|
|
8717
|
+
}
|
|
8718
|
+
|
|
8719
|
+
function solve(g, depth) {
|
|
8720
|
+
if (!g || depth > maxDepth) return null;
|
|
8721
|
+
|
|
8722
|
+
const base = matchingBaseFact(g);
|
|
8723
|
+
if (base) return { kind: 'fact', fact: base, source: base.__source };
|
|
8724
|
+
|
|
8725
|
+
const builtin = builtinProof(g);
|
|
8726
|
+
if (builtin) return builtin;
|
|
8727
|
+
|
|
8728
|
+
if (!(g.p instanceof Iri)) return null;
|
|
8729
|
+
const gKey = __proofTripleKey(g);
|
|
8730
|
+
if (visited.has(gKey)) return null;
|
|
8731
|
+
visited.add(gKey);
|
|
8732
|
+
|
|
8733
|
+
try {
|
|
8734
|
+
ensureBackRuleIndexes(ruleList);
|
|
8735
|
+
const candRules = (ruleList.__byHeadPred.get(g.p.__tid) || []).concat(ruleList.__wildHeadPred);
|
|
8736
|
+
for (const r of candRules) {
|
|
8737
|
+
if (!r || !Array.isArray(r.conclusion) || r.conclusion.length !== 1) continue;
|
|
8738
|
+
const rawHead = r.conclusion[0];
|
|
8739
|
+
if (rawHead.p instanceof Iri && rawHead.p.__tid !== g.p.__tid) continue;
|
|
8740
|
+
|
|
8741
|
+
const rStd = __annotateProofVarSourceNames(__copyProofSource(r, standardizeRule(r, varGen)));
|
|
8742
|
+
const head = rStd.conclusion[0];
|
|
8743
|
+
const s0 = unifyTriple(head, g, __emptySubst());
|
|
8744
|
+
if (s0 === null) continue;
|
|
8745
|
+
|
|
8746
|
+
const solutions = proveGoals(rStd.premise, s0, factList, ruleList, depth + 1, [], varGen, 1, {
|
|
8747
|
+
keepVars: varsInRule(rStd),
|
|
8748
|
+
deferBuiltins: true,
|
|
8749
|
+
});
|
|
8750
|
+
if (!solutions.length) continue;
|
|
8751
|
+
|
|
8752
|
+
const subst = solutions[0];
|
|
8753
|
+
const fact = applySubstTriple(head, subst);
|
|
8754
|
+
const premises = rStd.premise.map((prem) => applySubstTriple(prem, subst));
|
|
8755
|
+
const df = new DerivedFact(fact, rStd, premises, __cloneSubst(subst));
|
|
8756
|
+
const children = premises.map((prem) => builtinProof(prem) || solve(prem, depth + 1));
|
|
8757
|
+
return { kind: 'rule', df, children };
|
|
8758
|
+
}
|
|
8759
|
+
} finally {
|
|
8760
|
+
visited.delete(gKey);
|
|
8761
|
+
}
|
|
8762
|
+
|
|
8763
|
+
return null;
|
|
8764
|
+
}
|
|
8765
|
+
|
|
8766
|
+
return solve(goal, 0);
|
|
8767
|
+
}
|
|
8768
|
+
|
|
8865
8769
|
// ===========================================================================
|
|
8866
8770
|
// Forward chaining to fixpoint
|
|
8867
8771
|
// ===========================================================================
|
|
@@ -9547,7 +9451,7 @@ function reasonStream(input, opts = {}) {
|
|
|
9547
9451
|
|
|
9548
9452
|
const useRdfCompatibility = !!rdf;
|
|
9549
9453
|
|
|
9550
|
-
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility });
|
|
9454
|
+
const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility, sourceLocations: proof });
|
|
9551
9455
|
const parsedInput = parsedSourceList || normalizeParsedReasonerInputSync(input);
|
|
9552
9456
|
const rdfFactory = rdfjs ? getDataFactory(dataFactory) : null;
|
|
9553
9457
|
|
|
@@ -9583,11 +9487,22 @@ function reasonStream(input, opts = {}) {
|
|
|
9583
9487
|
if (baseIri) prefixes.setBase(baseIri);
|
|
9584
9488
|
} else {
|
|
9585
9489
|
const n3Text = normalizeReasonerInputSync(input);
|
|
9586
|
-
|
|
9587
|
-
|
|
9588
|
-
|
|
9490
|
+
if (proof) {
|
|
9491
|
+
const parsed = parseN3Text(n3Text, {
|
|
9492
|
+
label: 'input.n3',
|
|
9493
|
+
baseIri: baseIri || '',
|
|
9494
|
+
keepSourceArtifacts: false,
|
|
9495
|
+
sourceLocations: true,
|
|
9496
|
+
rdf: useRdfCompatibility,
|
|
9497
|
+
});
|
|
9498
|
+
({ prefixes, triples, frules, brules, logQueryRules } = parsed);
|
|
9499
|
+
} else {
|
|
9500
|
+
const toks = lex(n3Text, { rdf: useRdfCompatibility });
|
|
9501
|
+
const parser = new Parser(toks);
|
|
9502
|
+
if (baseIri) parser.prefixes.setBase(baseIri);
|
|
9589
9503
|
|
|
9590
|
-
|
|
9504
|
+
[prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
|
|
9505
|
+
}
|
|
9591
9506
|
}
|
|
9592
9507
|
// Make the parsed prefixes available to log:trace output
|
|
9593
9508
|
trace.setTracePrefixes(prefixes);
|
|
@@ -9658,7 +9573,7 @@ function reasonStream(input, opts = {}) {
|
|
|
9658
9573
|
const closureN3 = proof
|
|
9659
9574
|
? renderProofDocument(
|
|
9660
9575
|
Array.isArray(logQueryRules) && logQueryRules.length ? queryDerived : derived,
|
|
9661
|
-
derived,
|
|
9576
|
+
derived.concat(queryDerived || []),
|
|
9662
9577
|
triples,
|
|
9663
9578
|
prefixes,
|
|
9664
9579
|
brules,
|
|
@@ -9711,7 +9626,7 @@ function reasonRdfJs(input, opts = {}) {
|
|
|
9711
9626
|
|
|
9712
9627
|
Promise.resolve().then(async () => {
|
|
9713
9628
|
try {
|
|
9714
|
-
const normalizedInput = parseN3SourceList(input, restOpts) || (await normalizeReasonerInputAsync(input));
|
|
9629
|
+
const normalizedInput = parseN3SourceList(input, { ...restOpts, sourceLocations: !!(restOpts.proof || restOpts.proofComments) }) || (await normalizeReasonerInputAsync(input));
|
|
9715
9630
|
reasonStream(normalizedInput, {
|
|
9716
9631
|
...restOpts,
|
|
9717
9632
|
rdfjs: false,
|
|
@@ -10020,7 +9935,6 @@ ${lineIndent(body, ' ')}
|
|
|
10020
9935
|
}`;
|
|
10021
9936
|
}
|
|
10022
9937
|
|
|
10023
|
-
|
|
10024
9938
|
function clonePrefixEnvWithProofVocabulary(prefixes) {
|
|
10025
9939
|
const map = { ...(prefixes && prefixes.map ? prefixes.map : {}) };
|
|
10026
9940
|
if (!map.pe) map.pe = PE_NS;
|
|
@@ -10038,6 +9952,11 @@ ${lineIndent(body, ' ')}
|
|
|
10038
9952
|
return source.label.replace(/\\/g, '/').split('/').pop() || source.label;
|
|
10039
9953
|
}
|
|
10040
9954
|
|
|
9955
|
+
function sourceKeyForProof(source) {
|
|
9956
|
+
if (!source) return '<unknown>';
|
|
9957
|
+
return `${sourceLabelForProof(source)}:${Number.isInteger(source.line) ? source.line : ''}`;
|
|
9958
|
+
}
|
|
9959
|
+
|
|
10041
9960
|
function byBlankNode(kind, source) {
|
|
10042
9961
|
const src = source || {};
|
|
10043
9962
|
const props = [`pe:${kind} ${n3String(sourceLabelForProof(src))}`];
|
|
@@ -10045,121 +9964,129 @@ ${lineIndent(body, ' ')}
|
|
|
10045
9964
|
return `[ ${props.join('; ')} ]`;
|
|
10046
9965
|
}
|
|
10047
9966
|
|
|
10048
|
-
function
|
|
10049
|
-
if (!df || !df.rule || !df.subst) return
|
|
9967
|
+
function renderBindingItems(df, prefixes) {
|
|
9968
|
+
if (!df || !df.rule || !df.subst) return [];
|
|
10050
9969
|
const ruleVars = varsInRule(df.rule);
|
|
10051
9970
|
const visibleNames = Object.keys(df.subst)
|
|
10052
9971
|
.filter((name) => ruleVars.has(name))
|
|
10053
9972
|
.sort();
|
|
10054
|
-
if (!visibleNames.length) return
|
|
9973
|
+
if (!visibleNames.length) return [];
|
|
10055
9974
|
const sourceNames = (df.rule && df.rule.__proofVarSourceNames) || null;
|
|
10056
|
-
return visibleNames
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
|
|
10060
|
-
|
|
10061
|
-
})
|
|
10062
|
-
.join(', ');
|
|
9975
|
+
return visibleNames.map((name) => {
|
|
9976
|
+
const value = applySubstTerm(new Var(name), df.subst);
|
|
9977
|
+
const displayName = sourceNames && sourceNames[name] ? sourceNames[name] : name;
|
|
9978
|
+
return `[ pe:var ${n3String(displayName)}; pe:value ${termToN3(value, prefixes)} ]`;
|
|
9979
|
+
});
|
|
10063
9980
|
}
|
|
10064
9981
|
|
|
10065
|
-
function
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10069
|
-
return `${label}\t${line}`;
|
|
9982
|
+
function withLastLineSuffix(text, suffix) {
|
|
9983
|
+
const lines = String(text).split(/\r?\n/);
|
|
9984
|
+
lines[lines.length - 1] += suffix;
|
|
9985
|
+
return lines.join('\n');
|
|
10070
9986
|
}
|
|
10071
9987
|
|
|
10072
|
-
function
|
|
10073
|
-
|
|
9988
|
+
function renderPredicateObjects(predicate, objects, isLast) {
|
|
9989
|
+
const values = (objects || []).filter((value) => value);
|
|
9990
|
+
if (!values.length) return [];
|
|
9991
|
+
const end = isLast ? '.' : ';';
|
|
9992
|
+
if (values.length === 1 && !values[0].includes('\n')) {
|
|
9993
|
+
return [` ${predicate} ${values[0]}${end}`];
|
|
9994
|
+
}
|
|
9995
|
+
const out = [` ${predicate}`];
|
|
9996
|
+
for (let i = 0; i < values.length; i++) {
|
|
9997
|
+
const suffix = i === values.length - 1 ? end : ',';
|
|
9998
|
+
out.push(lineIndent(withLastLineSuffix(values[i], suffix), ' '));
|
|
9999
|
+
}
|
|
10000
|
+
return out;
|
|
10074
10001
|
}
|
|
10075
10002
|
|
|
10076
|
-
function
|
|
10077
|
-
|
|
10078
|
-
|
|
10079
|
-
|
|
10003
|
+
function proofEntryKey(entry) {
|
|
10004
|
+
if (!entry) return '';
|
|
10005
|
+
if (entry.kind === 'rule') {
|
|
10006
|
+
const df = entry.df;
|
|
10007
|
+
const source = df && df.rule && df.rule.__source;
|
|
10008
|
+
const premiseKey = (df && df.premises ? df.premises : []).map(proofTripleKey).join('|');
|
|
10009
|
+
return `rule:${proofTripleKey(df && df.fact)}:${sourceKeyForProof(source)}:${premiseKey}`;
|
|
10010
|
+
}
|
|
10011
|
+
if (entry.kind === 'builtin') return `builtin:${proofTripleKey(entry.fact)}`;
|
|
10012
|
+
return `fact:${proofTripleKey(entry.fact)}:${sourceKeyForProof(entry.source)}`;
|
|
10080
10013
|
}
|
|
10081
10014
|
|
|
10082
10015
|
function collectProofEntries(rootDf, derivedByKey, baseFactByKey, resolveBackwardProof) {
|
|
10083
10016
|
const entries = [];
|
|
10084
10017
|
const seen = new Set();
|
|
10085
10018
|
|
|
10086
|
-
function
|
|
10087
|
-
|
|
10088
|
-
if (
|
|
10089
|
-
|
|
10090
|
-
|
|
10019
|
+
function remember(entry) {
|
|
10020
|
+
const key = proofEntryKey(entry);
|
|
10021
|
+
if (!key || seen.has(key)) return false;
|
|
10022
|
+
seen.add(key);
|
|
10023
|
+
entries.push(entry);
|
|
10024
|
+
return true;
|
|
10025
|
+
}
|
|
10026
|
+
|
|
10027
|
+
function derivedCandidatesForKey(key) {
|
|
10028
|
+
const found = derivedByKey.get(key);
|
|
10029
|
+
if (!found) return [];
|
|
10030
|
+
return Array.isArray(found) ? found : [found];
|
|
10091
10031
|
}
|
|
10092
10032
|
|
|
10093
|
-
function visitProofNode(proof, fallbackTriple) {
|
|
10033
|
+
function visitProofNode(proof, fallbackTriple, parentDf) {
|
|
10094
10034
|
if (!proof) {
|
|
10095
|
-
visitFactTriple(fallbackTriple);
|
|
10035
|
+
visitFactTriple(fallbackTriple, parentDf);
|
|
10096
10036
|
return;
|
|
10097
10037
|
}
|
|
10098
|
-
const key = entryKeyForProof(proof, fallbackTriple);
|
|
10099
|
-
if (!key || seen.has(key)) return;
|
|
10100
10038
|
if (proof.kind === 'rule' && proof.df) {
|
|
10101
10039
|
visitDerivedFact(proof.df, proof.children || null);
|
|
10102
10040
|
return;
|
|
10103
10041
|
}
|
|
10104
|
-
seen.add(key);
|
|
10105
10042
|
if (proof.kind === 'builtin') {
|
|
10106
|
-
|
|
10107
|
-
|
|
10108
|
-
fact: proof.fact || fallbackTriple,
|
|
10109
|
-
builtin: proof.builtin || (proof.fact && proof.fact.p),
|
|
10110
|
-
});
|
|
10111
|
-
} else {
|
|
10112
|
-
entries.push({ kind: 'fact', fact: proof.fact || fallbackTriple, source: proof.source });
|
|
10043
|
+
remember({ kind: 'builtin', fact: proof.fact || fallbackTriple, builtin: proof.builtin || (proof.fact && proof.fact.p) });
|
|
10044
|
+
return;
|
|
10113
10045
|
}
|
|
10046
|
+
remember({ kind: 'fact', fact: proof.fact || fallbackTriple, source: proof.source });
|
|
10114
10047
|
}
|
|
10115
10048
|
|
|
10116
|
-
function visitFactTriple(tr) {
|
|
10117
|
-
const
|
|
10118
|
-
|
|
10119
|
-
|
|
10120
|
-
|
|
10121
|
-
visitDerivedFact(df);
|
|
10049
|
+
function visitFactTriple(tr, parentDf) {
|
|
10050
|
+
const key = proofTripleKey(tr);
|
|
10051
|
+
const base = baseFactByKey.get(key) || null;
|
|
10052
|
+
if (base) {
|
|
10053
|
+
remember({ kind: 'fact', fact: base, source: base.__source });
|
|
10122
10054
|
return;
|
|
10123
10055
|
}
|
|
10124
|
-
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
|
|
10128
|
-
|
|
10129
|
-
entries.push({ kind: 'fact', fact: base, source: base.__source });
|
|
10056
|
+
|
|
10057
|
+
const candidates = derivedCandidatesForKey(key);
|
|
10058
|
+
const df = candidates.find((candidate) => candidate !== parentDf) || null;
|
|
10059
|
+
if (df) {
|
|
10060
|
+
visitDerivedFact(df);
|
|
10130
10061
|
return;
|
|
10131
10062
|
}
|
|
10063
|
+
|
|
10132
10064
|
if (tr && isBuiltinPred(tr.p)) {
|
|
10133
|
-
|
|
10134
|
-
if (seen.has(key)) return;
|
|
10135
|
-
seen.add(key);
|
|
10136
|
-
entries.push({ kind: 'builtin', fact: tr, builtin: tr.p });
|
|
10065
|
+
remember({ kind: 'builtin', fact: tr, builtin: tr.p });
|
|
10137
10066
|
return;
|
|
10138
10067
|
}
|
|
10068
|
+
|
|
10139
10069
|
if (resolveBackwardProof) {
|
|
10140
10070
|
const proof = resolveBackwardProof(tr);
|
|
10141
10071
|
if (proof) {
|
|
10142
|
-
visitProofNode(proof, tr);
|
|
10072
|
+
visitProofNode(proof, tr, parentDf);
|
|
10143
10073
|
return;
|
|
10144
10074
|
}
|
|
10145
10075
|
}
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
seen.add(key);
|
|
10149
|
-
entries.push({ kind: 'fact', fact: tr, source: null });
|
|
10076
|
+
|
|
10077
|
+
remember({ kind: 'fact', fact: tr, source: null });
|
|
10150
10078
|
}
|
|
10151
10079
|
|
|
10152
10080
|
function visitDerivedFact(df, children) {
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
entries.push({ kind: 'rule', df });
|
|
10081
|
+
if (!df || !df.fact) return;
|
|
10082
|
+
const entry = { kind: 'rule', df };
|
|
10083
|
+
if (!remember(entry)) return;
|
|
10157
10084
|
|
|
10158
10085
|
if (Array.isArray(children) && children.length) {
|
|
10159
|
-
for (const child of children) visitProofNode(child);
|
|
10086
|
+
for (const child of children) visitProofNode(child, null, df);
|
|
10160
10087
|
return;
|
|
10161
10088
|
}
|
|
10162
|
-
for (const prem of df.premises || []) visitFactTriple(prem);
|
|
10089
|
+
for (const prem of df.premises || []) visitFactTriple(prem, df);
|
|
10163
10090
|
}
|
|
10164
10091
|
|
|
10165
10092
|
visitDerivedFact(rootDf);
|
|
@@ -10189,16 +10116,18 @@ ${lineIndent(body, ' ')}
|
|
|
10189
10116
|
}
|
|
10190
10117
|
|
|
10191
10118
|
const df = entry.df;
|
|
10192
|
-
const
|
|
10193
|
-
const
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10119
|
+
const bindingItems = renderBindingItems(df, prefixes);
|
|
10120
|
+
const useItems = (df.premises || []).map((prem) => graphForTriple(prem, prefixes));
|
|
10121
|
+
const propertyGroups = [
|
|
10122
|
+
{ predicate: 'pe:by', objects: [byBlankNode('rule', df.rule && df.rule.__source)] },
|
|
10123
|
+
{ predicate: 'pe:binding', objects: bindingItems },
|
|
10124
|
+
{ predicate: 'pe:uses', objects: useItems },
|
|
10125
|
+
].filter((group) => group.objects.length);
|
|
10198
10126
|
|
|
10199
10127
|
let out = ` ${graphForTriple(df.fact, prefixes)}\n`;
|
|
10200
|
-
for (let i = 0; i <
|
|
10201
|
-
|
|
10128
|
+
for (let i = 0; i < propertyGroups.length; i++) {
|
|
10129
|
+
const group = propertyGroups[i];
|
|
10130
|
+
out += renderPredicateObjects(group.predicate, group.objects, i === propertyGroups.length - 1).join('\n') + '\n';
|
|
10202
10131
|
}
|
|
10203
10132
|
return out.trimEnd();
|
|
10204
10133
|
}
|
|
@@ -10219,13 +10148,18 @@ ${proofBody}
|
|
|
10219
10148
|
|
|
10220
10149
|
const proofPrefixes = clonePrefixEnvWithProofVocabulary(prefixes);
|
|
10221
10150
|
const derivedByKey = new Map();
|
|
10222
|
-
|
|
10223
|
-
if (!df || !df.fact)
|
|
10151
|
+
function addDerived(df) {
|
|
10152
|
+
if (!df || !df.fact) return;
|
|
10224
10153
|
const key = proofTripleKey(df.fact);
|
|
10225
|
-
|
|
10154
|
+
let bucket = derivedByKey.get(key);
|
|
10155
|
+
if (!bucket) {
|
|
10156
|
+
bucket = [];
|
|
10157
|
+
derivedByKey.set(key, bucket);
|
|
10158
|
+
}
|
|
10159
|
+
if (!bucket.includes(df)) bucket.push(df);
|
|
10226
10160
|
}
|
|
10227
|
-
|
|
10228
|
-
|
|
10161
|
+
for (const df of allDerived || []) addDerived(df);
|
|
10162
|
+
for (const df of selectedDerived) addDerived(df);
|
|
10229
10163
|
|
|
10230
10164
|
const baseFactByKey = new Map();
|
|
10231
10165
|
for (const tr of baseFacts || []) {
|
|
@@ -12173,20 +12107,20 @@ function emptyParsedDocument() {
|
|
|
12173
12107
|
}
|
|
12174
12108
|
|
|
12175
12109
|
function lineStartsForText(text) {
|
|
12176
|
-
const s = String(text);
|
|
12177
12110
|
const starts = [0];
|
|
12178
|
-
|
|
12179
|
-
|
|
12180
|
-
|
|
12181
|
-
|
|
12182
|
-
|
|
12183
|
-
starts.push(i + 1);
|
|
12111
|
+
const str = String(text);
|
|
12112
|
+
for (let i = 0; i < str.length; i++) {
|
|
12113
|
+
const c = str[i];
|
|
12114
|
+
if (c === '\n') starts.push(i + 1);
|
|
12115
|
+
else if (c === '\r') {
|
|
12116
|
+
starts.push(i + 1 < str.length && str[i + 1] === '\n' ? i + 2 : i + 1);
|
|
12117
|
+
if (i + 1 < str.length && str[i + 1] === '\n') i++;
|
|
12184
12118
|
}
|
|
12185
12119
|
}
|
|
12186
12120
|
return starts;
|
|
12187
12121
|
}
|
|
12188
12122
|
|
|
12189
|
-
function
|
|
12123
|
+
function offsetToLine(lineStarts, offset) {
|
|
12190
12124
|
if (typeof offset !== 'number') return null;
|
|
12191
12125
|
let lo = 0;
|
|
12192
12126
|
let hi = lineStarts.length;
|
|
@@ -12198,9 +12132,9 @@ function offsetToLineFromStarts(offset, lineStarts) {
|
|
|
12198
12132
|
return lo + 1;
|
|
12199
12133
|
}
|
|
12200
12134
|
|
|
12201
|
-
function annotateSourceLocation(obj,
|
|
12135
|
+
function annotateSourceLocation(obj, lineStarts, label) {
|
|
12202
12136
|
if (!obj || typeof obj.__sourceOffset !== 'number') return obj;
|
|
12203
|
-
const line =
|
|
12137
|
+
const line = offsetToLine(lineStarts, obj.__sourceOffset);
|
|
12204
12138
|
Object.defineProperty(obj, '__source', {
|
|
12205
12139
|
value: { label, line },
|
|
12206
12140
|
enumerable: false,
|
|
@@ -12212,10 +12146,10 @@ function annotateSourceLocation(obj, label, lineStarts) {
|
|
|
12212
12146
|
|
|
12213
12147
|
function annotateParsedSourceLocations(doc, text, label) {
|
|
12214
12148
|
const lineStarts = lineStartsForText(text);
|
|
12215
|
-
for (const tr of doc.triples || []) annotateSourceLocation(tr,
|
|
12216
|
-
for (const r of doc.frules || []) annotateSourceLocation(r,
|
|
12217
|
-
for (const r of doc.brules || []) annotateSourceLocation(r,
|
|
12218
|
-
for (const r of doc.logQueryRules || []) annotateSourceLocation(r,
|
|
12149
|
+
for (const tr of doc.triples || []) annotateSourceLocation(tr, lineStarts, label);
|
|
12150
|
+
for (const r of doc.frules || []) annotateSourceLocation(r, lineStarts, label);
|
|
12151
|
+
for (const r of doc.brules || []) annotateSourceLocation(r, lineStarts, label);
|
|
12152
|
+
for (const r of doc.logQueryRules || []) annotateSourceLocation(r, lineStarts, label);
|
|
12219
12153
|
}
|
|
12220
12154
|
|
|
12221
12155
|
function copySourceMetadata(from, to) {
|
|
@@ -12310,7 +12244,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
12310
12244
|
label = '<input>',
|
|
12311
12245
|
keepSourceArtifacts = true,
|
|
12312
12246
|
collectUsedPrefixes = false,
|
|
12313
|
-
|
|
12247
|
+
sourceLocations = false,
|
|
12314
12248
|
rdf = false,
|
|
12315
12249
|
} = opts || {};
|
|
12316
12250
|
const tokens = lex(text, { rdf });
|
|
@@ -12319,7 +12253,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
12319
12253
|
const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
|
|
12320
12254
|
|
|
12321
12255
|
const doc = { prefixes, triples, frules, brules, logQueryRules, label };
|
|
12322
|
-
if (
|
|
12256
|
+
if (sourceLocations) annotateParsedSourceLocations(doc, text, label);
|
|
12323
12257
|
|
|
12324
12258
|
if (collectUsedPrefixes) {
|
|
12325
12259
|
Object.defineProperty(doc, 'usedPrefixes', {
|
|
@@ -12510,8 +12444,8 @@ function parseN3SourceList(input, opts = {}) {
|
|
|
12510
12444
|
label: source.label,
|
|
12511
12445
|
baseIri: source.baseIri || (sources.length === 1 ? defaultBaseIri : ''),
|
|
12512
12446
|
collectUsedPrefixes: true,
|
|
12513
|
-
collectSourceLocations: !!opts.collectSourceLocations,
|
|
12514
12447
|
keepSourceArtifacts: !!opts.keepSourceArtifacts,
|
|
12448
|
+
sourceLocations: !!opts.sourceLocations,
|
|
12515
12449
|
rdf: !!opts.rdf,
|
|
12516
12450
|
}),
|
|
12517
12451
|
);
|