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
package/lib/explain.js
CHANGED
|
@@ -135,7 +135,6 @@ ${lineIndent(body, ' ')}
|
|
|
135
135
|
}`;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
139
138
|
function clonePrefixEnvWithProofVocabulary(prefixes) {
|
|
140
139
|
const map = { ...(prefixes && prefixes.map ? prefixes.map : {}) };
|
|
141
140
|
if (!map.pe) map.pe = PE_NS;
|
|
@@ -153,6 +152,11 @@ ${lineIndent(body, ' ')}
|
|
|
153
152
|
return source.label.replace(/\\/g, '/').split('/').pop() || source.label;
|
|
154
153
|
}
|
|
155
154
|
|
|
155
|
+
function sourceKeyForProof(source) {
|
|
156
|
+
if (!source) return '<unknown>';
|
|
157
|
+
return `${sourceLabelForProof(source)}:${Number.isInteger(source.line) ? source.line : ''}`;
|
|
158
|
+
}
|
|
159
|
+
|
|
156
160
|
function byBlankNode(kind, source) {
|
|
157
161
|
const src = source || {};
|
|
158
162
|
const props = [`pe:${kind} ${n3String(sourceLabelForProof(src))}`];
|
|
@@ -160,121 +164,129 @@ ${lineIndent(body, ' ')}
|
|
|
160
164
|
return `[ ${props.join('; ')} ]`;
|
|
161
165
|
}
|
|
162
166
|
|
|
163
|
-
function
|
|
164
|
-
if (!df || !df.rule || !df.subst) return
|
|
167
|
+
function renderBindingItems(df, prefixes) {
|
|
168
|
+
if (!df || !df.rule || !df.subst) return [];
|
|
165
169
|
const ruleVars = varsInRule(df.rule);
|
|
166
170
|
const visibleNames = Object.keys(df.subst)
|
|
167
171
|
.filter((name) => ruleVars.has(name))
|
|
168
172
|
.sort();
|
|
169
|
-
if (!visibleNames.length) return
|
|
173
|
+
if (!visibleNames.length) return [];
|
|
170
174
|
const sourceNames = (df.rule && df.rule.__proofVarSourceNames) || null;
|
|
171
|
-
return visibleNames
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
})
|
|
177
|
-
.join(', ');
|
|
175
|
+
return visibleNames.map((name) => {
|
|
176
|
+
const value = applySubstTerm(new Var(name), df.subst);
|
|
177
|
+
const displayName = sourceNames && sourceNames[name] ? sourceNames[name] : name;
|
|
178
|
+
return `[ pe:var ${n3String(displayName)}; pe:value ${termToN3(value, prefixes)} ]`;
|
|
179
|
+
});
|
|
178
180
|
}
|
|
179
181
|
|
|
180
|
-
function
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
return `${label}\t${line}`;
|
|
182
|
+
function withLastLineSuffix(text, suffix) {
|
|
183
|
+
const lines = String(text).split(/\r?\n/);
|
|
184
|
+
lines[lines.length - 1] += suffix;
|
|
185
|
+
return lines.join('\n');
|
|
185
186
|
}
|
|
186
187
|
|
|
187
|
-
function
|
|
188
|
-
|
|
188
|
+
function renderPredicateObjects(predicate, objects, isLast) {
|
|
189
|
+
const values = (objects || []).filter((value) => value);
|
|
190
|
+
if (!values.length) return [];
|
|
191
|
+
const end = isLast ? '.' : ';';
|
|
192
|
+
if (values.length === 1 && !values[0].includes('\n')) {
|
|
193
|
+
return [` ${predicate} ${values[0]}${end}`];
|
|
194
|
+
}
|
|
195
|
+
const out = [` ${predicate}`];
|
|
196
|
+
for (let i = 0; i < values.length; i++) {
|
|
197
|
+
const suffix = i === values.length - 1 ? end : ',';
|
|
198
|
+
out.push(lineIndent(withLastLineSuffix(values[i], suffix), ' '));
|
|
199
|
+
}
|
|
200
|
+
return out;
|
|
189
201
|
}
|
|
190
202
|
|
|
191
|
-
function
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
function proofEntryKey(entry) {
|
|
204
|
+
if (!entry) return '';
|
|
205
|
+
if (entry.kind === 'rule') {
|
|
206
|
+
const df = entry.df;
|
|
207
|
+
const source = df && df.rule && df.rule.__source;
|
|
208
|
+
const premiseKey = (df && df.premises ? df.premises : []).map(proofTripleKey).join('|');
|
|
209
|
+
return `rule:${proofTripleKey(df && df.fact)}:${sourceKeyForProof(source)}:${premiseKey}`;
|
|
210
|
+
}
|
|
211
|
+
if (entry.kind === 'builtin') return `builtin:${proofTripleKey(entry.fact)}`;
|
|
212
|
+
return `fact:${proofTripleKey(entry.fact)}:${sourceKeyForProof(entry.source)}`;
|
|
195
213
|
}
|
|
196
214
|
|
|
197
215
|
function collectProofEntries(rootDf, derivedByKey, baseFactByKey, resolveBackwardProof) {
|
|
198
216
|
const entries = [];
|
|
199
217
|
const seen = new Set();
|
|
200
218
|
|
|
201
|
-
function
|
|
202
|
-
|
|
203
|
-
if (
|
|
204
|
-
|
|
205
|
-
|
|
219
|
+
function remember(entry) {
|
|
220
|
+
const key = proofEntryKey(entry);
|
|
221
|
+
if (!key || seen.has(key)) return false;
|
|
222
|
+
seen.add(key);
|
|
223
|
+
entries.push(entry);
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function derivedCandidatesForKey(key) {
|
|
228
|
+
const found = derivedByKey.get(key);
|
|
229
|
+
if (!found) return [];
|
|
230
|
+
return Array.isArray(found) ? found : [found];
|
|
206
231
|
}
|
|
207
232
|
|
|
208
|
-
function visitProofNode(proof, fallbackTriple) {
|
|
233
|
+
function visitProofNode(proof, fallbackTriple, parentDf) {
|
|
209
234
|
if (!proof) {
|
|
210
|
-
visitFactTriple(fallbackTriple);
|
|
235
|
+
visitFactTriple(fallbackTriple, parentDf);
|
|
211
236
|
return;
|
|
212
237
|
}
|
|
213
|
-
const key = entryKeyForProof(proof, fallbackTriple);
|
|
214
|
-
if (!key || seen.has(key)) return;
|
|
215
238
|
if (proof.kind === 'rule' && proof.df) {
|
|
216
239
|
visitDerivedFact(proof.df, proof.children || null);
|
|
217
240
|
return;
|
|
218
241
|
}
|
|
219
|
-
seen.add(key);
|
|
220
242
|
if (proof.kind === 'builtin') {
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
fact: proof.fact || fallbackTriple,
|
|
224
|
-
builtin: proof.builtin || (proof.fact && proof.fact.p),
|
|
225
|
-
});
|
|
226
|
-
} else {
|
|
227
|
-
entries.push({ kind: 'fact', fact: proof.fact || fallbackTriple, source: proof.source });
|
|
243
|
+
remember({ kind: 'builtin', fact: proof.fact || fallbackTriple, builtin: proof.builtin || (proof.fact && proof.fact.p) });
|
|
244
|
+
return;
|
|
228
245
|
}
|
|
246
|
+
remember({ kind: 'fact', fact: proof.fact || fallbackTriple, source: proof.source });
|
|
229
247
|
}
|
|
230
248
|
|
|
231
|
-
function visitFactTriple(tr) {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
visitDerivedFact(df);
|
|
249
|
+
function visitFactTriple(tr, parentDf) {
|
|
250
|
+
const key = proofTripleKey(tr);
|
|
251
|
+
const base = baseFactByKey.get(key) || null;
|
|
252
|
+
if (base) {
|
|
253
|
+
remember({ kind: 'fact', fact: base, source: base.__source });
|
|
237
254
|
return;
|
|
238
255
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
entries.push({ kind: 'fact', fact: base, source: base.__source });
|
|
256
|
+
|
|
257
|
+
const candidates = derivedCandidatesForKey(key);
|
|
258
|
+
const df = candidates.find((candidate) => candidate !== parentDf) || null;
|
|
259
|
+
if (df) {
|
|
260
|
+
visitDerivedFact(df);
|
|
245
261
|
return;
|
|
246
262
|
}
|
|
263
|
+
|
|
247
264
|
if (tr && isBuiltinPred(tr.p)) {
|
|
248
|
-
|
|
249
|
-
if (seen.has(key)) return;
|
|
250
|
-
seen.add(key);
|
|
251
|
-
entries.push({ kind: 'builtin', fact: tr, builtin: tr.p });
|
|
265
|
+
remember({ kind: 'builtin', fact: tr, builtin: tr.p });
|
|
252
266
|
return;
|
|
253
267
|
}
|
|
268
|
+
|
|
254
269
|
if (resolveBackwardProof) {
|
|
255
270
|
const proof = resolveBackwardProof(tr);
|
|
256
271
|
if (proof) {
|
|
257
|
-
visitProofNode(proof, tr);
|
|
272
|
+
visitProofNode(proof, tr, parentDf);
|
|
258
273
|
return;
|
|
259
274
|
}
|
|
260
275
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
seen.add(key);
|
|
264
|
-
entries.push({ kind: 'fact', fact: tr, source: null });
|
|
276
|
+
|
|
277
|
+
remember({ kind: 'fact', fact: tr, source: null });
|
|
265
278
|
}
|
|
266
279
|
|
|
267
280
|
function visitDerivedFact(df, children) {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
entries.push({ kind: 'rule', df });
|
|
281
|
+
if (!df || !df.fact) return;
|
|
282
|
+
const entry = { kind: 'rule', df };
|
|
283
|
+
if (!remember(entry)) return;
|
|
272
284
|
|
|
273
285
|
if (Array.isArray(children) && children.length) {
|
|
274
|
-
for (const child of children) visitProofNode(child);
|
|
286
|
+
for (const child of children) visitProofNode(child, null, df);
|
|
275
287
|
return;
|
|
276
288
|
}
|
|
277
|
-
for (const prem of df.premises || []) visitFactTriple(prem);
|
|
289
|
+
for (const prem of df.premises || []) visitFactTriple(prem, df);
|
|
278
290
|
}
|
|
279
291
|
|
|
280
292
|
visitDerivedFact(rootDf);
|
|
@@ -304,16 +316,18 @@ ${lineIndent(body, ' ')}
|
|
|
304
316
|
}
|
|
305
317
|
|
|
306
318
|
const df = entry.df;
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
319
|
+
const bindingItems = renderBindingItems(df, prefixes);
|
|
320
|
+
const useItems = (df.premises || []).map((prem) => graphForTriple(prem, prefixes));
|
|
321
|
+
const propertyGroups = [
|
|
322
|
+
{ predicate: 'pe:by', objects: [byBlankNode('rule', df.rule && df.rule.__source)] },
|
|
323
|
+
{ predicate: 'pe:binding', objects: bindingItems },
|
|
324
|
+
{ predicate: 'pe:uses', objects: useItems },
|
|
325
|
+
].filter((group) => group.objects.length);
|
|
313
326
|
|
|
314
327
|
let out = ` ${graphForTriple(df.fact, prefixes)}\n`;
|
|
315
|
-
for (let i = 0; i <
|
|
316
|
-
|
|
328
|
+
for (let i = 0; i < propertyGroups.length; i++) {
|
|
329
|
+
const group = propertyGroups[i];
|
|
330
|
+
out += renderPredicateObjects(group.predicate, group.objects, i === propertyGroups.length - 1).join('\n') + '\n';
|
|
317
331
|
}
|
|
318
332
|
return out.trimEnd();
|
|
319
333
|
}
|
|
@@ -334,13 +348,18 @@ ${proofBody}
|
|
|
334
348
|
|
|
335
349
|
const proofPrefixes = clonePrefixEnvWithProofVocabulary(prefixes);
|
|
336
350
|
const derivedByKey = new Map();
|
|
337
|
-
|
|
338
|
-
if (!df || !df.fact)
|
|
351
|
+
function addDerived(df) {
|
|
352
|
+
if (!df || !df.fact) return;
|
|
339
353
|
const key = proofTripleKey(df.fact);
|
|
340
|
-
|
|
354
|
+
let bucket = derivedByKey.get(key);
|
|
355
|
+
if (!bucket) {
|
|
356
|
+
bucket = [];
|
|
357
|
+
derivedByKey.set(key, bucket);
|
|
358
|
+
}
|
|
359
|
+
if (!bucket.includes(df)) bucket.push(df);
|
|
341
360
|
}
|
|
342
|
-
|
|
343
|
-
|
|
361
|
+
for (const df of allDerived || []) addDerived(df);
|
|
362
|
+
for (const df of selectedDerived) addDerived(df);
|
|
344
363
|
|
|
345
364
|
const baseFactByKey = new Map();
|
|
346
365
|
for (const tr of baseFacts || []) {
|
package/lib/multisource.js
CHANGED
|
@@ -32,20 +32,20 @@ function emptyParsedDocument() {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
function lineStartsForText(text) {
|
|
35
|
-
const s = String(text);
|
|
36
35
|
const starts = [0];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
starts.push(i + 1);
|
|
36
|
+
const str = String(text);
|
|
37
|
+
for (let i = 0; i < str.length; i++) {
|
|
38
|
+
const c = str[i];
|
|
39
|
+
if (c === '\n') starts.push(i + 1);
|
|
40
|
+
else if (c === '\r') {
|
|
41
|
+
starts.push(i + 1 < str.length && str[i + 1] === '\n' ? i + 2 : i + 1);
|
|
42
|
+
if (i + 1 < str.length && str[i + 1] === '\n') i++;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
return starts;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
function
|
|
48
|
+
function offsetToLine(lineStarts, offset) {
|
|
49
49
|
if (typeof offset !== 'number') return null;
|
|
50
50
|
let lo = 0;
|
|
51
51
|
let hi = lineStarts.length;
|
|
@@ -57,9 +57,9 @@ function offsetToLineFromStarts(offset, lineStarts) {
|
|
|
57
57
|
return lo + 1;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
function annotateSourceLocation(obj,
|
|
60
|
+
function annotateSourceLocation(obj, lineStarts, label) {
|
|
61
61
|
if (!obj || typeof obj.__sourceOffset !== 'number') return obj;
|
|
62
|
-
const line =
|
|
62
|
+
const line = offsetToLine(lineStarts, obj.__sourceOffset);
|
|
63
63
|
Object.defineProperty(obj, '__source', {
|
|
64
64
|
value: { label, line },
|
|
65
65
|
enumerable: false,
|
|
@@ -71,10 +71,10 @@ function annotateSourceLocation(obj, label, lineStarts) {
|
|
|
71
71
|
|
|
72
72
|
function annotateParsedSourceLocations(doc, text, label) {
|
|
73
73
|
const lineStarts = lineStartsForText(text);
|
|
74
|
-
for (const tr of doc.triples || []) annotateSourceLocation(tr,
|
|
75
|
-
for (const r of doc.frules || []) annotateSourceLocation(r,
|
|
76
|
-
for (const r of doc.brules || []) annotateSourceLocation(r,
|
|
77
|
-
for (const r of doc.logQueryRules || []) annotateSourceLocation(r,
|
|
74
|
+
for (const tr of doc.triples || []) annotateSourceLocation(tr, lineStarts, label);
|
|
75
|
+
for (const r of doc.frules || []) annotateSourceLocation(r, lineStarts, label);
|
|
76
|
+
for (const r of doc.brules || []) annotateSourceLocation(r, lineStarts, label);
|
|
77
|
+
for (const r of doc.logQueryRules || []) annotateSourceLocation(r, lineStarts, label);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
function copySourceMetadata(from, to) {
|
|
@@ -169,7 +169,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
169
169
|
label = '<input>',
|
|
170
170
|
keepSourceArtifacts = true,
|
|
171
171
|
collectUsedPrefixes = false,
|
|
172
|
-
|
|
172
|
+
sourceLocations = false,
|
|
173
173
|
rdf = false,
|
|
174
174
|
} = opts || {};
|
|
175
175
|
const tokens = lex(text, { rdf });
|
|
@@ -178,7 +178,7 @@ function parseN3Text(text, opts = {}) {
|
|
|
178
178
|
const [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
|
|
179
179
|
|
|
180
180
|
const doc = { prefixes, triples, frules, brules, logQueryRules, label };
|
|
181
|
-
if (
|
|
181
|
+
if (sourceLocations) annotateParsedSourceLocations(doc, text, label);
|
|
182
182
|
|
|
183
183
|
if (collectUsedPrefixes) {
|
|
184
184
|
Object.defineProperty(doc, 'usedPrefixes', {
|
|
@@ -369,8 +369,8 @@ function parseN3SourceList(input, opts = {}) {
|
|
|
369
369
|
label: source.label,
|
|
370
370
|
baseIri: source.baseIri || (sources.length === 1 ? defaultBaseIri : ''),
|
|
371
371
|
collectUsedPrefixes: true,
|
|
372
|
-
collectSourceLocations: !!opts.collectSourceLocations,
|
|
373
372
|
keepSourceArtifacts: !!opts.keepSourceArtifacts,
|
|
373
|
+
sourceLocations: !!opts.sourceLocations,
|
|
374
374
|
rdf: !!opts.rdf,
|
|
375
375
|
}),
|
|
376
376
|
);
|