eyeling 1.5.32 → 1.5.34
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/json-pointer.n3 +2 -1
- package/examples/json-reconcile-vat.n3 +356 -0
- package/examples/output/age.n3 +2 -2
- package/examples/output/json-pointer.n3 +103 -103
- package/examples/output/json-reconcile-vat.n3 +33530 -0
- package/examples/output/math-builtins-tests.n3 +21 -20
- package/eyeling.js +63 -119
- package/package.json +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
@prefix : <http://example.org/math-tests#> .
|
|
2
2
|
@prefix math: <http://www.w3.org/2000/10/swap/math#> .
|
|
3
|
+
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
|
3
4
|
|
|
4
5
|
# ----------------------------------------------------------------------
|
|
5
6
|
# Proof for derived triple:
|
|
@@ -3431,16 +3432,16 @@
|
|
|
3431
3432
|
# Proof for derived triple:
|
|
3432
3433
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3433
3434
|
# It holds because the following instance of the rule body is provable:
|
|
3434
|
-
# "3.3"
|
|
3435
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3435
3436
|
# 3 math:equalTo 3 .
|
|
3436
3437
|
# via the schematic forward rule:
|
|
3437
3438
|
# {
|
|
3438
|
-
# "3.3"
|
|
3439
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3439
3440
|
# ?r math:equalTo 3 .
|
|
3440
3441
|
# } => {
|
|
3441
3442
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3442
3443
|
# :test-rounded-1 :builtin math:rounded .
|
|
3443
|
-
# :test-rounded-1 :input "3.3"
|
|
3444
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3444
3445
|
# :test-rounded-1 :expected 3 .
|
|
3445
3446
|
# :test-rounded-1 :actual ?r .
|
|
3446
3447
|
# :test-rounded-1 :status :pass .
|
|
@@ -3456,16 +3457,16 @@
|
|
|
3456
3457
|
# Proof for derived triple:
|
|
3457
3458
|
# :test-rounded-1 :builtin math:rounded .
|
|
3458
3459
|
# It holds because the following instance of the rule body is provable:
|
|
3459
|
-
# "3.3"
|
|
3460
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3460
3461
|
# 3 math:equalTo 3 .
|
|
3461
3462
|
# via the schematic forward rule:
|
|
3462
3463
|
# {
|
|
3463
|
-
# "3.3"
|
|
3464
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3464
3465
|
# ?r math:equalTo 3 .
|
|
3465
3466
|
# } => {
|
|
3466
3467
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3467
3468
|
# :test-rounded-1 :builtin math:rounded .
|
|
3468
|
-
# :test-rounded-1 :input "3.3"
|
|
3469
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3469
3470
|
# :test-rounded-1 :expected 3 .
|
|
3470
3471
|
# :test-rounded-1 :actual ?r .
|
|
3471
3472
|
# :test-rounded-1 :status :pass .
|
|
@@ -3479,18 +3480,18 @@
|
|
|
3479
3480
|
|
|
3480
3481
|
# ----------------------------------------------------------------------
|
|
3481
3482
|
# Proof for derived triple:
|
|
3482
|
-
# :test-rounded-1 :input "3.3"
|
|
3483
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3483
3484
|
# It holds because the following instance of the rule body is provable:
|
|
3484
|
-
# "3.3"
|
|
3485
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3485
3486
|
# 3 math:equalTo 3 .
|
|
3486
3487
|
# via the schematic forward rule:
|
|
3487
3488
|
# {
|
|
3488
|
-
# "3.3"
|
|
3489
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3489
3490
|
# ?r math:equalTo 3 .
|
|
3490
3491
|
# } => {
|
|
3491
3492
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3492
3493
|
# :test-rounded-1 :builtin math:rounded .
|
|
3493
|
-
# :test-rounded-1 :input "3.3"
|
|
3494
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3494
3495
|
# :test-rounded-1 :expected 3 .
|
|
3495
3496
|
# :test-rounded-1 :actual ?r .
|
|
3496
3497
|
# :test-rounded-1 :status :pass .
|
|
@@ -3500,22 +3501,22 @@
|
|
|
3500
3501
|
# Therefore the derived triple above is entailed by the rules and facts.
|
|
3501
3502
|
# ----------------------------------------------------------------------
|
|
3502
3503
|
|
|
3503
|
-
:test-rounded-1 :input "3.3"
|
|
3504
|
+
:test-rounded-1 :input "3.3"^^xsd:double .
|
|
3504
3505
|
|
|
3505
3506
|
# ----------------------------------------------------------------------
|
|
3506
3507
|
# Proof for derived triple:
|
|
3507
3508
|
# :test-rounded-1 :expected 3 .
|
|
3508
3509
|
# It holds because the following instance of the rule body is provable:
|
|
3509
|
-
# "3.3"
|
|
3510
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3510
3511
|
# 3 math:equalTo 3 .
|
|
3511
3512
|
# via the schematic forward rule:
|
|
3512
3513
|
# {
|
|
3513
|
-
# "3.3"
|
|
3514
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3514
3515
|
# ?r math:equalTo 3 .
|
|
3515
3516
|
# } => {
|
|
3516
3517
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3517
3518
|
# :test-rounded-1 :builtin math:rounded .
|
|
3518
|
-
# :test-rounded-1 :input "3.3"
|
|
3519
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3519
3520
|
# :test-rounded-1 :expected 3 .
|
|
3520
3521
|
# :test-rounded-1 :actual ?r .
|
|
3521
3522
|
# :test-rounded-1 :status :pass .
|
|
@@ -3531,16 +3532,16 @@
|
|
|
3531
3532
|
# Proof for derived triple:
|
|
3532
3533
|
# :test-rounded-1 :actual 3 .
|
|
3533
3534
|
# It holds because the following instance of the rule body is provable:
|
|
3534
|
-
# "3.3"
|
|
3535
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3535
3536
|
# 3 math:equalTo 3 .
|
|
3536
3537
|
# via the schematic forward rule:
|
|
3537
3538
|
# {
|
|
3538
|
-
# "3.3"
|
|
3539
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3539
3540
|
# ?r math:equalTo 3 .
|
|
3540
3541
|
# } => {
|
|
3541
3542
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3542
3543
|
# :test-rounded-1 :builtin math:rounded .
|
|
3543
|
-
# :test-rounded-1 :input "3.3"
|
|
3544
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3544
3545
|
# :test-rounded-1 :expected 3 .
|
|
3545
3546
|
# :test-rounded-1 :actual ?r .
|
|
3546
3547
|
# :test-rounded-1 :status :pass .
|
|
@@ -3556,16 +3557,16 @@
|
|
|
3556
3557
|
# Proof for derived triple:
|
|
3557
3558
|
# :test-rounded-1 :status :pass .
|
|
3558
3559
|
# It holds because the following instance of the rule body is provable:
|
|
3559
|
-
# "3.3"
|
|
3560
|
+
# "3.3"^^xsd:double math:rounded 3 .
|
|
3560
3561
|
# 3 math:equalTo 3 .
|
|
3561
3562
|
# via the schematic forward rule:
|
|
3562
3563
|
# {
|
|
3563
|
-
# "3.3"
|
|
3564
|
+
# "3.3"^^xsd:double math:rounded ?r .
|
|
3564
3565
|
# ?r math:equalTo 3 .
|
|
3565
3566
|
# } => {
|
|
3566
3567
|
# :test-rounded-1 a :MathBuiltinTest .
|
|
3567
3568
|
# :test-rounded-1 :builtin math:rounded .
|
|
3568
|
-
# :test-rounded-1 :input "3.3"
|
|
3569
|
+
# :test-rounded-1 :input "3.3"^^xsd:double .
|
|
3569
3570
|
# :test-rounded-1 :expected 3 .
|
|
3570
3571
|
# :test-rounded-1 :actual ?r .
|
|
3571
3572
|
# :test-rounded-1 :status :pass .
|
package/eyeling.js
CHANGED
|
@@ -34,6 +34,28 @@ const LIST_NS = "http://www.w3.org/2000/10/swap/list#";
|
|
|
34
34
|
const LOG_NS = "http://www.w3.org/2000/10/swap/log#";
|
|
35
35
|
const STRING_NS = "http://www.w3.org/2000/10/swap/string#";
|
|
36
36
|
const SKOLEM_NS = "https://eyereasoner.github.io/.well-known/genid/";
|
|
37
|
+
const RDF_JSON_DT = RDF_NS + "JSON";
|
|
38
|
+
|
|
39
|
+
function isRdfJsonDatatype(dt) {
|
|
40
|
+
// dt comes from literalParts() and may be expanded or prefixed depending on parsing/printing.
|
|
41
|
+
return dt === null || dt === RDF_JSON_DT || dt === "rdf:JSON";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function termToJsonText(t) {
|
|
45
|
+
if (!(t instanceof Literal)) return null;
|
|
46
|
+
const [lex, dt] = literalParts(t.value);
|
|
47
|
+
if (!isRdfJsonDatatype(dt)) return null;
|
|
48
|
+
// decode escapes for short literals; long literals are taken verbatim
|
|
49
|
+
return termToJsStringDecoded(t);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function makeRdfJsonLiteral(jsonText) {
|
|
53
|
+
// Prefer a readable long literal when safe; fall back to short if needed.
|
|
54
|
+
if (!jsonText.includes('"""')) {
|
|
55
|
+
return new Literal('"""' + jsonText + '"""^^<' + RDF_JSON_DT + '>');
|
|
56
|
+
}
|
|
57
|
+
return new Literal(JSON.stringify(jsonText) + '^^<' + RDF_JSON_DT + '>');
|
|
58
|
+
}
|
|
37
59
|
|
|
38
60
|
// For a single reasoning run, this maps a canonical representation
|
|
39
61
|
// of the subject term in log:skolem to a Skolem IRI.
|
|
@@ -552,6 +574,9 @@ function collectIrisInTerm(t) {
|
|
|
552
574
|
const out = [];
|
|
553
575
|
if (t instanceof Iri) {
|
|
554
576
|
out.push(t.value);
|
|
577
|
+
} else if (t instanceof Literal) {
|
|
578
|
+
const [_lex, dt] = literalParts(t.value);
|
|
579
|
+
if (dt) out.push(dt); // so rdf/xsd prefixes are emitted when only used in ^^...
|
|
555
580
|
} else if (t instanceof ListTerm) {
|
|
556
581
|
for (const x of t.elems) out.push(...collectIrisInTerm(x));
|
|
557
582
|
} else if (t instanceof OpenListTerm) {
|
|
@@ -1842,91 +1867,6 @@ function termToJsStringDecoded(t) {
|
|
|
1842
1867
|
return stripQuotes(lex);
|
|
1843
1868
|
}
|
|
1844
1869
|
|
|
1845
|
-
function _jsonPointerUnescape(seg) {
|
|
1846
|
-
// RFC6901: ~1 -> '/', ~0 -> '~'
|
|
1847
|
-
// Any other '~' escape is invalid.
|
|
1848
|
-
let out = "";
|
|
1849
|
-
for (let i = 0; i < seg.length; i++) {
|
|
1850
|
-
const c = seg[i];
|
|
1851
|
-
if (c !== "~") { out += c; continue; }
|
|
1852
|
-
if (i + 1 >= seg.length) return null;
|
|
1853
|
-
const n = seg[i + 1];
|
|
1854
|
-
if (n === "0") out += "~";
|
|
1855
|
-
else if (n === "1") out += "/";
|
|
1856
|
-
else return null;
|
|
1857
|
-
i++;
|
|
1858
|
-
}
|
|
1859
|
-
return out;
|
|
1860
|
-
}
|
|
1861
|
-
|
|
1862
|
-
function _jsonToTerm(v) {
|
|
1863
|
-
if (v === null) return makeStringLiteral("null");
|
|
1864
|
-
if (typeof v === "string") return makeStringLiteral(v);
|
|
1865
|
-
if (typeof v === "number") return new Literal(String(v));
|
|
1866
|
-
if (typeof v === "boolean") return new Literal(v ? "true" : "false");
|
|
1867
|
-
if (Array.isArray(v)) return new ListTerm(v.map(_jsonToTerm));
|
|
1868
|
-
if (typeof v === "object") return makeStringLiteral(JSON.stringify(v));
|
|
1869
|
-
return null;
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
function _jsonPointerLookup(jsonText, pointer) {
|
|
1873
|
-
// Support URI fragment form "#/a/b" (percent-decoded) as well.
|
|
1874
|
-
let ptr = pointer;
|
|
1875
|
-
if (ptr.startsWith("#")) {
|
|
1876
|
-
try { ptr = decodeURIComponent(ptr.slice(1)); } catch (e) { return null; }
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
// Cache per JSON document
|
|
1880
|
-
let entry = jsonPointerCache.get(jsonText);
|
|
1881
|
-
if (!entry) {
|
|
1882
|
-
let parsed = null;
|
|
1883
|
-
try { parsed = JSON.parse(jsonText); } catch (e) { parsed = null; }
|
|
1884
|
-
entry = { parsed, ptrCache: new Map() };
|
|
1885
|
-
jsonPointerCache.set(jsonText, entry);
|
|
1886
|
-
}
|
|
1887
|
-
if (entry.parsed === null) return null;
|
|
1888
|
-
|
|
1889
|
-
// Cache per pointer within this doc
|
|
1890
|
-
if (entry.ptrCache.has(ptr)) return entry.ptrCache.get(ptr);
|
|
1891
|
-
|
|
1892
|
-
let cur = entry.parsed;
|
|
1893
|
-
|
|
1894
|
-
if (ptr === "") {
|
|
1895
|
-
const t = _jsonToTerm(cur);
|
|
1896
|
-
entry.ptrCache.set(ptr, t);
|
|
1897
|
-
return t;
|
|
1898
|
-
}
|
|
1899
|
-
if (!ptr.startsWith("/")) { entry.ptrCache.set(ptr, null); return null; }
|
|
1900
|
-
|
|
1901
|
-
const parts = ptr.split("/").slice(1);
|
|
1902
|
-
for (const raw of parts) {
|
|
1903
|
-
const seg = _jsonPointerUnescape(raw);
|
|
1904
|
-
if (seg === null) { entry.ptrCache.set(ptr, null); return null; }
|
|
1905
|
-
|
|
1906
|
-
if (Array.isArray(cur)) {
|
|
1907
|
-
// JSON Pointer uses array indices as decimal strings
|
|
1908
|
-
if (!/^(0|[1-9]\d*)$/.test(seg)) { entry.ptrCache.set(ptr, null); return null; }
|
|
1909
|
-
const idx = Number(seg);
|
|
1910
|
-
if (!Number.isFinite(idx) || idx < 0 || idx >= cur.length) { entry.ptrCache.set(ptr, null); return null; }
|
|
1911
|
-
cur = cur[idx];
|
|
1912
|
-
continue;
|
|
1913
|
-
}
|
|
1914
|
-
|
|
1915
|
-
if (cur !== null && typeof cur === "object") {
|
|
1916
|
-
if (!Object.prototype.hasOwnProperty.call(cur, seg)) { entry.ptrCache.set(ptr, null); return null; }
|
|
1917
|
-
cur = cur[seg];
|
|
1918
|
-
continue;
|
|
1919
|
-
}
|
|
1920
|
-
|
|
1921
|
-
entry.ptrCache.set(ptr, null);
|
|
1922
|
-
return null;
|
|
1923
|
-
}
|
|
1924
|
-
|
|
1925
|
-
const out = _jsonToTerm(cur);
|
|
1926
|
-
entry.ptrCache.set(ptr, out);
|
|
1927
|
-
return out;
|
|
1928
|
-
}
|
|
1929
|
-
|
|
1930
1870
|
function jsonPointerUnescape(seg) {
|
|
1931
1871
|
// RFC6901: ~1 -> '/', ~0 -> '~'
|
|
1932
1872
|
let out = "";
|
|
@@ -1951,10 +1891,7 @@ function jsonToTerm(v) {
|
|
|
1951
1891
|
if (Array.isArray(v)) return new ListTerm(v.map(jsonToTerm));
|
|
1952
1892
|
|
|
1953
1893
|
if (v && typeof v === "object") {
|
|
1954
|
-
|
|
1955
|
-
// without needing escape decoding.
|
|
1956
|
-
const raw = JSON.stringify(v);
|
|
1957
|
-
return new Literal('"""' + raw + '"""');
|
|
1894
|
+
return makeRdfJsonLiteral(JSON.stringify(v));
|
|
1958
1895
|
}
|
|
1959
1896
|
return null;
|
|
1960
1897
|
}
|
|
@@ -3566,8 +3503,9 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3566
3503
|
// Schema: ( $jsonText $pointer ) string:jsonPointer $value
|
|
3567
3504
|
if (g.p instanceof Iri && g.p.value === STRING_NS + "jsonPointer") {
|
|
3568
3505
|
if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
|
|
3569
|
-
|
|
3570
|
-
const
|
|
3506
|
+
|
|
3507
|
+
const jsonText = termToJsonText(g.s.elems[0]); // <-- changed
|
|
3508
|
+
const ptr = termToJsStringDecoded(g.s.elems[1]);
|
|
3571
3509
|
if (jsonText === null || ptr === null) return [];
|
|
3572
3510
|
|
|
3573
3511
|
const valTerm = jsonPointerLookup(jsonText, ptr);
|
|
@@ -3817,28 +3755,28 @@ function listHasTriple(list, tr) {
|
|
|
3817
3755
|
//
|
|
3818
3756
|
// This is semantics-preserving for the ongoing proof state.
|
|
3819
3757
|
|
|
3820
|
-
function
|
|
3758
|
+
function gcCollectVarsInTerm(t, out) {
|
|
3821
3759
|
if (t instanceof Var) { out.add(t.name); return; }
|
|
3822
|
-
if (t instanceof ListTerm) { for (const e of t.elems)
|
|
3760
|
+
if (t instanceof ListTerm) { for (const e of t.elems) gcCollectVarsInTerm(e, out); return; }
|
|
3823
3761
|
if (t instanceof OpenListTerm) {
|
|
3824
|
-
for (const e of t.prefix)
|
|
3762
|
+
for (const e of t.prefix) gcCollectVarsInTerm(e, out);
|
|
3825
3763
|
out.add(t.tailVar);
|
|
3826
3764
|
return;
|
|
3827
3765
|
}
|
|
3828
|
-
if (t instanceof FormulaTerm) { for (const tr of t.triples)
|
|
3766
|
+
if (t instanceof FormulaTerm) { for (const tr of t.triples) gcCollectVarsInTriple(tr, out); return; }
|
|
3829
3767
|
}
|
|
3830
3768
|
|
|
3831
|
-
function
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3769
|
+
function gcCollectVarsInTriple(tr, out) {
|
|
3770
|
+
gcCollectVarsInTerm(tr.s, out);
|
|
3771
|
+
gcCollectVarsInTerm(tr.p, out);
|
|
3772
|
+
gcCollectVarsInTerm(tr.o, out);
|
|
3835
3773
|
}
|
|
3836
3774
|
|
|
3837
|
-
function
|
|
3838
|
-
for (const g of goals)
|
|
3775
|
+
function gcCollectVarsInGoals(goals, out) {
|
|
3776
|
+
for (const g of goals) gcCollectVarsInTriple(g, out);
|
|
3839
3777
|
}
|
|
3840
3778
|
|
|
3841
|
-
function
|
|
3779
|
+
function substSizeOver(subst, limit) {
|
|
3842
3780
|
let c = 0;
|
|
3843
3781
|
for (const _k in subst) {
|
|
3844
3782
|
if (++c > limit) return true;
|
|
@@ -3846,9 +3784,9 @@ function _substSizeOver(subst, limit) {
|
|
|
3846
3784
|
return false;
|
|
3847
3785
|
}
|
|
3848
3786
|
|
|
3849
|
-
function
|
|
3787
|
+
function gcCompactForGoals(subst, goals, answerVars) {
|
|
3850
3788
|
const keep = new Set(answerVars);
|
|
3851
|
-
|
|
3789
|
+
gcCollectVarsInGoals(goals, keep);
|
|
3852
3790
|
|
|
3853
3791
|
const expanded = new Set();
|
|
3854
3792
|
const queue = Array.from(keep);
|
|
@@ -3862,7 +3800,7 @@ function _gcCompactForGoals(subst, goals, answerVars) {
|
|
|
3862
3800
|
if (bound === undefined) continue;
|
|
3863
3801
|
|
|
3864
3802
|
const before = keep.size;
|
|
3865
|
-
|
|
3803
|
+
gcCollectVarsInTerm(bound, keep);
|
|
3866
3804
|
if (keep.size !== before) {
|
|
3867
3805
|
for (const nv of keep) {
|
|
3868
3806
|
if (!expanded.has(nv)) queue.push(nv);
|
|
@@ -3877,12 +3815,12 @@ function _gcCompactForGoals(subst, goals, answerVars) {
|
|
|
3877
3815
|
return out;
|
|
3878
3816
|
}
|
|
3879
3817
|
|
|
3880
|
-
function
|
|
3818
|
+
function maybeCompactSubst(subst, goals, answerVars, depth) {
|
|
3881
3819
|
// Keep the fast path fast.
|
|
3882
3820
|
// Only compact when the substitution is clearly getting large, or
|
|
3883
3821
|
// we are in a deep chain (where the quadratic behavior shows up).
|
|
3884
|
-
if (depth < 128 && !
|
|
3885
|
-
return
|
|
3822
|
+
if (depth < 128 && !substSizeOver(subst, 256)) return subst;
|
|
3823
|
+
return gcCompactForGoals(subst, goals, answerVars);
|
|
3886
3824
|
}
|
|
3887
3825
|
|
|
3888
3826
|
|
|
@@ -3898,9 +3836,9 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
3898
3836
|
|
|
3899
3837
|
// Variables from the original goal list (needed by the caller to instantiate conclusions)
|
|
3900
3838
|
const answerVars = new Set();
|
|
3901
|
-
|
|
3839
|
+
gcCollectVarsInGoals(initialGoals, answerVars);
|
|
3902
3840
|
if (!initialGoals.length) {
|
|
3903
|
-
results.push(
|
|
3841
|
+
results.push(gcCompactForGoals(initialSubst, [], answerVars));
|
|
3904
3842
|
return results;
|
|
3905
3843
|
}
|
|
3906
3844
|
|
|
@@ -3912,7 +3850,7 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
3912
3850
|
const state = stack.pop();
|
|
3913
3851
|
|
|
3914
3852
|
if (!state.goals.length) {
|
|
3915
|
-
results.push(
|
|
3853
|
+
results.push(gcCompactForGoals(state.subst, [], answerVars));
|
|
3916
3854
|
continue;
|
|
3917
3855
|
}
|
|
3918
3856
|
|
|
@@ -3928,9 +3866,9 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
3928
3866
|
if (composed === null) continue;
|
|
3929
3867
|
|
|
3930
3868
|
if (!restGoals.length) {
|
|
3931
|
-
results.push(
|
|
3869
|
+
results.push(gcCompactForGoals(composed, [], answerVars));
|
|
3932
3870
|
} else {
|
|
3933
|
-
const nextSubst =
|
|
3871
|
+
const nextSubst = maybeCompactSubst(composed, restGoals, answerVars, state.depth + 1);
|
|
3934
3872
|
stack.push({
|
|
3935
3873
|
goals: restGoals,
|
|
3936
3874
|
subst: nextSubst,
|
|
@@ -3957,9 +3895,9 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
3957
3895
|
if (composed === null) continue;
|
|
3958
3896
|
|
|
3959
3897
|
if (!restGoals.length) {
|
|
3960
|
-
results.push(
|
|
3898
|
+
results.push(gcCompactForGoals(composed, [], answerVars));
|
|
3961
3899
|
} else {
|
|
3962
|
-
const nextSubst =
|
|
3900
|
+
const nextSubst = maybeCompactSubst(composed, restGoals, answerVars, state.depth + 1);
|
|
3963
3901
|
stack.push({
|
|
3964
3902
|
goals: restGoals,
|
|
3965
3903
|
subst: nextSubst,
|
|
@@ -3978,9 +3916,9 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
3978
3916
|
if (composed === null) continue;
|
|
3979
3917
|
|
|
3980
3918
|
if (!restGoals.length) {
|
|
3981
|
-
results.push(
|
|
3919
|
+
results.push(gcCompactForGoals(composed, [], answerVars));
|
|
3982
3920
|
} else {
|
|
3983
|
-
const nextSubst =
|
|
3921
|
+
const nextSubst = maybeCompactSubst(composed, restGoals, answerVars, state.depth + 1);
|
|
3984
3922
|
stack.push({
|
|
3985
3923
|
goals: restGoals,
|
|
3986
3924
|
subst: nextSubst,
|
|
@@ -4013,7 +3951,7 @@ function proveGoals( goals, subst, facts, backRules, depth, visited, varGen ) {
|
|
|
4013
3951
|
if (composed === null) continue;
|
|
4014
3952
|
|
|
4015
3953
|
const newGoals = body.concat(restGoals);
|
|
4016
|
-
const nextSubst =
|
|
3954
|
+
const nextSubst = maybeCompactSubst(composed, newGoals, answerVars, state.depth + 1);
|
|
4017
3955
|
stack.push({
|
|
4018
3956
|
goals: newGoals,
|
|
4019
3957
|
subst: nextSubst,
|
|
@@ -4174,7 +4112,13 @@ function termToN3(t, pref) {
|
|
|
4174
4112
|
if (i.startsWith("_:")) return i;
|
|
4175
4113
|
return `<${i}>`;
|
|
4176
4114
|
}
|
|
4177
|
-
|
|
4115
|
+
if (t instanceof Literal) {
|
|
4116
|
+
const [lex, dt] = literalParts(t.value);
|
|
4117
|
+
if (!dt) return t.value; // keep numbers, booleans, lang-tagged strings, etc.
|
|
4118
|
+
const qdt = pref.shrinkIri(dt);
|
|
4119
|
+
if (qdt !== null) return `${lex}^^${qdt}`; // e.g. ^^rdf:JSON
|
|
4120
|
+
return `${lex}^^<${dt}>`; // fallback
|
|
4121
|
+
}
|
|
4178
4122
|
if (t instanceof Var) return `?${t.name}`;
|
|
4179
4123
|
if (t instanceof Blank) return t.label;
|
|
4180
4124
|
if (t instanceof ListTerm) {
|