eyeling 1.6.18 → 1.6.20
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 +113 -75
- package/package.json +1 -1
package/eyeling.js
CHANGED
|
@@ -62,9 +62,9 @@ function termToJsonText(t) {
|
|
|
62
62
|
function makeRdfJsonLiteral(jsonText) {
|
|
63
63
|
// Prefer a readable long literal when safe; fall back to short if needed.
|
|
64
64
|
if (!jsonText.includes('"""')) {
|
|
65
|
-
return
|
|
65
|
+
return internLiteral('"""' + jsonText + '"""^^<' + RDF_JSON_DT + '>');
|
|
66
66
|
}
|
|
67
|
-
return
|
|
67
|
+
return internLiteral(JSON.stringify(jsonText) + '^^<' + RDF_JSON_DT + '>');
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
// For a single reasoning run, this maps a canonical representation
|
|
@@ -87,16 +87,6 @@ let fixedNowLex = null;
|
|
|
87
87
|
// If not fixed, we still memoize one value per run to avoid re-firing rules.
|
|
88
88
|
let runNowLex = null;
|
|
89
89
|
|
|
90
|
-
function normalizeDateTimeLex(s) {
|
|
91
|
-
// Accept: 2025-... , "2025-..." , "2025-..."^^xsd:dateTime , "..."^^<...>
|
|
92
|
-
if (s == null) return null;
|
|
93
|
-
let t = String(s).trim();
|
|
94
|
-
const caret = t.indexOf('^^');
|
|
95
|
-
if (caret >= 0) t = t.slice(0, caret).trim();
|
|
96
|
-
if (t.startsWith('"') && t.endsWith('"') && t.length >= 2) t = t.slice(1, -1);
|
|
97
|
-
return t.trim();
|
|
98
|
-
}
|
|
99
|
-
|
|
100
90
|
// ===========================================================================
|
|
101
91
|
// Run-level time helpers
|
|
102
92
|
// ===========================================================================
|
|
@@ -222,6 +212,37 @@ class Var extends Term {
|
|
|
222
212
|
}
|
|
223
213
|
}
|
|
224
214
|
|
|
215
|
+
// ===========================================================================
|
|
216
|
+
// Term interning
|
|
217
|
+
// ===========================================================================
|
|
218
|
+
|
|
219
|
+
// Intern IRIs and literals by their raw lexical string.
|
|
220
|
+
// This reduces allocations when the same terms repeat and can improve performance.
|
|
221
|
+
//
|
|
222
|
+
// NOTE: Terms are treated as immutable. Do NOT mutate .value on interned objects.
|
|
223
|
+
const __iriIntern = new Map();
|
|
224
|
+
const __literalIntern = new Map();
|
|
225
|
+
|
|
226
|
+
/** @param {string} value */
|
|
227
|
+
function internIri(value) {
|
|
228
|
+
let t = __iriIntern.get(value);
|
|
229
|
+
if (!t) {
|
|
230
|
+
t = new Iri(value);
|
|
231
|
+
__iriIntern.set(value, t);
|
|
232
|
+
}
|
|
233
|
+
return t;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/** @param {string} value */
|
|
237
|
+
function internLiteral(value) {
|
|
238
|
+
let t = __literalIntern.get(value);
|
|
239
|
+
if (!t) {
|
|
240
|
+
t = new Literal(value);
|
|
241
|
+
__literalIntern.set(value, t);
|
|
242
|
+
}
|
|
243
|
+
return t;
|
|
244
|
+
}
|
|
245
|
+
|
|
225
246
|
class Blank extends Term {
|
|
226
247
|
constructor(label) {
|
|
227
248
|
super();
|
|
@@ -986,23 +1007,23 @@ class Parser {
|
|
|
986
1007
|
const val = tok.value;
|
|
987
1008
|
|
|
988
1009
|
if (typ === 'Equals') {
|
|
989
|
-
return
|
|
1010
|
+
return internIri(OWL_NS + 'sameAs');
|
|
990
1011
|
}
|
|
991
1012
|
|
|
992
1013
|
if (typ === 'IriRef') {
|
|
993
1014
|
const base = this.prefixes.map[''] || '';
|
|
994
|
-
return
|
|
1015
|
+
return internIri(resolveIriRef(val || '', base));
|
|
995
1016
|
}
|
|
996
1017
|
if (typ === 'Ident') {
|
|
997
1018
|
const name = val || '';
|
|
998
1019
|
if (name === 'a') {
|
|
999
|
-
return
|
|
1020
|
+
return internIri(RDF_NS + 'type');
|
|
1000
1021
|
} else if (name.startsWith('_:')) {
|
|
1001
1022
|
return new Blank(name);
|
|
1002
1023
|
} else if (name.includes(':')) {
|
|
1003
|
-
return
|
|
1024
|
+
return internIri(this.prefixes.expandQName(name));
|
|
1004
1025
|
} else {
|
|
1005
|
-
return
|
|
1026
|
+
return internIri(name);
|
|
1006
1027
|
}
|
|
1007
1028
|
}
|
|
1008
1029
|
|
|
@@ -1040,7 +1061,7 @@ class Parser {
|
|
|
1040
1061
|
}
|
|
1041
1062
|
s = `${s}^^<${dtIri}>`;
|
|
1042
1063
|
}
|
|
1043
|
-
return
|
|
1064
|
+
return internLiteral(s);
|
|
1044
1065
|
}
|
|
1045
1066
|
|
|
1046
1067
|
if (typ === 'Var') return new Var(val || '');
|
|
@@ -1079,7 +1100,7 @@ class Parser {
|
|
|
1079
1100
|
let invert = false;
|
|
1080
1101
|
if (this.peek().typ === 'Ident' && (this.peek().value || '') === 'a') {
|
|
1081
1102
|
this.next();
|
|
1082
|
-
pred =
|
|
1103
|
+
pred = internIri(RDF_NS + 'type');
|
|
1083
1104
|
} else if (this.peek().typ === 'OpPredInvert') {
|
|
1084
1105
|
this.next(); // consume "<-"
|
|
1085
1106
|
pred = this.parseTerm();
|
|
@@ -1123,7 +1144,7 @@ class Parser {
|
|
|
1123
1144
|
if (this.peek().typ === 'OpImplies') {
|
|
1124
1145
|
this.next();
|
|
1125
1146
|
const right = this.parseTerm();
|
|
1126
|
-
const pred =
|
|
1147
|
+
const pred = internIri(LOG_NS + 'implies');
|
|
1127
1148
|
triples.push(new Triple(left, pred, right));
|
|
1128
1149
|
if (this.peek().typ === 'Dot') this.next();
|
|
1129
1150
|
else if (this.peek().typ === 'RBrace') {
|
|
@@ -1134,7 +1155,7 @@ class Parser {
|
|
|
1134
1155
|
} else if (this.peek().typ === 'OpImpliedBy') {
|
|
1135
1156
|
this.next();
|
|
1136
1157
|
const right = this.parseTerm();
|
|
1137
|
-
const pred =
|
|
1158
|
+
const pred = internIri(LOG_NS + 'impliedBy');
|
|
1138
1159
|
triples.push(new Triple(left, pred, right));
|
|
1139
1160
|
if (this.peek().typ === 'Dot') this.next();
|
|
1140
1161
|
else if (this.peek().typ === 'RBrace') {
|
|
@@ -1182,7 +1203,7 @@ class Parser {
|
|
|
1182
1203
|
|
|
1183
1204
|
if (this.peek().typ === 'Ident' && (this.peek().value || '') === 'a') {
|
|
1184
1205
|
this.next();
|
|
1185
|
-
verb =
|
|
1206
|
+
verb = internIri(RDF_NS + 'type');
|
|
1186
1207
|
} else if (this.peek().typ === 'OpPredInvert') {
|
|
1187
1208
|
this.next(); // "<-"
|
|
1188
1209
|
verb = this.parseTerm();
|
|
@@ -1651,10 +1672,6 @@ function alphaEqTriple(a, b) {
|
|
|
1651
1672
|
return alphaEqTerm(a.s, b.s, bmap) && alphaEqTerm(a.p, b.p, bmap) && alphaEqTerm(a.o, b.o, bmap);
|
|
1652
1673
|
}
|
|
1653
1674
|
|
|
1654
|
-
function hasAlphaEquiv(triples, tr) {
|
|
1655
|
-
return triples.some((t) => alphaEqTriple(t, tr));
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
1675
|
// ===========================================================================
|
|
1659
1676
|
// Indexes (facts + backward rules)
|
|
1660
1677
|
// ===========================================================================
|
|
@@ -1683,13 +1700,18 @@ function tripleFastKey(tr) {
|
|
|
1683
1700
|
}
|
|
1684
1701
|
|
|
1685
1702
|
function ensureFactIndexes(facts) {
|
|
1686
|
-
if (facts.__byPred && facts.__byPO && facts.__keySet) return;
|
|
1703
|
+
if (facts.__byPred && facts.__byPS && facts.__byPO && facts.__keySet) return;
|
|
1687
1704
|
|
|
1688
1705
|
Object.defineProperty(facts, '__byPred', {
|
|
1689
1706
|
value: new Map(),
|
|
1690
1707
|
enumerable: false,
|
|
1691
1708
|
writable: true,
|
|
1692
1709
|
});
|
|
1710
|
+
Object.defineProperty(facts, '__byPS', {
|
|
1711
|
+
value: new Map(),
|
|
1712
|
+
enumerable: false,
|
|
1713
|
+
writable: true,
|
|
1714
|
+
});
|
|
1693
1715
|
Object.defineProperty(facts, '__byPO', {
|
|
1694
1716
|
value: new Map(),
|
|
1695
1717
|
enumerable: false,
|
|
@@ -1715,6 +1737,21 @@ function indexFact(facts, tr) {
|
|
|
1715
1737
|
}
|
|
1716
1738
|
pb.push(tr);
|
|
1717
1739
|
|
|
1740
|
+
const sk = termFastKey(tr.s);
|
|
1741
|
+
if (sk !== null) {
|
|
1742
|
+
let ps = facts.__byPS.get(pk);
|
|
1743
|
+
if (!ps) {
|
|
1744
|
+
ps = new Map();
|
|
1745
|
+
facts.__byPS.set(pk, ps);
|
|
1746
|
+
}
|
|
1747
|
+
let psb = ps.get(sk);
|
|
1748
|
+
if (!psb) {
|
|
1749
|
+
psb = [];
|
|
1750
|
+
ps.set(sk, psb);
|
|
1751
|
+
}
|
|
1752
|
+
psb.push(tr);
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1718
1755
|
const ok = termFastKey(tr.o);
|
|
1719
1756
|
if (ok !== null) {
|
|
1720
1757
|
let po = facts.__byPO.get(pk);
|
|
@@ -1741,15 +1778,27 @@ function candidateFacts(facts, goal) {
|
|
|
1741
1778
|
if (goal.p instanceof Iri) {
|
|
1742
1779
|
const pk = goal.p.value;
|
|
1743
1780
|
|
|
1781
|
+
const sk = termFastKey(goal.s);
|
|
1744
1782
|
const ok = termFastKey(goal.o);
|
|
1783
|
+
|
|
1784
|
+
/** @type {Triple[] | null} */
|
|
1785
|
+
let byPS = null;
|
|
1786
|
+
if (sk !== null) {
|
|
1787
|
+
const ps = facts.__byPS.get(pk);
|
|
1788
|
+
if (ps) byPS = ps.get(sk) || null;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
/** @type {Triple[] | null} */
|
|
1792
|
+
let byPO = null;
|
|
1745
1793
|
if (ok !== null) {
|
|
1746
1794
|
const po = facts.__byPO.get(pk);
|
|
1747
|
-
if (po)
|
|
1748
|
-
const pob = po.get(ok);
|
|
1749
|
-
if (pob) return pob;
|
|
1750
|
-
}
|
|
1795
|
+
if (po) byPO = po.get(ok) || null;
|
|
1751
1796
|
}
|
|
1752
1797
|
|
|
1798
|
+
if (byPS && byPO) return byPS.length <= byPO.length ? byPS : byPO;
|
|
1799
|
+
if (byPS) return byPS;
|
|
1800
|
+
if (byPO) return byPO;
|
|
1801
|
+
|
|
1753
1802
|
return facts.__byPred.get(pk) || [];
|
|
1754
1803
|
}
|
|
1755
1804
|
|
|
@@ -1896,12 +1945,10 @@ function isConstraintBuiltin(tr) {
|
|
|
1896
1945
|
return false;
|
|
1897
1946
|
}
|
|
1898
1947
|
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
* - pure test / constraint builtins last (checked once bindings are in place).
|
|
1904
|
-
*/
|
|
1948
|
+
// Move constraint builtins to the end of the rule premise.
|
|
1949
|
+
// This is a simple "delaying" strategy similar in spirit to Prolog's when/2:
|
|
1950
|
+
// - normal goals first (can bind variables),
|
|
1951
|
+
// - pure test / constraint builtins last (checked once bindings are in place).
|
|
1905
1952
|
function reorderPremiseForConstraints(premise) {
|
|
1906
1953
|
if (!premise || premise.length === 0) return premise;
|
|
1907
1954
|
|
|
@@ -2348,7 +2395,7 @@ function termToJsString(t) {
|
|
|
2348
2395
|
function makeStringLiteral(str) {
|
|
2349
2396
|
// JSON.stringify gives us a valid N3/Turtle-style quoted string
|
|
2350
2397
|
// (with proper escaping for quotes, backslashes, newlines, …).
|
|
2351
|
-
return
|
|
2398
|
+
return internLiteral(JSON.stringify(str));
|
|
2352
2399
|
}
|
|
2353
2400
|
|
|
2354
2401
|
function termToJsStringDecoded(t) {
|
|
@@ -2397,8 +2444,8 @@ function jsonPointerUnescape(seg) {
|
|
|
2397
2444
|
function jsonToTerm(v) {
|
|
2398
2445
|
if (v === null) return makeStringLiteral('null');
|
|
2399
2446
|
if (typeof v === 'string') return makeStringLiteral(v);
|
|
2400
|
-
if (typeof v === 'number') return
|
|
2401
|
-
if (typeof v === 'boolean') return
|
|
2447
|
+
if (typeof v === 'number') return internLiteral(String(v));
|
|
2448
|
+
if (typeof v === 'boolean') return internLiteral(v ? 'true' : 'false');
|
|
2402
2449
|
if (Array.isArray(v)) return new ListTerm(v.map(jsonToTerm));
|
|
2403
2450
|
|
|
2404
2451
|
if (v && typeof v === 'object') {
|
|
@@ -2676,15 +2723,6 @@ function parseIntLiteral(t) {
|
|
|
2676
2723
|
}
|
|
2677
2724
|
}
|
|
2678
2725
|
|
|
2679
|
-
function parseNumberLiteral(t) {
|
|
2680
|
-
// Prefer BigInt for integers, fall back to Number for other numeric literals.
|
|
2681
|
-
const bi = parseIntLiteral(t);
|
|
2682
|
-
if (bi !== null) return bi;
|
|
2683
|
-
const n = parseNum(t);
|
|
2684
|
-
if (n !== null) return n;
|
|
2685
|
-
return null;
|
|
2686
|
-
}
|
|
2687
|
-
|
|
2688
2726
|
function formatNum(n) {
|
|
2689
2727
|
return String(n);
|
|
2690
2728
|
}
|
|
@@ -2880,7 +2918,7 @@ function formatDurationLiteralFromSeconds(secs) {
|
|
|
2880
2918
|
const neg = secs < 0;
|
|
2881
2919
|
const days = Math.round(Math.abs(secs) / 86400.0);
|
|
2882
2920
|
const literalLex = neg ? `"-P${days}D"` : `"P${days}D"`;
|
|
2883
|
-
return
|
|
2921
|
+
return internLiteral(`${literalLex}^^<${XSD_NS}duration>`);
|
|
2884
2922
|
}
|
|
2885
2923
|
function numEqualTerm(t, n, eps = 1e-9) {
|
|
2886
2924
|
const v = parseNum(t);
|
|
@@ -2992,21 +3030,21 @@ function commonNumericDatatype(terms, outTerm) {
|
|
|
2992
3030
|
|
|
2993
3031
|
function makeNumericOutputLiteral(val, dt) {
|
|
2994
3032
|
if (dt === XSD_INTEGER_DT) {
|
|
2995
|
-
if (typeof val === 'bigint') return
|
|
2996
|
-
if (Number.isInteger(val)) return
|
|
3033
|
+
if (typeof val === 'bigint') return internLiteral(val.toString());
|
|
3034
|
+
if (Number.isInteger(val)) return internLiteral(String(val));
|
|
2997
3035
|
// If a non-integer sneaks in, promote to decimal.
|
|
2998
|
-
return
|
|
3036
|
+
return internLiteral(`"${formatNum(val)}"^^<${XSD_DECIMAL_DT}>`);
|
|
2999
3037
|
}
|
|
3000
3038
|
|
|
3001
3039
|
if (dt === XSD_FLOAT_DT || dt === XSD_DOUBLE_DT) {
|
|
3002
3040
|
const sp = formatXsdFloatSpecialLex(val);
|
|
3003
3041
|
const lex = sp !== null ? sp : formatNum(val);
|
|
3004
|
-
return
|
|
3042
|
+
return internLiteral(`"${lex}"^^<${dt}>`);
|
|
3005
3043
|
}
|
|
3006
3044
|
|
|
3007
3045
|
// decimal
|
|
3008
3046
|
const lex = typeof val === 'bigint' ? val.toString() : formatNum(val);
|
|
3009
|
-
return
|
|
3047
|
+
return internLiteral(`"${lex}"^^<${dt}>`);
|
|
3010
3048
|
}
|
|
3011
3049
|
|
|
3012
3050
|
function evalUnaryMathRel(g, subst, forwardFn, inverseFn /* may be null */) {
|
|
@@ -3254,7 +3292,7 @@ function hashLiteralTerm(t, algo) {
|
|
|
3254
3292
|
const input = stripQuotes(lex);
|
|
3255
3293
|
try {
|
|
3256
3294
|
const digest = nodeCrypto.createHash(algo).update(input, 'utf8').digest('hex');
|
|
3257
|
-
return
|
|
3295
|
+
return internLiteral(JSON.stringify(digest));
|
|
3258
3296
|
} catch (e) {
|
|
3259
3297
|
return null;
|
|
3260
3298
|
}
|
|
@@ -3454,7 +3492,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3454
3492
|
if (secs !== null) {
|
|
3455
3493
|
const outSecs = aDt.getTime() / 1000.0 - secs;
|
|
3456
3494
|
const lex = utcIsoDateTimeStringFromEpochSeconds(outSecs);
|
|
3457
|
-
const lit =
|
|
3495
|
+
const lit = internLiteral(`"${lex}"^^<${XSD_NS}dateTime>`);
|
|
3458
3496
|
if (g.o instanceof Var) {
|
|
3459
3497
|
const s2 = { ...subst };
|
|
3460
3498
|
s2[g.o.name] = lit;
|
|
@@ -3470,7 +3508,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3470
3508
|
const bi = parseIntLiteral(b0);
|
|
3471
3509
|
if (ai !== null && bi !== null) {
|
|
3472
3510
|
const ci = ai - bi;
|
|
3473
|
-
const lit =
|
|
3511
|
+
const lit = internLiteral(ci.toString());
|
|
3474
3512
|
if (g.o instanceof Var) {
|
|
3475
3513
|
const s2 = { ...subst };
|
|
3476
3514
|
s2[g.o.name] = lit;
|
|
@@ -3505,7 +3543,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3505
3543
|
}
|
|
3506
3544
|
|
|
3507
3545
|
// Fallback (if you *don’t* have those helpers yet):
|
|
3508
|
-
const lit =
|
|
3546
|
+
const lit = internLiteral(formatNum(c));
|
|
3509
3547
|
if (g.o instanceof Var) {
|
|
3510
3548
|
const s2 = { ...subst };
|
|
3511
3549
|
s2[g.o.name] = lit;
|
|
@@ -3556,7 +3594,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3556
3594
|
if (ai !== null && bi !== null) {
|
|
3557
3595
|
if (bi === 0n) return [];
|
|
3558
3596
|
const q = ai / bi; // BigInt division truncates toward zero
|
|
3559
|
-
const lit =
|
|
3597
|
+
const lit = internLiteral(q.toString());
|
|
3560
3598
|
if (g.o instanceof Var) {
|
|
3561
3599
|
const s2 = { ...subst };
|
|
3562
3600
|
s2[g.o.name] = lit;
|
|
@@ -3585,7 +3623,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3585
3623
|
if (!Number.isInteger(a) || !Number.isInteger(b)) return [];
|
|
3586
3624
|
|
|
3587
3625
|
const q = Math.trunc(a / b);
|
|
3588
|
-
const lit =
|
|
3626
|
+
const lit = internLiteral(String(q));
|
|
3589
3627
|
if (g.o instanceof Var) {
|
|
3590
3628
|
const s2 = { ...subst };
|
|
3591
3629
|
s2[g.o.name] = lit;
|
|
@@ -3783,7 +3821,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3783
3821
|
if (Number.isNaN(a)) return [];
|
|
3784
3822
|
|
|
3785
3823
|
const rVal = Math.round(a); // ties go toward +∞ in JS (e.g., -1.5 -> -1)
|
|
3786
|
-
const lit =
|
|
3824
|
+
const lit = internLiteral(String(rVal)); // integer token
|
|
3787
3825
|
|
|
3788
3826
|
if (g.o instanceof Var) {
|
|
3789
3827
|
const s2 = { ...subst };
|
|
@@ -3811,7 +3849,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3811
3849
|
|
|
3812
3850
|
if (g.o instanceof Var) {
|
|
3813
3851
|
const s2 = { ...subst };
|
|
3814
|
-
s2[g.o.name] =
|
|
3852
|
+
s2[g.o.name] = internLiteral(`"${now}"^^<${XSD_NS}dateTime>`);
|
|
3815
3853
|
return [s2];
|
|
3816
3854
|
}
|
|
3817
3855
|
if (g.o instanceof Literal) {
|
|
@@ -3873,7 +3911,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3873
3911
|
const outs = [];
|
|
3874
3912
|
|
|
3875
3913
|
for (let i = 0; i < xs.length; i++) {
|
|
3876
|
-
const idxLit =
|
|
3914
|
+
const idxLit = internLiteral(String(i)); // 0-based
|
|
3877
3915
|
const val = xs[i];
|
|
3878
3916
|
|
|
3879
3917
|
// Fast path: object is exactly a 2-element list (idx, value)
|
|
@@ -3929,7 +3967,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
3929
3967
|
const outs = [];
|
|
3930
3968
|
|
|
3931
3969
|
for (let i = 0; i < xs.length; i++) {
|
|
3932
|
-
const idxLit =
|
|
3970
|
+
const idxLit = internLiteral(String(i)); // index starts at 0
|
|
3933
3971
|
|
|
3934
3972
|
// --- index side: strict if ground, otherwise unify/bind
|
|
3935
3973
|
let s1 = null;
|
|
@@ -4005,7 +4043,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4005
4043
|
// list:length (strict: do not accept integer<->decimal matches for a ground object)
|
|
4006
4044
|
if (pv === LIST_NS + 'length') {
|
|
4007
4045
|
if (!(g.s instanceof ListTerm)) return [];
|
|
4008
|
-
const nTerm =
|
|
4046
|
+
const nTerm = internLiteral(String(g.s.elems.length));
|
|
4009
4047
|
|
|
4010
4048
|
const o2 = applySubstTerm(g.o, subst);
|
|
4011
4049
|
if (isGroundTerm(o2)) {
|
|
@@ -4117,7 +4155,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4117
4155
|
if (!(inputTerm instanceof ListTerm)) return [];
|
|
4118
4156
|
const inputList = inputTerm.elems;
|
|
4119
4157
|
if (!(predTerm instanceof Iri)) return [];
|
|
4120
|
-
const pred =
|
|
4158
|
+
const pred = internIri(predTerm.value);
|
|
4121
4159
|
if (!isBuiltinPred(pred)) return [];
|
|
4122
4160
|
if (!inputList.every((e) => isGroundTerm(e))) return [];
|
|
4123
4161
|
|
|
@@ -4210,8 +4248,8 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4210
4248
|
}
|
|
4211
4249
|
|
|
4212
4250
|
if (oDt !== null) {
|
|
4213
|
-
const strLit = isQuotedLexical(oLex) ?
|
|
4214
|
-
const subjList = new ListTerm([strLit,
|
|
4251
|
+
const strLit = isQuotedLexical(oLex) ? internLiteral(oLex) : makeStringLiteral(String(oLex));
|
|
4252
|
+
const subjList = new ListTerm([strLit, internIri(oDt)]);
|
|
4215
4253
|
const s2 = unifyTerm(goal.s, subjList, subst);
|
|
4216
4254
|
if (s2 !== null) results.push(s2);
|
|
4217
4255
|
}
|
|
@@ -4230,7 +4268,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4230
4268
|
if (okString) {
|
|
4231
4269
|
const dtIri = b.value;
|
|
4232
4270
|
// For xsd:string, prefer the plain string literal form.
|
|
4233
|
-
const outLit = dtIri === XSD_NS + 'string' ?
|
|
4271
|
+
const outLit = dtIri === XSD_NS + 'string' ? internLiteral(sLex) : internLiteral(`${sLex}^^<${dtIri}>`);
|
|
4234
4272
|
const s2 = unifyTerm(goal.o, outLit, subst);
|
|
4235
4273
|
if (s2 !== null) results.push(s2);
|
|
4236
4274
|
}
|
|
@@ -4266,7 +4304,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4266
4304
|
const tag = extractLangTag(g.o.value);
|
|
4267
4305
|
if (tag !== null) {
|
|
4268
4306
|
const [oLex] = literalParts(g.o.value); // strips @lang into lexical part
|
|
4269
|
-
const strLit = isQuotedLexical(oLex) ?
|
|
4307
|
+
const strLit = isQuotedLexical(oLex) ? internLiteral(oLex) : makeStringLiteral(String(oLex));
|
|
4270
4308
|
const langLit = makeStringLiteral(tag);
|
|
4271
4309
|
const subjList = new ListTerm([strLit, langLit]);
|
|
4272
4310
|
const s2 = unifyTerm(goal.s, subjList, subst);
|
|
@@ -4286,7 +4324,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4286
4324
|
if (okString && okLang) {
|
|
4287
4325
|
const tag = stripQuotes(langLex);
|
|
4288
4326
|
if (LANG_RE.test(tag)) {
|
|
4289
|
-
const outLit =
|
|
4327
|
+
const outLit = internLiteral(`${sLex}@${tag}`);
|
|
4290
4328
|
const s2 = unifyTerm(goal.o, outLit, subst);
|
|
4291
4329
|
if (s2 !== null) results.push(s2);
|
|
4292
4330
|
}
|
|
@@ -4308,7 +4346,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4308
4346
|
const r = standardizeRule(r0, varGen);
|
|
4309
4347
|
|
|
4310
4348
|
const premF = new FormulaTerm(r.premise);
|
|
4311
|
-
const concTerm = r0.isFuse ?
|
|
4349
|
+
const concTerm = r0.isFuse ? internLiteral('false') : new FormulaTerm(r.conclusion);
|
|
4312
4350
|
|
|
4313
4351
|
// unify subject with the premise formula
|
|
4314
4352
|
let s2 = unifyTerm(goal.s, premF, subst);
|
|
@@ -4445,7 +4483,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4445
4483
|
let iri = skolemCache.get(key);
|
|
4446
4484
|
if (!iri) {
|
|
4447
4485
|
const id = deterministicSkolemIdFromKey(key);
|
|
4448
|
-
iri =
|
|
4486
|
+
iri = internIri(SKOLEM_NS + id);
|
|
4449
4487
|
skolemCache.set(key, iri);
|
|
4450
4488
|
}
|
|
4451
4489
|
|
|
@@ -4467,7 +4505,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
|
|
|
4467
4505
|
if (g.o instanceof Literal) {
|
|
4468
4506
|
const uriStr = termToJsString(g.o); // JS string from the literal
|
|
4469
4507
|
if (uriStr === null) return [];
|
|
4470
|
-
const iri =
|
|
4508
|
+
const iri = internIri(uriStr);
|
|
4471
4509
|
const s2 = unifyTerm(goal.s, iri, subst);
|
|
4472
4510
|
return s2 !== null ? [s2] : [];
|
|
4473
4511
|
}
|