eyeling 1.7.5 → 1.7.6
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/list-map.n3 +17 -0
- package/examples/log-conclusion.n3 +20 -0
- package/examples/output/list-map.n3 +6 -0
- package/examples/output/log-conclusion.n3 +13 -0
- package/eyeling.js +116 -2
- package/package.json +1 -1
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ========================================================
|
|
2
|
+
# List map
|
|
3
|
+
# behaves like the functional programming operator flatMap
|
|
4
|
+
# Examples from Giacomo Citi
|
|
5
|
+
# ========================================================
|
|
6
|
+
|
|
7
|
+
@prefix list: <http://www.w3.org/2000/10/swap/list#> .
|
|
8
|
+
@prefix : <http://example.org/#>.
|
|
9
|
+
|
|
10
|
+
:s1 :p1 :o1 .
|
|
11
|
+
:s2 :p1 :o2 .
|
|
12
|
+
:s3 :p1 :o3, :o4 .
|
|
13
|
+
|
|
14
|
+
{ ((:s1 :s2) :p1) list:map (:o1 :o2) } => { :test1 :is true } .
|
|
15
|
+
{ ((:s1 :s2 :s3) :p1) list:map (:o1 :o2 :o3 :o4) } => { :test2 :is true } .
|
|
16
|
+
{ ((:s4) :p1) list:map () } => { :test3 :is true } .
|
|
17
|
+
{ ((:s1) :p2) list:map () } => { :test4 :is true } .
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# ======================
|
|
2
|
+
# log:conclusion example
|
|
3
|
+
# ======================
|
|
4
|
+
|
|
5
|
+
@prefix : <http://example.org/>.
|
|
6
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
7
|
+
|
|
8
|
+
:let :param {
|
|
9
|
+
:Felix a :Cat .
|
|
10
|
+
{ ?X a :Cat . } => { ?X :says "Meow" . } .
|
|
11
|
+
} .
|
|
12
|
+
|
|
13
|
+
{
|
|
14
|
+
:let :param ?param .
|
|
15
|
+
?param log:conclusion ?conclusion .
|
|
16
|
+
}
|
|
17
|
+
=>
|
|
18
|
+
{
|
|
19
|
+
:result :is ?conclusion .
|
|
20
|
+
} .
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
@prefix : <http://example.org/> .
|
|
2
|
+
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
|
|
3
|
+
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
|
|
4
|
+
|
|
5
|
+
:result :is {
|
|
6
|
+
:Felix a :Cat .
|
|
7
|
+
{
|
|
8
|
+
?X a :Cat .
|
|
9
|
+
} => {
|
|
10
|
+
?X :says "Meow" .
|
|
11
|
+
} .
|
|
12
|
+
:Felix :says "Meow" .
|
|
13
|
+
} .
|
package/eyeling.js
CHANGED
|
@@ -89,6 +89,7 @@ const jsonPointerCache = new Map();
|
|
|
89
89
|
// Key is the dereferenced document IRI *without* fragment.
|
|
90
90
|
const __logContentCache = new Map(); // iri -> string | null (null means fetch/read failed)
|
|
91
91
|
const __logSemanticsCache = new Map(); // iri -> GraphTerm | null (null means parse failed)
|
|
92
|
+
const __logConclusionCache = new WeakMap(); // GraphTerm -> GraphTerm (deductive closure)
|
|
92
93
|
|
|
93
94
|
function __stripFragment(iri) {
|
|
94
95
|
const i = iri.indexOf('#');
|
|
@@ -233,6 +234,87 @@ function __derefSemanticsSync(iriNoFrag) {
|
|
|
233
234
|
return null;
|
|
234
235
|
}
|
|
235
236
|
}
|
|
237
|
+
function __makeRuleFromTerms(left, right, isForward) {
|
|
238
|
+
// Mirror Parser.makeRule, but usable at runtime (e.g., log:conclusion).
|
|
239
|
+
let premiseTerm, conclTerm;
|
|
240
|
+
|
|
241
|
+
if (isForward) {
|
|
242
|
+
premiseTerm = left;
|
|
243
|
+
conclTerm = right;
|
|
244
|
+
} else {
|
|
245
|
+
premiseTerm = right;
|
|
246
|
+
conclTerm = left;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
let isFuse = false;
|
|
250
|
+
if (isForward) {
|
|
251
|
+
if (conclTerm instanceof Literal && conclTerm.value === 'false') {
|
|
252
|
+
isFuse = true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let rawPremise;
|
|
257
|
+
if (premiseTerm instanceof GraphTerm) {
|
|
258
|
+
rawPremise = premiseTerm.triples;
|
|
259
|
+
} else if (premiseTerm instanceof Literal && premiseTerm.value === 'true') {
|
|
260
|
+
rawPremise = [];
|
|
261
|
+
} else {
|
|
262
|
+
rawPremise = [];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
let rawConclusion;
|
|
266
|
+
if (conclTerm instanceof GraphTerm) {
|
|
267
|
+
rawConclusion = conclTerm.triples;
|
|
268
|
+
} else if (conclTerm instanceof Literal && conclTerm.value === 'false') {
|
|
269
|
+
rawConclusion = [];
|
|
270
|
+
} else {
|
|
271
|
+
rawConclusion = [];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const headBlankLabels = collectBlankLabelsInTriples(rawConclusion);
|
|
275
|
+
const [premise0, conclusion] = liftBlankRuleVars(rawPremise, rawConclusion);
|
|
276
|
+
const premise = isForward ? reorderPremiseForConstraints(premise0) : premise0;
|
|
277
|
+
return new Rule(premise, conclusion, isForward, isFuse, headBlankLabels);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function __computeConclusionFromFormula(formula) {
|
|
281
|
+
if (!(formula instanceof GraphTerm)) return null;
|
|
282
|
+
|
|
283
|
+
const cached = __logConclusionCache.get(formula);
|
|
284
|
+
if (cached) return cached;
|
|
285
|
+
|
|
286
|
+
// Facts start as *all* triples in the formula, including rule triples.
|
|
287
|
+
const facts2 = formula.triples.slice();
|
|
288
|
+
|
|
289
|
+
// Extract rules from rule-triples present inside the formula.
|
|
290
|
+
const fw = [];
|
|
291
|
+
const bw = [];
|
|
292
|
+
|
|
293
|
+
for (const tr of formula.triples) {
|
|
294
|
+
// Treat {A} => {B} as a forward rule.
|
|
295
|
+
if (isLogImplies(tr.p)) {
|
|
296
|
+
fw.push(__makeRuleFromTerms(tr.s, tr.o, true));
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Treat {A} <= {B} as the same rule in the other direction, i.e., {B} => {A},
|
|
301
|
+
// so it participates in deductive closure even if only <= is used.
|
|
302
|
+
if (isLogImpliedBy(tr.p)) {
|
|
303
|
+
fw.push(__makeRuleFromTerms(tr.o, tr.s, true));
|
|
304
|
+
// Also index it as a backward rule for completeness (helps proveGoals in some cases).
|
|
305
|
+
bw.push(__makeRuleFromTerms(tr.s, tr.o, false));
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Saturate within this local formula only.
|
|
311
|
+
forwardChain(facts2, fw, bw);
|
|
312
|
+
|
|
313
|
+
const out = new GraphTerm(facts2.slice());
|
|
314
|
+
__logConclusionCache.set(formula, out);
|
|
315
|
+
return out;
|
|
316
|
+
}
|
|
317
|
+
|
|
236
318
|
|
|
237
319
|
|
|
238
320
|
// Controls whether human-readable proof comments are printed.
|
|
@@ -4850,6 +4932,31 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4850
4932
|
return s2 !== null ? [s2] : [];
|
|
4851
4933
|
}
|
|
4852
4934
|
|
|
4935
|
+
|
|
4936
|
+
// log:conclusion
|
|
4937
|
+
// Schema: $s+ log:conclusion $o?
|
|
4938
|
+
// $o is the deductive closure of the subject formula $s (including rule inferences).
|
|
4939
|
+
if (pv === LOG_NS + 'conclusion') {
|
|
4940
|
+
// Accept 'true' as the empty formula.
|
|
4941
|
+
let inFormula = null;
|
|
4942
|
+
if (g.s instanceof GraphTerm) inFormula = g.s;
|
|
4943
|
+
else if (g.s instanceof Literal && g.s.value === 'true') inFormula = new GraphTerm([]);
|
|
4944
|
+
else return [];
|
|
4945
|
+
|
|
4946
|
+
const conclusion = __computeConclusionFromFormula(inFormula);
|
|
4947
|
+
if (!(conclusion instanceof GraphTerm)) return [];
|
|
4948
|
+
|
|
4949
|
+
if (g.o instanceof Var) {
|
|
4950
|
+
const s2 = { ...subst };
|
|
4951
|
+
s2[g.o.name] = conclusion;
|
|
4952
|
+
return [s2];
|
|
4953
|
+
}
|
|
4954
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4955
|
+
|
|
4956
|
+
const s2 = unifyTerm(g.o, conclusion, subst);
|
|
4957
|
+
return s2 !== null ? [s2] : [];
|
|
4958
|
+
}
|
|
4959
|
+
|
|
4853
4960
|
// log:content
|
|
4854
4961
|
// Schema: $s+ log:content $o?
|
|
4855
4962
|
// Dereferences $s and returns the online resource as an xsd:string.
|
|
@@ -5998,10 +6105,17 @@ function termToN3(t, pref) {
|
|
|
5998
6105
|
return '(' + inside.join(' ') + ')';
|
|
5999
6106
|
}
|
|
6000
6107
|
if (t instanceof GraphTerm) {
|
|
6108
|
+
const indent = ' ';
|
|
6109
|
+
const indentBlock = (str) =>
|
|
6110
|
+
str
|
|
6111
|
+
.split(/\r?\n/)
|
|
6112
|
+
.map((ln) => (ln.length ? indent + ln : ln))
|
|
6113
|
+
.join('\n');
|
|
6114
|
+
|
|
6001
6115
|
let s = '{\n';
|
|
6002
6116
|
for (const tr of t.triples) {
|
|
6003
|
-
|
|
6004
|
-
if (
|
|
6117
|
+
const block = tripleToN3(tr, pref).trimEnd();
|
|
6118
|
+
if (block) s += indentBlock(block) + '\n';
|
|
6005
6119
|
}
|
|
6006
6120
|
s += '}';
|
|
6007
6121
|
return s;
|