eyeling 1.11.14 → 1.11.15
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/eyeling.js +20 -2
- package/lib/builtins.js +2 -2
- package/lib/engine.js +18 -0
- package/package.json +1 -1
- package/test/api.test.js +21 -0
package/eyeling.js
CHANGED
|
@@ -1251,13 +1251,13 @@ function materializeRdfLists(triples, forwardRules, backwardRules) {
|
|
|
1251
1251
|
}
|
|
1252
1252
|
|
|
1253
1253
|
function rewriteTerm(t) {
|
|
1254
|
+
// rdf:nil is the empty list ()
|
|
1255
|
+
if (t instanceof Iri && t.value === RDF_NIL) return new ListTerm([]);
|
|
1254
1256
|
// Replace list nodes (Blank/Iri) by their constructed ListTerm when possible
|
|
1255
1257
|
const k = nodeKey(t);
|
|
1256
1258
|
if (k) {
|
|
1257
1259
|
const built = buildListForKey(k);
|
|
1258
1260
|
if (built) return built;
|
|
1259
|
-
// Also rewrite rdf:nil even if not otherwise referenced
|
|
1260
|
-
if (t instanceof Iri && t.value === RDF_NIL) return new ListTerm([]);
|
|
1261
1261
|
return t;
|
|
1262
1262
|
}
|
|
1263
1263
|
if (t instanceof ListTerm) {
|
|
@@ -4405,6 +4405,11 @@ const {
|
|
|
4405
4405
|
collectBlankLabelsInTriples,
|
|
4406
4406
|
} = require('./prelude');
|
|
4407
4407
|
|
|
4408
|
+
// In N3/Turtle, rdf:nil is the canonical IRI for the empty RDF list.
|
|
4409
|
+
// Eyeling represents list literals with ListTerm; ensure rdf:nil unifies with ().
|
|
4410
|
+
const RDF_NIL_IRI = RDF_NS + 'nil';
|
|
4411
|
+
const __EMPTY_LIST = new ListTerm([]);
|
|
4412
|
+
|
|
4408
4413
|
const { lex, N3SyntaxError } = require('./lexer');
|
|
4409
4414
|
const { Parser } = require('./parser');
|
|
4410
4415
|
const { liftBlankRuleVars } = require('./rules');
|
|
@@ -4718,6 +4723,10 @@ function termsEqual(a, b) {
|
|
|
4718
4723
|
if (a === b) return true;
|
|
4719
4724
|
if (!a || !b) return false;
|
|
4720
4725
|
if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
|
|
4726
|
+
|
|
4727
|
+
// rdf:nil is equivalent to the empty list ()
|
|
4728
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
|
|
4729
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
|
|
4721
4730
|
if (a.constructor !== b.constructor) return false;
|
|
4722
4731
|
|
|
4723
4732
|
if (a instanceof Iri) return a.value === b.value;
|
|
@@ -4777,6 +4786,10 @@ function termsEqualNoIntDecimal(a, b) {
|
|
|
4777
4786
|
if (a === b) return true;
|
|
4778
4787
|
if (!a || !b) return false;
|
|
4779
4788
|
if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
|
|
4789
|
+
|
|
4790
|
+
// rdf:nil is equivalent to the empty list ()
|
|
4791
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
|
|
4792
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
|
|
4780
4793
|
if (a.constructor !== b.constructor) return false;
|
|
4781
4794
|
|
|
4782
4795
|
if (a instanceof Iri) return a.value === b.value;
|
|
@@ -5427,6 +5440,11 @@ function unifyTermWithOptions(a, b, subst, opts) {
|
|
|
5427
5440
|
a = applySubstTerm(a, subst);
|
|
5428
5441
|
b = applySubstTerm(b, subst);
|
|
5429
5442
|
|
|
5443
|
+
// Normalize rdf:nil IRI to the empty list term, so it unifies with () and
|
|
5444
|
+
// list builtins treat it consistently.
|
|
5445
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI) a = __EMPTY_LIST;
|
|
5446
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI) b = __EMPTY_LIST;
|
|
5447
|
+
|
|
5430
5448
|
// Variable binding
|
|
5431
5449
|
if (a instanceof Var) {
|
|
5432
5450
|
const v = a.name;
|
package/lib/builtins.js
CHANGED
|
@@ -1239,13 +1239,13 @@ function materializeRdfLists(triples, forwardRules, backwardRules) {
|
|
|
1239
1239
|
}
|
|
1240
1240
|
|
|
1241
1241
|
function rewriteTerm(t) {
|
|
1242
|
+
// rdf:nil is the empty list ()
|
|
1243
|
+
if (t instanceof Iri && t.value === RDF_NIL) return new ListTerm([]);
|
|
1242
1244
|
// Replace list nodes (Blank/Iri) by their constructed ListTerm when possible
|
|
1243
1245
|
const k = nodeKey(t);
|
|
1244
1246
|
if (k) {
|
|
1245
1247
|
const built = buildListForKey(k);
|
|
1246
1248
|
if (built) return built;
|
|
1247
|
-
// Also rewrite rdf:nil even if not otherwise referenced
|
|
1248
|
-
if (t instanceof Iri && t.value === RDF_NIL) return new ListTerm([]);
|
|
1249
1249
|
return t;
|
|
1250
1250
|
}
|
|
1251
1251
|
if (t instanceof ListTerm) {
|
package/lib/engine.js
CHANGED
|
@@ -27,6 +27,11 @@ const {
|
|
|
27
27
|
collectBlankLabelsInTriples,
|
|
28
28
|
} = require('./prelude');
|
|
29
29
|
|
|
30
|
+
// In N3/Turtle, rdf:nil is the canonical IRI for the empty RDF list.
|
|
31
|
+
// Eyeling represents list literals with ListTerm; ensure rdf:nil unifies with ().
|
|
32
|
+
const RDF_NIL_IRI = RDF_NS + 'nil';
|
|
33
|
+
const __EMPTY_LIST = new ListTerm([]);
|
|
34
|
+
|
|
30
35
|
const { lex, N3SyntaxError } = require('./lexer');
|
|
31
36
|
const { Parser } = require('./parser');
|
|
32
37
|
const { liftBlankRuleVars } = require('./rules');
|
|
@@ -340,6 +345,10 @@ function termsEqual(a, b) {
|
|
|
340
345
|
if (a === b) return true;
|
|
341
346
|
if (!a || !b) return false;
|
|
342
347
|
if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
|
|
348
|
+
|
|
349
|
+
// rdf:nil is equivalent to the empty list ()
|
|
350
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
|
|
351
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
|
|
343
352
|
if (a.constructor !== b.constructor) return false;
|
|
344
353
|
|
|
345
354
|
if (a instanceof Iri) return a.value === b.value;
|
|
@@ -399,6 +408,10 @@ function termsEqualNoIntDecimal(a, b) {
|
|
|
399
408
|
if (a === b) return true;
|
|
400
409
|
if (!a || !b) return false;
|
|
401
410
|
if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
|
|
411
|
+
|
|
412
|
+
// rdf:nil is equivalent to the empty list ()
|
|
413
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
|
|
414
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
|
|
402
415
|
if (a.constructor !== b.constructor) return false;
|
|
403
416
|
|
|
404
417
|
if (a instanceof Iri) return a.value === b.value;
|
|
@@ -1049,6 +1062,11 @@ function unifyTermWithOptions(a, b, subst, opts) {
|
|
|
1049
1062
|
a = applySubstTerm(a, subst);
|
|
1050
1063
|
b = applySubstTerm(b, subst);
|
|
1051
1064
|
|
|
1065
|
+
// Normalize rdf:nil IRI to the empty list term, so it unifies with () and
|
|
1066
|
+
// list builtins treat it consistently.
|
|
1067
|
+
if (a instanceof Iri && a.value === RDF_NIL_IRI) a = __EMPTY_LIST;
|
|
1068
|
+
if (b instanceof Iri && b.value === RDF_NIL_IRI) b = __EMPTY_LIST;
|
|
1069
|
+
|
|
1052
1070
|
// Variable binding
|
|
1053
1071
|
if (a instanceof Var) {
|
|
1054
1072
|
const v = a.name;
|
package/package.json
CHANGED
package/test/api.test.js
CHANGED
|
@@ -749,6 +749,27 @@ ${U('a')} <-${U('p')} ${U('b')}.`,
|
|
|
749
749
|
expect: [new RegExp(`${EX}s>\\s+<${EX}second>\\s+<${EX}b>\\s*\\.`)],
|
|
750
750
|
},
|
|
751
751
|
|
|
752
|
+
{
|
|
753
|
+
name: '49b rdf:nil matches empty list in rdf:rest (issue #7)',
|
|
754
|
+
opt: { proofComments: false },
|
|
755
|
+
input: `@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
|
|
756
|
+
|
|
757
|
+
${U('o1')} ${U('path')} (${U('c')} ${U('d')}).
|
|
758
|
+
|
|
759
|
+
{ ?o ${U('path')} ?path. } => { ?path rdf:type ${U('P')}. }.
|
|
760
|
+
{ ?p1 rdf:type ${U('P')}. ?p1 rdf:rest ?p2. } => { ?p2 rdf:type ${U('P')}. }.
|
|
761
|
+
|
|
762
|
+
# query1 uses ()
|
|
763
|
+
{ ?p rdf:type ${U('P')}. ?p rdf:rest (). } => { ${U('result')} ${U('query1')} (?p). }.
|
|
764
|
+
# query2 uses rdf:nil
|
|
765
|
+
{ ?p rdf:type ${U('P')}. ?p rdf:rest rdf:nil. } => { ${U('result')} ${U('query2')} (?p). }.
|
|
766
|
+
`,
|
|
767
|
+
expect: [
|
|
768
|
+
new RegExp(`${EX}result>\\s+<${EX}query1>\\s+\\(\\(\\s*<${EX}d>\\s*\\)\\)\\s*\\.`),
|
|
769
|
+
new RegExp(`${EX}result>\\s+<${EX}query2>\\s+\\(\\(\\s*<${EX}d>\\s*\\)\\)\\s*\\.`),
|
|
770
|
+
],
|
|
771
|
+
},
|
|
772
|
+
|
|
752
773
|
{
|
|
753
774
|
name: '50 rdf collection materialization: rdf:first/rdf:rest triples become list terms',
|
|
754
775
|
opt: { proofComments: false },
|