eyeling 1.10.21 → 1.10.22
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/output/builtins-string-math.n3 +10 -0
- package/examples/output/builtins-triple-termtests.n3 +10 -0
- package/eyeling.js +72 -67
- package/lib/engine.js +72 -67
- package/package.json +1 -1
package/eyeling.js
CHANGED
|
@@ -1735,6 +1735,14 @@ function unifyTermListAppend(a, b, subst) {
|
|
|
1735
1735
|
});
|
|
1736
1736
|
}
|
|
1737
1737
|
|
|
1738
|
+
function unifyTermMaybe(target, value, subst) {
|
|
1739
|
+
// Treat blanks as wildcards (succeed once without binding).
|
|
1740
|
+
if (target instanceof Blank) return [{ ...subst }];
|
|
1741
|
+
|
|
1742
|
+
const s2 = unifyTerm(target, value, subst);
|
|
1743
|
+
return s2 !== null ? [s2] : [];
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1738
1746
|
function unifyTermWithOptions(a, b, subst, opts) {
|
|
1739
1747
|
a = applySubstTerm(a, subst);
|
|
1740
1748
|
b = applySubstTerm(b, subst);
|
|
@@ -3742,6 +3750,15 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3742
3750
|
s2[g.o.name] = lit;
|
|
3743
3751
|
return [s2];
|
|
3744
3752
|
}
|
|
3753
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3754
|
+
|
|
3755
|
+
// Accept typed numeric literals too (e.g., "3"^^xsd:float) if numerically equal.
|
|
3756
|
+
if (numEqualTerm(g.o, rVal)) return [{ ...subst }];
|
|
3757
|
+
|
|
3758
|
+
// Fallback to strict unification
|
|
3759
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
3760
|
+
return s2 !== null ? [s2] : [];
|
|
3761
|
+
}
|
|
3745
3762
|
|
|
3746
3763
|
// math:ceiling (Eyeling extension)
|
|
3747
3764
|
// Schema: $s+ math:ceiling $o-
|
|
@@ -3749,13 +3766,14 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3749
3766
|
if (pv === MATH_NS + 'ceiling') {
|
|
3750
3767
|
const info = parseNumericLiteralInfo(g.s);
|
|
3751
3768
|
if (!info) return [];
|
|
3752
|
-
if (
|
|
3753
|
-
//
|
|
3769
|
+
if (info.kind === 'bigint') {
|
|
3770
|
+
// Already integral
|
|
3754
3771
|
const lit = internLiteral(String(info.value));
|
|
3755
3772
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3756
3773
|
}
|
|
3757
|
-
|
|
3758
|
-
|
|
3774
|
+
const n = info.value;
|
|
3775
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) return [];
|
|
3776
|
+
const lit = internLiteral(String(Math.ceil(n)));
|
|
3759
3777
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3760
3778
|
}
|
|
3761
3779
|
|
|
@@ -3765,25 +3783,16 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3765
3783
|
if (pv === MATH_NS + 'floor') {
|
|
3766
3784
|
const info = parseNumericLiteralInfo(g.s);
|
|
3767
3785
|
if (!info) return [];
|
|
3768
|
-
if (
|
|
3786
|
+
if (info.kind === 'bigint') {
|
|
3769
3787
|
const lit = internLiteral(String(info.value));
|
|
3770
3788
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3771
3789
|
}
|
|
3772
|
-
|
|
3773
|
-
|
|
3790
|
+
const n = info.value;
|
|
3791
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) return [];
|
|
3792
|
+
const lit = internLiteral(String(Math.floor(n)));
|
|
3774
3793
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3775
3794
|
}
|
|
3776
3795
|
|
|
3777
|
-
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3778
|
-
|
|
3779
|
-
// Accept typed numeric literals too (e.g., "3"^^xsd:float) if numerically equal.
|
|
3780
|
-
if (numEqualTerm(g.o, rVal)) return [{ ...subst }];
|
|
3781
|
-
|
|
3782
|
-
// Fallback to strict unification
|
|
3783
|
-
const s2 = unifyTerm(g.o, lit, subst);
|
|
3784
|
-
return s2 !== null ? [s2] : [];
|
|
3785
|
-
}
|
|
3786
|
-
|
|
3787
3796
|
// -----------------------------------------------------------------
|
|
3788
3797
|
// 4.3 time: builtins
|
|
3789
3798
|
// -----------------------------------------------------------------
|
|
@@ -4570,48 +4579,42 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4570
4579
|
s2[g.o.name] = ty;
|
|
4571
4580
|
return [s2];
|
|
4572
4581
|
}
|
|
4582
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4583
|
+
|
|
4584
|
+
const s2 = unifyTerm(g.o, ty, subst);
|
|
4585
|
+
return s2 !== null ? [s2] : [];
|
|
4586
|
+
}
|
|
4573
4587
|
|
|
4574
4588
|
// log:isIRI / log:isLiteral / log:isBlank / log:isNumeric / log:isTriple (Eyeling extensions)
|
|
4575
4589
|
// Schema: $s+ log:isIRI $o? (succeeds when s matches; o may be 'true' or a variable)
|
|
4576
|
-
|
|
4577
|
-
if (obj instanceof Blank) return [subst0];
|
|
4578
|
-
const tTrue = internLiteral('true');
|
|
4579
|
-
const s2 = unifyTermMaybe(obj, tTrue, subst0);
|
|
4580
|
-
return s2 ? [s2] : [];
|
|
4581
|
-
}
|
|
4590
|
+
const __BOOL_TRUE = internLiteral('true');
|
|
4582
4591
|
|
|
4583
4592
|
if (pv === LOG_NS + 'isIRI') {
|
|
4584
4593
|
if (!(g.s instanceof Iri)) return [];
|
|
4585
|
-
return
|
|
4594
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
4586
4595
|
}
|
|
4587
4596
|
|
|
4588
4597
|
if (pv === LOG_NS + 'isLiteral') {
|
|
4589
4598
|
if (!(g.s instanceof Literal)) return [];
|
|
4590
|
-
return
|
|
4599
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
4591
4600
|
}
|
|
4592
4601
|
|
|
4593
4602
|
if (pv === LOG_NS + 'isBlank') {
|
|
4594
4603
|
if (!(g.s instanceof Blank)) return [];
|
|
4595
|
-
return
|
|
4604
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
4596
4605
|
}
|
|
4597
4606
|
|
|
4598
4607
|
if (pv === LOG_NS + 'isNumeric') {
|
|
4599
4608
|
if (!(g.s instanceof Literal)) return [];
|
|
4600
4609
|
const dt = numericDatatypeOfTerm(g.s);
|
|
4601
4610
|
if (!dt) return [];
|
|
4602
|
-
return
|
|
4611
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
4603
4612
|
}
|
|
4604
4613
|
|
|
4605
4614
|
if (pv === LOG_NS + 'isTriple') {
|
|
4606
4615
|
if (!(g.s instanceof GraphTerm)) return [];
|
|
4607
4616
|
if (g.s.triples.length !== 1) return [];
|
|
4608
|
-
return
|
|
4609
|
-
}
|
|
4610
|
-
|
|
4611
|
-
if (g.o instanceof Blank) return [{ ...subst }];
|
|
4612
|
-
|
|
4613
|
-
const s2 = unifyTerm(g.o, ty, subst);
|
|
4614
|
-
return s2 !== null ? [s2] : [];
|
|
4617
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
4615
4618
|
}
|
|
4616
4619
|
|
|
4617
4620
|
// log:dtlit
|
|
@@ -5086,6 +5089,9 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
5086
5089
|
skolemCache.set(key, iri);
|
|
5087
5090
|
}
|
|
5088
5091
|
|
|
5092
|
+
return unifyTermMaybe(g.o, iri, subst);
|
|
5093
|
+
}
|
|
5094
|
+
|
|
5089
5095
|
// log:uuid / log:struuid (Eyeling extensions)
|
|
5090
5096
|
// NOTE: these generate fresh values and can affect termination; prefer log:skolem for deterministic IDs.
|
|
5091
5097
|
//
|
|
@@ -5103,11 +5109,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
5103
5109
|
return unifyTermMaybe(g.o, lit, subst);
|
|
5104
5110
|
}
|
|
5105
5111
|
|
|
5106
|
-
|
|
5107
|
-
const s2 = unifyTerm(goal.o, iri, subst);
|
|
5108
|
-
return s2 !== null ? [s2] : [];
|
|
5109
|
-
}
|
|
5110
|
-
|
|
5111
5112
|
// log:uri
|
|
5112
5113
|
if (pv === LOG_NS + 'uri') {
|
|
5113
5114
|
// Direction 1: subject is an IRI -> object is its string representation
|
|
@@ -5211,6 +5212,19 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
5211
5212
|
args.push(aStr);
|
|
5212
5213
|
}
|
|
5213
5214
|
|
|
5215
|
+
const formatted = simpleStringFormat(fmtStr, args);
|
|
5216
|
+
if (formatted === null) return []; // unsupported format specifier(s)
|
|
5217
|
+
|
|
5218
|
+
const lit = makeStringLiteral(formatted);
|
|
5219
|
+
if (g.o instanceof Var) {
|
|
5220
|
+
const s2 = { ...subst };
|
|
5221
|
+
s2[g.o.name] = lit;
|
|
5222
|
+
return [s2];
|
|
5223
|
+
}
|
|
5224
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
5225
|
+
return s2 !== null ? [s2] : [];
|
|
5226
|
+
}
|
|
5227
|
+
|
|
5214
5228
|
// string:length (Eyeling extension)
|
|
5215
5229
|
// Schema: $s+ string:length $o-
|
|
5216
5230
|
if (pv === STRING_NS + 'length') {
|
|
@@ -5246,46 +5260,37 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
5246
5260
|
// NOTE: start is 1-based (SPARQL SUBSTR), len is optional.
|
|
5247
5261
|
if (pv === STRING_NS + 'substring') {
|
|
5248
5262
|
if (!(g.s instanceof ListTerm)) return [];
|
|
5249
|
-
const
|
|
5250
|
-
if (
|
|
5251
|
-
|
|
5263
|
+
const elems = g.s.elems;
|
|
5264
|
+
if (elems.length !== 2 && elems.length !== 3) return [];
|
|
5265
|
+
|
|
5266
|
+
const s0 = termToJsStringDecoded(elems[0]);
|
|
5252
5267
|
if (s0 === null) return [];
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
5268
|
+
|
|
5269
|
+
const startInfo = parseNumericLiteralInfo(elems[1]);
|
|
5270
|
+
if (!startInfo) return [];
|
|
5271
|
+
let start = startInfo.kind === 'bigint' ? Number(startInfo.value) : startInfo.value;
|
|
5272
|
+
if (!Number.isFinite(start) || Number.isNaN(start)) return [];
|
|
5273
|
+
start = Math.floor(start);
|
|
5257
5274
|
start = Math.max(1, start);
|
|
5258
5275
|
|
|
5259
5276
|
let outStr = '';
|
|
5260
|
-
if (
|
|
5277
|
+
if (elems.length === 2) {
|
|
5261
5278
|
outStr = s0.slice(start - 1);
|
|
5262
5279
|
} else {
|
|
5263
|
-
const lenInfo = parseNumericLiteralInfo(
|
|
5264
|
-
if (!lenInfo
|
|
5265
|
-
let
|
|
5266
|
-
if (!Number.isFinite(
|
|
5267
|
-
|
|
5268
|
-
|
|
5280
|
+
const lenInfo = parseNumericLiteralInfo(elems[2]);
|
|
5281
|
+
if (!lenInfo) return [];
|
|
5282
|
+
let length = lenInfo.kind === 'bigint' ? Number(lenInfo.value) : lenInfo.value;
|
|
5283
|
+
if (!Number.isFinite(length) || Number.isNaN(length)) return [];
|
|
5284
|
+
length = Math.floor(length);
|
|
5285
|
+
|
|
5286
|
+
if (length <= 0) outStr = '';
|
|
5287
|
+
else outStr = s0.slice(start - 1, start - 1 + length);
|
|
5269
5288
|
}
|
|
5270
5289
|
|
|
5271
5290
|
const lit = makeStringLiteral(outStr);
|
|
5272
5291
|
return unifyTermMaybe(g.o, lit, subst);
|
|
5273
5292
|
}
|
|
5274
5293
|
|
|
5275
|
-
|
|
5276
|
-
const formatted = simpleStringFormat(fmtStr, args);
|
|
5277
|
-
if (formatted === null) return []; // unsupported format specifier(s)
|
|
5278
|
-
|
|
5279
|
-
const lit = makeStringLiteral(formatted);
|
|
5280
|
-
if (g.o instanceof Var) {
|
|
5281
|
-
const s2 = { ...subst };
|
|
5282
|
-
s2[g.o.name] = lit;
|
|
5283
|
-
return [s2];
|
|
5284
|
-
}
|
|
5285
|
-
const s2 = unifyTerm(g.o, lit, subst);
|
|
5286
|
-
return s2 !== null ? [s2] : [];
|
|
5287
|
-
}
|
|
5288
|
-
|
|
5289
5294
|
// string:jsonPointer
|
|
5290
5295
|
// Schema: ( $jsonText $pointer ) string:jsonPointer $value
|
|
5291
5296
|
if (pv === STRING_NS + 'jsonPointer') {
|
package/lib/engine.js
CHANGED
|
@@ -1050,6 +1050,14 @@ function unifyTermListAppend(a, b, subst) {
|
|
|
1050
1050
|
});
|
|
1051
1051
|
}
|
|
1052
1052
|
|
|
1053
|
+
function unifyTermMaybe(target, value, subst) {
|
|
1054
|
+
// Treat blanks as wildcards (succeed once without binding).
|
|
1055
|
+
if (target instanceof Blank) return [{ ...subst }];
|
|
1056
|
+
|
|
1057
|
+
const s2 = unifyTerm(target, value, subst);
|
|
1058
|
+
return s2 !== null ? [s2] : [];
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1053
1061
|
function unifyTermWithOptions(a, b, subst, opts) {
|
|
1054
1062
|
a = applySubstTerm(a, subst);
|
|
1055
1063
|
b = applySubstTerm(b, subst);
|
|
@@ -3057,6 +3065,15 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3057
3065
|
s2[g.o.name] = lit;
|
|
3058
3066
|
return [s2];
|
|
3059
3067
|
}
|
|
3068
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3069
|
+
|
|
3070
|
+
// Accept typed numeric literals too (e.g., "3"^^xsd:float) if numerically equal.
|
|
3071
|
+
if (numEqualTerm(g.o, rVal)) return [{ ...subst }];
|
|
3072
|
+
|
|
3073
|
+
// Fallback to strict unification
|
|
3074
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
3075
|
+
return s2 !== null ? [s2] : [];
|
|
3076
|
+
}
|
|
3060
3077
|
|
|
3061
3078
|
// math:ceiling (Eyeling extension)
|
|
3062
3079
|
// Schema: $s+ math:ceiling $o-
|
|
@@ -3064,13 +3081,14 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3064
3081
|
if (pv === MATH_NS + 'ceiling') {
|
|
3065
3082
|
const info = parseNumericLiteralInfo(g.s);
|
|
3066
3083
|
if (!info) return [];
|
|
3067
|
-
if (
|
|
3068
|
-
//
|
|
3084
|
+
if (info.kind === 'bigint') {
|
|
3085
|
+
// Already integral
|
|
3069
3086
|
const lit = internLiteral(String(info.value));
|
|
3070
3087
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3071
3088
|
}
|
|
3072
|
-
|
|
3073
|
-
|
|
3089
|
+
const n = info.value;
|
|
3090
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) return [];
|
|
3091
|
+
const lit = internLiteral(String(Math.ceil(n)));
|
|
3074
3092
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3075
3093
|
}
|
|
3076
3094
|
|
|
@@ -3080,25 +3098,16 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3080
3098
|
if (pv === MATH_NS + 'floor') {
|
|
3081
3099
|
const info = parseNumericLiteralInfo(g.s);
|
|
3082
3100
|
if (!info) return [];
|
|
3083
|
-
if (
|
|
3101
|
+
if (info.kind === 'bigint') {
|
|
3084
3102
|
const lit = internLiteral(String(info.value));
|
|
3085
3103
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3086
3104
|
}
|
|
3087
|
-
|
|
3088
|
-
|
|
3105
|
+
const n = info.value;
|
|
3106
|
+
if (Number.isNaN(n) || !Number.isFinite(n)) return [];
|
|
3107
|
+
const lit = internLiteral(String(Math.floor(n)));
|
|
3089
3108
|
return unifyTermMaybe(g.o, lit, subst);
|
|
3090
3109
|
}
|
|
3091
3110
|
|
|
3092
|
-
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3093
|
-
|
|
3094
|
-
// Accept typed numeric literals too (e.g., "3"^^xsd:float) if numerically equal.
|
|
3095
|
-
if (numEqualTerm(g.o, rVal)) return [{ ...subst }];
|
|
3096
|
-
|
|
3097
|
-
// Fallback to strict unification
|
|
3098
|
-
const s2 = unifyTerm(g.o, lit, subst);
|
|
3099
|
-
return s2 !== null ? [s2] : [];
|
|
3100
|
-
}
|
|
3101
|
-
|
|
3102
3111
|
// -----------------------------------------------------------------
|
|
3103
3112
|
// 4.3 time: builtins
|
|
3104
3113
|
// -----------------------------------------------------------------
|
|
@@ -3885,48 +3894,42 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
3885
3894
|
s2[g.o.name] = ty;
|
|
3886
3895
|
return [s2];
|
|
3887
3896
|
}
|
|
3897
|
+
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3898
|
+
|
|
3899
|
+
const s2 = unifyTerm(g.o, ty, subst);
|
|
3900
|
+
return s2 !== null ? [s2] : [];
|
|
3901
|
+
}
|
|
3888
3902
|
|
|
3889
3903
|
// log:isIRI / log:isLiteral / log:isBlank / log:isNumeric / log:isTriple (Eyeling extensions)
|
|
3890
3904
|
// Schema: $s+ log:isIRI $o? (succeeds when s matches; o may be 'true' or a variable)
|
|
3891
|
-
|
|
3892
|
-
if (obj instanceof Blank) return [subst0];
|
|
3893
|
-
const tTrue = internLiteral('true');
|
|
3894
|
-
const s2 = unifyTermMaybe(obj, tTrue, subst0);
|
|
3895
|
-
return s2 ? [s2] : [];
|
|
3896
|
-
}
|
|
3905
|
+
const __BOOL_TRUE = internLiteral('true');
|
|
3897
3906
|
|
|
3898
3907
|
if (pv === LOG_NS + 'isIRI') {
|
|
3899
3908
|
if (!(g.s instanceof Iri)) return [];
|
|
3900
|
-
return
|
|
3909
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
3901
3910
|
}
|
|
3902
3911
|
|
|
3903
3912
|
if (pv === LOG_NS + 'isLiteral') {
|
|
3904
3913
|
if (!(g.s instanceof Literal)) return [];
|
|
3905
|
-
return
|
|
3914
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
3906
3915
|
}
|
|
3907
3916
|
|
|
3908
3917
|
if (pv === LOG_NS + 'isBlank') {
|
|
3909
3918
|
if (!(g.s instanceof Blank)) return [];
|
|
3910
|
-
return
|
|
3919
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
3911
3920
|
}
|
|
3912
3921
|
|
|
3913
3922
|
if (pv === LOG_NS + 'isNumeric') {
|
|
3914
3923
|
if (!(g.s instanceof Literal)) return [];
|
|
3915
3924
|
const dt = numericDatatypeOfTerm(g.s);
|
|
3916
3925
|
if (!dt) return [];
|
|
3917
|
-
return
|
|
3926
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
3918
3927
|
}
|
|
3919
3928
|
|
|
3920
3929
|
if (pv === LOG_NS + 'isTriple') {
|
|
3921
3930
|
if (!(g.s instanceof GraphTerm)) return [];
|
|
3922
3931
|
if (g.s.triples.length !== 1) return [];
|
|
3923
|
-
return
|
|
3924
|
-
}
|
|
3925
|
-
|
|
3926
|
-
if (g.o instanceof Blank) return [{ ...subst }];
|
|
3927
|
-
|
|
3928
|
-
const s2 = unifyTerm(g.o, ty, subst);
|
|
3929
|
-
return s2 !== null ? [s2] : [];
|
|
3932
|
+
return unifyTermMaybe(g.o, __BOOL_TRUE, subst);
|
|
3930
3933
|
}
|
|
3931
3934
|
|
|
3932
3935
|
// log:dtlit
|
|
@@ -4401,6 +4404,9 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4401
4404
|
skolemCache.set(key, iri);
|
|
4402
4405
|
}
|
|
4403
4406
|
|
|
4407
|
+
return unifyTermMaybe(g.o, iri, subst);
|
|
4408
|
+
}
|
|
4409
|
+
|
|
4404
4410
|
// log:uuid / log:struuid (Eyeling extensions)
|
|
4405
4411
|
// NOTE: these generate fresh values and can affect termination; prefer log:skolem for deterministic IDs.
|
|
4406
4412
|
//
|
|
@@ -4418,11 +4424,6 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4418
4424
|
return unifyTermMaybe(g.o, lit, subst);
|
|
4419
4425
|
}
|
|
4420
4426
|
|
|
4421
|
-
|
|
4422
|
-
const s2 = unifyTerm(goal.o, iri, subst);
|
|
4423
|
-
return s2 !== null ? [s2] : [];
|
|
4424
|
-
}
|
|
4425
|
-
|
|
4426
4427
|
// log:uri
|
|
4427
4428
|
if (pv === LOG_NS + 'uri') {
|
|
4428
4429
|
// Direction 1: subject is an IRI -> object is its string representation
|
|
@@ -4526,6 +4527,19 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4526
4527
|
args.push(aStr);
|
|
4527
4528
|
}
|
|
4528
4529
|
|
|
4530
|
+
const formatted = simpleStringFormat(fmtStr, args);
|
|
4531
|
+
if (formatted === null) return []; // unsupported format specifier(s)
|
|
4532
|
+
|
|
4533
|
+
const lit = makeStringLiteral(formatted);
|
|
4534
|
+
if (g.o instanceof Var) {
|
|
4535
|
+
const s2 = { ...subst };
|
|
4536
|
+
s2[g.o.name] = lit;
|
|
4537
|
+
return [s2];
|
|
4538
|
+
}
|
|
4539
|
+
const s2 = unifyTerm(g.o, lit, subst);
|
|
4540
|
+
return s2 !== null ? [s2] : [];
|
|
4541
|
+
}
|
|
4542
|
+
|
|
4529
4543
|
// string:length (Eyeling extension)
|
|
4530
4544
|
// Schema: $s+ string:length $o-
|
|
4531
4545
|
if (pv === STRING_NS + 'length') {
|
|
@@ -4561,46 +4575,37 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen, maxResults) {
|
|
|
4561
4575
|
// NOTE: start is 1-based (SPARQL SUBSTR), len is optional.
|
|
4562
4576
|
if (pv === STRING_NS + 'substring') {
|
|
4563
4577
|
if (!(g.s instanceof ListTerm)) return [];
|
|
4564
|
-
const
|
|
4565
|
-
if (
|
|
4566
|
-
|
|
4578
|
+
const elems = g.s.elems;
|
|
4579
|
+
if (elems.length !== 2 && elems.length !== 3) return [];
|
|
4580
|
+
|
|
4581
|
+
const s0 = termToJsStringDecoded(elems[0]);
|
|
4567
4582
|
if (s0 === null) return [];
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4583
|
+
|
|
4584
|
+
const startInfo = parseNumericLiteralInfo(elems[1]);
|
|
4585
|
+
if (!startInfo) return [];
|
|
4586
|
+
let start = startInfo.kind === 'bigint' ? Number(startInfo.value) : startInfo.value;
|
|
4587
|
+
if (!Number.isFinite(start) || Number.isNaN(start)) return [];
|
|
4588
|
+
start = Math.floor(start);
|
|
4572
4589
|
start = Math.max(1, start);
|
|
4573
4590
|
|
|
4574
4591
|
let outStr = '';
|
|
4575
|
-
if (
|
|
4592
|
+
if (elems.length === 2) {
|
|
4576
4593
|
outStr = s0.slice(start - 1);
|
|
4577
4594
|
} else {
|
|
4578
|
-
const lenInfo = parseNumericLiteralInfo(
|
|
4579
|
-
if (!lenInfo
|
|
4580
|
-
let
|
|
4581
|
-
if (!Number.isFinite(
|
|
4582
|
-
|
|
4583
|
-
|
|
4595
|
+
const lenInfo = parseNumericLiteralInfo(elems[2]);
|
|
4596
|
+
if (!lenInfo) return [];
|
|
4597
|
+
let length = lenInfo.kind === 'bigint' ? Number(lenInfo.value) : lenInfo.value;
|
|
4598
|
+
if (!Number.isFinite(length) || Number.isNaN(length)) return [];
|
|
4599
|
+
length = Math.floor(length);
|
|
4600
|
+
|
|
4601
|
+
if (length <= 0) outStr = '';
|
|
4602
|
+
else outStr = s0.slice(start - 1, start - 1 + length);
|
|
4584
4603
|
}
|
|
4585
4604
|
|
|
4586
4605
|
const lit = makeStringLiteral(outStr);
|
|
4587
4606
|
return unifyTermMaybe(g.o, lit, subst);
|
|
4588
4607
|
}
|
|
4589
4608
|
|
|
4590
|
-
|
|
4591
|
-
const formatted = simpleStringFormat(fmtStr, args);
|
|
4592
|
-
if (formatted === null) return []; // unsupported format specifier(s)
|
|
4593
|
-
|
|
4594
|
-
const lit = makeStringLiteral(formatted);
|
|
4595
|
-
if (g.o instanceof Var) {
|
|
4596
|
-
const s2 = { ...subst };
|
|
4597
|
-
s2[g.o.name] = lit;
|
|
4598
|
-
return [s2];
|
|
4599
|
-
}
|
|
4600
|
-
const s2 = unifyTerm(g.o, lit, subst);
|
|
4601
|
-
return s2 !== null ? [s2] : [];
|
|
4602
|
-
}
|
|
4603
|
-
|
|
4604
4609
|
// string:jsonPointer
|
|
4605
4610
|
// Schema: ( $jsonText $pointer ) string:jsonPointer $value
|
|
4606
4611
|
if (pv === STRING_NS + 'jsonPointer') {
|