eyeling 1.6.16 → 1.6.17

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.
Files changed (2) hide show
  1. package/eyeling.js +173 -234
  2. package/package.json +1 -1
package/eyeling.js CHANGED
@@ -1993,6 +1993,10 @@ function applySubstTriple(tr, s) {
1993
1993
  return new Triple(applySubstTerm(tr.s, s), applySubstTerm(tr.p, s), applySubstTerm(tr.o, s));
1994
1994
  }
1995
1995
 
1996
+ function iriValue(t) {
1997
+ return t instanceof Iri ? t.value : null;
1998
+ }
1999
+
1996
2000
  function unifyOpenWithList(prefix, tailv, ys, subst) {
1997
2001
  if (ys.length < prefix.length) return null;
1998
2002
  let s2 = { ...subst };
@@ -2524,6 +2528,10 @@ function parseXsdFloatSpecialLex(s) {
2524
2528
  return null;
2525
2529
  }
2526
2530
 
2531
+ // ============================================================================
2532
+ // Math builtin helpers
2533
+ // ============================================================================
2534
+
2527
2535
  function formatXsdFloatSpecialLex(n) {
2528
2536
  if (n === Infinity) return 'INF';
2529
2537
  if (n === -Infinity) return '-INF';
@@ -2678,6 +2686,10 @@ function pow10n(k) {
2678
2686
  return 10n ** BigInt(k);
2679
2687
  }
2680
2688
 
2689
+ // ============================================================================
2690
+ // Time & duration builtin helpers
2691
+ // ============================================================================
2692
+
2681
2693
  function parseXsdDateTerm(t) {
2682
2694
  if (!(t instanceof Literal)) return null;
2683
2695
  const [lex, dt] = literalParts(t.value);
@@ -2759,7 +2771,7 @@ function parseNumericForCompareTerm(t) {
2759
2771
  }
2760
2772
 
2761
2773
  function cmpNumericInfo(aInfo, bInfo, op) {
2762
- // op is one of ">", "<", ">=", "<="
2774
+ // op is one of ">", "<", ">=", "<=", "==", "!="
2763
2775
  if (!aInfo || !bInfo) return false;
2764
2776
 
2765
2777
  if (aInfo.kind === 'bigint' && bInfo.kind === 'bigint') {
@@ -2784,6 +2796,19 @@ function cmpNumericInfo(aInfo, bInfo, op) {
2784
2796
  return false;
2785
2797
  }
2786
2798
 
2799
+ function evalNumericComparisonBuiltin(g, subst, op) {
2800
+ const aInfo = parseNumericForCompareTerm(g.s);
2801
+ const bInfo = parseNumericForCompareTerm(g.o);
2802
+ if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, op)) return [{ ...subst }];
2803
+
2804
+ if (g.s instanceof ListTerm && g.s.elems.length === 2) {
2805
+ const a2 = parseNumericForCompareTerm(g.s.elems[0]);
2806
+ const b2 = parseNumericForCompareTerm(g.s.elems[1]);
2807
+ if (a2 && b2 && cmpNumericInfo(a2, b2, op)) return [{ ...subst }];
2808
+ }
2809
+ return [];
2810
+ }
2811
+
2787
2812
  function parseNumOrDuration(t) {
2788
2813
  const n = parseNum(t);
2789
2814
  if (n !== null) return n;
@@ -2816,24 +2841,6 @@ function formatDurationLiteralFromSeconds(secs) {
2816
2841
  const literalLex = neg ? `"-P${days}D"` : `"P${days}D"`;
2817
2842
  return new Literal(`${literalLex}^^<${XSD_NS}duration>`);
2818
2843
  }
2819
-
2820
- function listAppendSplit(parts, resElems, subst) {
2821
- if (!parts.length) {
2822
- if (!resElems.length) return [{ ...subst }];
2823
- return [];
2824
- }
2825
- const out = [];
2826
- const n = resElems.length;
2827
- for (let k = 0; k <= n; k++) {
2828
- const left = new ListTerm(resElems.slice(0, k));
2829
- let s1 = unifyTermListAppend(parts[0], left, subst);
2830
- if (s1 === null) continue;
2831
- const restElems = resElems.slice(k);
2832
- out.push(...listAppendSplit(parts.slice(1), restElems, s1));
2833
- }
2834
- return out;
2835
- }
2836
-
2837
2844
  function numEqualTerm(t, n, eps = 1e-9) {
2838
2845
  const v = parseNum(t);
2839
2846
  if (v === null) return false;
@@ -3010,6 +3017,27 @@ function evalUnaryMathRel(g, subst, forwardFn, inverseFn /* may be null */) {
3010
3017
  return [];
3011
3018
  }
3012
3019
 
3020
+ // ============================================================================
3021
+ // List builtin helpers
3022
+ // ============================================================================
3023
+
3024
+ function listAppendSplit(parts, resElems, subst) {
3025
+ if (!parts.length) {
3026
+ if (!resElems.length) return [{ ...subst }];
3027
+ return [];
3028
+ }
3029
+ const out = [];
3030
+ const n = resElems.length;
3031
+ for (let k = 0; k <= n; k++) {
3032
+ const left = new ListTerm(resElems.slice(0, k));
3033
+ let s1 = unifyTermListAppend(parts[0], left, subst);
3034
+ if (s1 === null) continue;
3035
+ const restElems = resElems.slice(k);
3036
+ out.push(...listAppendSplit(parts.slice(1), restElems, s1));
3037
+ }
3038
+ return out;
3039
+ }
3040
+
3013
3041
  function evalListFirstLikeBuiltin(sTerm, oTerm, subst) {
3014
3042
  if (!(sTerm instanceof ListTerm)) return [];
3015
3043
  if (!sTerm.elems.length) return [];
@@ -3043,174 +3071,85 @@ function evalListRestLikeBuiltin(sTerm, oTerm, subst) {
3043
3071
  }
3044
3072
 
3045
3073
  // ============================================================================
3046
- // Backward proof & builtins mutual recursion — declarations first
3074
+ // Crypto builtin helpers
3047
3075
  // ============================================================================
3048
3076
 
3049
- function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3050
- const g = applySubstTriple(goal, subst);
3077
+ function hashLiteralTerm(t, algo) {
3078
+ if (!(t instanceof Literal)) return null;
3079
+ const [lex] = literalParts(t.value);
3080
+ const input = stripQuotes(lex);
3081
+ try {
3082
+ const digest = nodeCrypto.createHash(algo).update(input, 'utf8').digest('hex');
3083
+ return new Literal(JSON.stringify(digest));
3084
+ } catch (e) {
3085
+ return null;
3086
+ }
3087
+ }
3051
3088
 
3052
- function hashLiteral(t, algo) {
3053
- // Accept only literals, interpret lexical form as UTF-8 string
3054
- if (!(t instanceof Literal)) return null;
3055
- const [lex, _dt] = literalParts(t.value);
3056
- const input = stripQuotes(lex);
3057
- try {
3058
- const digest = nodeCrypto.createHash(algo).update(input, 'utf8').digest('hex');
3059
- // plain string literal with the hex digest
3060
- return new Literal(JSON.stringify(digest));
3061
- } catch (e) {
3062
- return null;
3063
- }
3089
+ function evalCryptoHashBuiltin(g, subst, algo) {
3090
+ const lit = hashLiteralTerm(g.s, algo);
3091
+ if (!lit) return [];
3092
+ if (g.o instanceof Var) {
3093
+ const s2 = { ...subst };
3094
+ s2[g.o.name] = lit;
3095
+ return [s2];
3064
3096
  }
3097
+ const s2 = unifyTerm(g.o, lit, subst);
3098
+ return s2 !== null ? [s2] : [];
3099
+ }
3100
+
3101
+ // ============================================================================
3102
+ // Builtin evaluation
3103
+ // ============================================================================
3104
+ // Backward proof & builtins mutual recursion — declarations first
3105
+
3106
+ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3107
+ const g = applySubstTriple(goal, subst);
3108
+ const pv = iriValue(g.p);
3109
+ if (pv === null) return null;
3065
3110
 
3066
3111
  // -----------------------------------------------------------------
3067
3112
  // 4.1 crypto: builtins
3068
3113
  // -----------------------------------------------------------------
3069
3114
 
3070
- // crypto:sha
3071
- // true iff ?o is the SHA-1 hash of the subject string.
3072
- if (g.p instanceof Iri && g.p.value === CRYPTO_NS + 'sha') {
3073
- const lit = hashLiteral(g.s, 'sha1');
3074
- if (!lit) return [];
3075
- if (g.o instanceof Var) {
3076
- const s2 = { ...subst };
3077
- s2[g.o.name] = lit;
3078
- return [s2];
3079
- }
3080
- const s2 = unifyTerm(g.o, lit, subst);
3081
- return s2 !== null ? [s2] : [];
3082
- }
3083
-
3084
- // crypto:md5
3085
- if (g.p instanceof Iri && g.p.value === CRYPTO_NS + 'md5') {
3086
- const lit = hashLiteral(g.s, 'md5');
3087
- if (!lit) return [];
3088
- if (g.o instanceof Var) {
3089
- const s2 = { ...subst };
3090
- s2[g.o.name] = lit;
3091
- return [s2];
3092
- }
3093
- const s2 = unifyTerm(g.o, lit, subst);
3094
- return s2 !== null ? [s2] : [];
3095
- }
3096
-
3097
- // crypto:sha256
3098
- if (g.p instanceof Iri && g.p.value === CRYPTO_NS + 'sha256') {
3099
- const lit = hashLiteral(g.s, 'sha256');
3100
- if (!lit) return [];
3101
- if (g.o instanceof Var) {
3102
- const s2 = { ...subst };
3103
- s2[g.o.name] = lit;
3104
- return [s2];
3105
- }
3106
- const s2 = unifyTerm(g.o, lit, subst);
3107
- return s2 !== null ? [s2] : [];
3108
- }
3109
-
3110
- // crypto:sha512
3111
- if (g.p instanceof Iri && g.p.value === CRYPTO_NS + 'sha512') {
3112
- const lit = hashLiteral(g.s, 'sha512');
3113
- if (!lit) return [];
3114
- if (g.o instanceof Var) {
3115
- const s2 = { ...subst };
3116
- s2[g.o.name] = lit;
3117
- return [s2];
3118
- }
3119
- const s2 = unifyTerm(g.o, lit, subst);
3120
- return s2 !== null ? [s2] : [];
3121
- }
3115
+ // crypto:sha, crypto:md5, crypto:sha256, crypto:sha512
3116
+ // Digest builtins. crypto:sha uses SHA-1 per the N3/crypto convention.
3117
+ const cryptoAlgo =
3118
+ pv === CRYPTO_NS + 'sha'
3119
+ ? 'sha1'
3120
+ : pv === CRYPTO_NS + 'md5'
3121
+ ? 'md5'
3122
+ : pv === CRYPTO_NS + 'sha256'
3123
+ ? 'sha256'
3124
+ : pv === CRYPTO_NS + 'sha512'
3125
+ ? 'sha512'
3126
+ : null;
3127
+ if (cryptoAlgo) return evalCryptoHashBuiltin(g, subst, cryptoAlgo);
3122
3128
 
3123
3129
  // -----------------------------------------------------------------
3124
3130
  // 4.2 math: builtins
3125
3131
  // -----------------------------------------------------------------
3126
3132
 
3127
- // math:greaterThan
3128
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'greaterThan') {
3129
- const aInfo = parseNumericForCompareTerm(g.s);
3130
- const bInfo = parseNumericForCompareTerm(g.o);
3131
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '>')) return [{ ...subst }];
3132
-
3133
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3134
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3135
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3136
- if (a2 && b2 && cmpNumericInfo(a2, b2, '>')) return [{ ...subst }];
3137
- }
3138
- return [];
3139
- }
3140
-
3141
- // math:lessThan
3142
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'lessThan') {
3143
- const aInfo = parseNumericForCompareTerm(g.s);
3144
- const bInfo = parseNumericForCompareTerm(g.o);
3145
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '<')) return [{ ...subst }];
3146
-
3147
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3148
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3149
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3150
- if (a2 && b2 && cmpNumericInfo(a2, b2, '<')) return [{ ...subst }];
3151
- }
3152
- return [];
3153
- }
3154
-
3155
- // math:notLessThan
3156
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'notLessThan') {
3157
- const aInfo = parseNumericForCompareTerm(g.s);
3158
- const bInfo = parseNumericForCompareTerm(g.o);
3159
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '>=')) return [{ ...subst }];
3160
-
3161
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3162
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3163
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3164
- if (a2 && b2 && cmpNumericInfo(a2, b2, '>=')) return [{ ...subst }];
3165
- }
3166
- return [];
3167
- }
3168
-
3169
- // math:notGreaterThan
3170
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'notGreaterThan') {
3171
- const aInfo = parseNumericForCompareTerm(g.s);
3172
- const bInfo = parseNumericForCompareTerm(g.o);
3173
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '<=')) return [{ ...subst }];
3174
-
3175
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3176
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3177
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3178
- if (a2 && b2 && cmpNumericInfo(a2, b2, '<=')) return [{ ...subst }];
3179
- }
3180
- return [];
3181
- }
3182
-
3183
- // math:equalTo
3184
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'equalTo') {
3185
- const aInfo = parseNumericForCompareTerm(g.s);
3186
- const bInfo = parseNumericForCompareTerm(g.o);
3187
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '==')) return [{ ...subst }];
3188
-
3189
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3190
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3191
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3192
- if (a2 && b2 && cmpNumericInfo(a2, b2, '==')) return [{ ...subst }];
3193
- }
3194
- return [];
3195
- }
3196
-
3197
- // math:notEqualTo
3198
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'notEqualTo') {
3199
- const aInfo = parseNumericForCompareTerm(g.s);
3200
- const bInfo = parseNumericForCompareTerm(g.o);
3201
- if (aInfo && bInfo && cmpNumericInfo(aInfo, bInfo, '!=')) return [{ ...subst }];
3202
-
3203
- if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3204
- const a2 = parseNumericForCompareTerm(g.s.elems[0]);
3205
- const b2 = parseNumericForCompareTerm(g.s.elems[1]);
3206
- if (a2 && b2 && cmpNumericInfo(a2, b2, '!=')) return [{ ...subst }];
3207
- }
3208
- return [];
3209
- }
3133
+ // math:greaterThan / lessThan / notLessThan / notGreaterThan / equalTo / notEqualTo
3134
+ const mathCmpOp =
3135
+ pv === MATH_NS + 'greaterThan'
3136
+ ? '>'
3137
+ : pv === MATH_NS + 'lessThan'
3138
+ ? '<'
3139
+ : pv === MATH_NS + 'notLessThan'
3140
+ ? '>='
3141
+ : pv === MATH_NS + 'notGreaterThan'
3142
+ ? '<='
3143
+ : pv === MATH_NS + 'equalTo'
3144
+ ? '=='
3145
+ : pv === MATH_NS + 'notEqualTo'
3146
+ ? '!='
3147
+ : null;
3148
+ if (mathCmpOp) return evalNumericComparisonBuiltin(g, subst, mathCmpOp);
3210
3149
 
3211
3150
  // math:sum
3212
3151
  // Schema: ( $s.i+ )+ math:sum $o-
3213
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'sum') {
3152
+ if (pv === MATH_NS + 'sum') {
3214
3153
  if (!(g.s instanceof ListTerm) || g.s.elems.length < 2) return [];
3215
3154
  const xs = g.s.elems;
3216
3155
 
@@ -3264,7 +3203,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3264
3203
 
3265
3204
  // math:product
3266
3205
  // Schema: ( $s.i+ )+ math:product $o-
3267
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'product') {
3206
+ if (pv === MATH_NS + 'product') {
3268
3207
  if (!(g.s instanceof ListTerm) || g.s.elems.length < 2) return [];
3269
3208
  const xs = g.s.elems;
3270
3209
 
@@ -3316,7 +3255,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3316
3255
 
3317
3256
  // math:difference
3318
3257
  // Schema: ( $s.1+ $s.2+ )+ math:difference $o-
3319
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'difference') {
3258
+ if (pv === MATH_NS + 'difference') {
3320
3259
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3321
3260
  const [a0, b0] = g.s.elems;
3322
3261
 
@@ -3404,7 +3343,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3404
3343
 
3405
3344
  // math:quotient
3406
3345
  // Schema: ( $s.1+ $s.2+ )+ math:quotient $o-
3407
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'quotient') {
3346
+ if (pv === MATH_NS + 'quotient') {
3408
3347
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3409
3348
  const [a0, b0] = g.s.elems;
3410
3349
 
@@ -3433,7 +3372,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3433
3372
  // math:integerQuotient
3434
3373
  // Schema: ( $a $b ) math:integerQuotient $q
3435
3374
  // Cwm: divide first integer by second integer, ignoring remainder. :contentReference[oaicite:1]{index=1}
3436
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'integerQuotient') {
3375
+ if (pv === MATH_NS + 'integerQuotient') {
3437
3376
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3438
3377
  const [a0, b0] = g.s.elems;
3439
3378
 
@@ -3487,7 +3426,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3487
3426
  }
3488
3427
 
3489
3428
  // math:exponentiation
3490
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'exponentiation') {
3429
+ if (pv === MATH_NS + 'exponentiation') {
3491
3430
  if (g.s instanceof ListTerm && g.s.elems.length === 2) {
3492
3431
  const baseTerm = g.s.elems[0];
3493
3432
  const expTerm = g.s.elems[1];
@@ -3534,7 +3473,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3534
3473
  }
3535
3474
 
3536
3475
  // math:absoluteValue
3537
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'absoluteValue') {
3476
+ if (pv === MATH_NS + 'absoluteValue') {
3538
3477
  const a = parseNum(g.s);
3539
3478
  if (a === null) return [];
3540
3479
 
@@ -3555,58 +3494,58 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3555
3494
  }
3556
3495
 
3557
3496
  // math:acos
3558
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'acos') {
3497
+ if (pv === MATH_NS + 'acos') {
3559
3498
  return evalUnaryMathRel(g, subst, Math.acos, Math.cos);
3560
3499
  }
3561
3500
 
3562
3501
  // math:asin
3563
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'asin') {
3502
+ if (pv === MATH_NS + 'asin') {
3564
3503
  return evalUnaryMathRel(g, subst, Math.asin, Math.sin);
3565
3504
  }
3566
3505
 
3567
3506
  // math:atan
3568
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'atan') {
3507
+ if (pv === MATH_NS + 'atan') {
3569
3508
  return evalUnaryMathRel(g, subst, Math.atan, Math.tan);
3570
3509
  }
3571
3510
 
3572
3511
  // math:sin (inverse uses principal asin)
3573
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'sin') {
3512
+ if (pv === MATH_NS + 'sin') {
3574
3513
  return evalUnaryMathRel(g, subst, Math.sin, Math.asin);
3575
3514
  }
3576
3515
 
3577
3516
  // math:cos (inverse uses principal acos)
3578
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'cos') {
3517
+ if (pv === MATH_NS + 'cos') {
3579
3518
  return evalUnaryMathRel(g, subst, Math.cos, Math.acos);
3580
3519
  }
3581
3520
 
3582
3521
  // math:tan (inverse uses principal atan)
3583
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'tan') {
3522
+ if (pv === MATH_NS + 'tan') {
3584
3523
  return evalUnaryMathRel(g, subst, Math.tan, Math.atan);
3585
3524
  }
3586
3525
 
3587
3526
  // math:sinh / cosh / tanh (guard for JS availability)
3588
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'sinh') {
3527
+ if (pv === MATH_NS + 'sinh') {
3589
3528
  if (typeof Math.sinh !== 'function' || typeof Math.asinh !== 'function') return [];
3590
3529
  return evalUnaryMathRel(g, subst, Math.sinh, Math.asinh);
3591
3530
  }
3592
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'cosh') {
3531
+ if (pv === MATH_NS + 'cosh') {
3593
3532
  if (typeof Math.cosh !== 'function' || typeof Math.acosh !== 'function') return [];
3594
3533
  return evalUnaryMathRel(g, subst, Math.cosh, Math.acosh);
3595
3534
  }
3596
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'tanh') {
3535
+ if (pv === MATH_NS + 'tanh') {
3597
3536
  if (typeof Math.tanh !== 'function' || typeof Math.atanh !== 'function') return [];
3598
3537
  return evalUnaryMathRel(g, subst, Math.tanh, Math.atanh);
3599
3538
  }
3600
3539
 
3601
3540
  // math:degrees (inverse is radians)
3602
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'degrees') {
3541
+ if (pv === MATH_NS + 'degrees') {
3603
3542
  const toDeg = (rad) => (rad * 180.0) / Math.PI;
3604
3543
  const toRad = (deg) => (deg * Math.PI) / 180.0;
3605
3544
  return evalUnaryMathRel(g, subst, toDeg, toRad);
3606
3545
  }
3607
3546
 
3608
3547
  // math:negation (inverse is itself)
3609
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'negation') {
3548
+ if (pv === MATH_NS + 'negation') {
3610
3549
  const neg = (x) => -x;
3611
3550
  return evalUnaryMathRel(g, subst, neg, neg);
3612
3551
  }
@@ -3614,7 +3553,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3614
3553
  // math:remainder
3615
3554
  // Subject is a list (dividend divisor); object is the remainder.
3616
3555
  // Schema: ( $a $b ) math:remainder $r
3617
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'remainder') {
3556
+ if (pv === MATH_NS + 'remainder') {
3618
3557
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3619
3558
  const [a0, b0] = g.s.elems;
3620
3559
 
@@ -3664,7 +3603,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3664
3603
  // If there are two such numbers, then the one closest to positive infinity is returned.
3665
3604
  // Schema: $s+ math:rounded $o-
3666
3605
  // Note: spec says $o is xsd:integer, but we also accept any numeric $o that equals the rounded value.
3667
- if (g.p instanceof Iri && g.p.value === MATH_NS + 'rounded') {
3606
+ if (pv === MATH_NS + 'rounded') {
3668
3607
  const a = parseNum(g.s);
3669
3608
  if (a === null) return [];
3670
3609
  if (Number.isNaN(a)) return [];
@@ -3693,7 +3632,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3693
3632
 
3694
3633
  // time:localTime
3695
3634
  // "" time:localTime ?D. binds ?D to “now” as xsd:dateTime.
3696
- if (g.p instanceof Iri && g.p.value === TIME_NS + 'localTime') {
3635
+ if (pv === TIME_NS + 'localTime') {
3697
3636
  const now = getNowLex();
3698
3637
 
3699
3638
  if (g.o instanceof Var) {
@@ -3715,7 +3654,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3715
3654
  // list:append
3716
3655
  // true if and only if $o is the concatenation of all lists $s.i.
3717
3656
  // Schema: ( $s.i?[*] )+ list:append $o?
3718
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'append') {
3657
+ if (pv === LIST_NS + 'append') {
3719
3658
  if (!(g.s instanceof ListTerm)) return [];
3720
3659
  const parts = g.s.elems;
3721
3660
  if (g.o instanceof ListTerm) {
@@ -3739,14 +3678,14 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3739
3678
  // list:first and rdf:first
3740
3679
  // true iff $s is a list and $o is the first member of that list.
3741
3680
  // Schema: $s+ list:first $o-
3742
- if (g.p instanceof Iri && (g.p.value === LIST_NS + 'first' || g.p.value === RDF_NS + 'first')) {
3681
+ if (pv === LIST_NS + 'first' || pv === RDF_NS + 'first') {
3743
3682
  return evalListFirstLikeBuiltin(g.s, g.o, subst);
3744
3683
  }
3745
3684
 
3746
3685
  // list:rest and rdf:rest
3747
3686
  // true iff $s is a (non-empty) list and $o is the rest (tail) of that list.
3748
3687
  // Schema: $s+ list:rest $o-
3749
- if (g.p instanceof Iri && (g.p.value === LIST_NS + 'rest' || g.p.value === RDF_NS + 'rest')) {
3688
+ if (pv === LIST_NS + 'rest' || pv === RDF_NS + 'rest') {
3750
3689
  return evalListRestLikeBuiltin(g.s, g.o, subst);
3751
3690
  }
3752
3691
 
@@ -3754,7 +3693,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3754
3693
  // Multi-solution builtin:
3755
3694
  // For a list subject $s, generate solutions by unifying $o with (index value).
3756
3695
  // This allows $o to be a variable (e.g., ?Y) or a pattern (e.g., (?i "Dewey")).
3757
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'iterate') {
3696
+ if (pv === LIST_NS + 'iterate') {
3758
3697
  if (!(g.s instanceof ListTerm)) return [];
3759
3698
  const xs = g.s.elems;
3760
3699
  const outs = [];
@@ -3795,7 +3734,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3795
3734
  // list:last
3796
3735
  // true iff $s is a list and $o is the last member of that list.
3797
3736
  // Schema: $s+ list:last $o-
3798
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'last') {
3737
+ if (pv === LIST_NS + 'last') {
3799
3738
  if (!(g.s instanceof ListTerm)) return [];
3800
3739
  const xs = g.s.elems;
3801
3740
  if (!xs.length) return [];
@@ -3807,7 +3746,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3807
3746
  // list:memberAt
3808
3747
  // true iff $s.1 is a list, $s.2 is a valid index, and $o is the member at that index.
3809
3748
  // Schema: ( $s.1+ $s.2?[*] )+ list:memberAt $o?[*]
3810
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'memberAt') {
3749
+ if (pv === LIST_NS + 'memberAt') {
3811
3750
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3812
3751
  const [listTerm, indexTerm] = g.s.elems;
3813
3752
  if (!(listTerm instanceof ListTerm)) return [];
@@ -3846,7 +3785,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3846
3785
  // list:remove
3847
3786
  // true iff $s.1 is a list and $o is that list with all occurrences of $s.2 removed.
3848
3787
  // Schema: ( $s.1+ $s.2+ )+ list:remove $o-
3849
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'remove') {
3788
+ if (pv === LIST_NS + 'remove') {
3850
3789
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
3851
3790
  const [listTerm, itemTerm] = g.s.elems;
3852
3791
  if (!(listTerm instanceof ListTerm)) return [];
@@ -3868,7 +3807,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3868
3807
  }
3869
3808
 
3870
3809
  // list:member
3871
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'member') {
3810
+ if (pv === LIST_NS + 'member') {
3872
3811
  if (!(g.s instanceof ListTerm)) return [];
3873
3812
  const outs = [];
3874
3813
  for (const x of g.s.elems) {
@@ -3879,7 +3818,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3879
3818
  }
3880
3819
 
3881
3820
  // list:in
3882
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'in') {
3821
+ if (pv === LIST_NS + 'in') {
3883
3822
  if (!(g.o instanceof ListTerm)) return [];
3884
3823
  const outs = [];
3885
3824
  for (const x of g.o.elems) {
@@ -3890,7 +3829,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3890
3829
  }
3891
3830
 
3892
3831
  // list:length (strict: do not accept integer<->decimal matches for a ground object)
3893
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'length') {
3832
+ if (pv === LIST_NS + 'length') {
3894
3833
  if (!(g.s instanceof ListTerm)) return [];
3895
3834
  const nTerm = new Literal(String(g.s.elems.length));
3896
3835
 
@@ -3904,7 +3843,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3904
3843
  }
3905
3844
 
3906
3845
  // list:notMember
3907
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'notMember') {
3846
+ if (pv === LIST_NS + 'notMember') {
3908
3847
  if (!(g.s instanceof ListTerm)) return [];
3909
3848
  for (const el of g.s.elems) {
3910
3849
  if (unifyTerm(g.o, el, subst) !== null) return [];
@@ -3913,7 +3852,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3913
3852
  }
3914
3853
 
3915
3854
  // list:reverse
3916
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'reverse') {
3855
+ if (pv === LIST_NS + 'reverse') {
3917
3856
  if (g.s instanceof ListTerm) {
3918
3857
  const rev = [...g.s.elems].reverse();
3919
3858
  const rterm = new ListTerm(rev);
@@ -3930,7 +3869,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3930
3869
  }
3931
3870
 
3932
3871
  // list:sort
3933
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'sort') {
3872
+ if (pv === LIST_NS + 'sort') {
3934
3873
  function cmpTermForSort(a, b) {
3935
3874
  if (a instanceof Literal && b instanceof Literal) {
3936
3875
  const [lexA] = literalParts(a.value);
@@ -3998,7 +3937,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
3998
3937
  }
3999
3938
 
4000
3939
  // list:map
4001
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'map') {
3940
+ if (pv === LIST_NS + 'map') {
4002
3941
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
4003
3942
  const [inputTerm, predTerm] = g.s.elems;
4004
3943
  if (!(inputTerm instanceof ListTerm)) return [];
@@ -4024,7 +3963,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4024
3963
  }
4025
3964
 
4026
3965
  // list:firstRest
4027
- if (g.p instanceof Iri && g.p.value === LIST_NS + 'firstRest') {
3966
+ if (pv === LIST_NS + 'firstRest') {
4028
3967
  if (g.s instanceof ListTerm) {
4029
3968
  if (!g.s.elems.length) return [];
4030
3969
  const first = g.s.elems[0];
@@ -4062,13 +4001,13 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4062
4001
  // -----------------------------------------------------------------
4063
4002
 
4064
4003
  // log:equalTo
4065
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'equalTo') {
4004
+ if (pv === LOG_NS + 'equalTo') {
4066
4005
  const s2 = unifyTerm(goal.s, goal.o, subst);
4067
4006
  return s2 !== null ? [s2] : [];
4068
4007
  }
4069
4008
 
4070
4009
  // log:notEqualTo
4071
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'notEqualTo') {
4010
+ if (pv === LOG_NS + 'notEqualTo') {
4072
4011
  const s2 = unifyTerm(goal.s, goal.o, subst);
4073
4012
  if (s2 !== null) return [];
4074
4013
  return [{ ...subst }];
@@ -4077,7 +4016,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4077
4016
  // log:dtlit
4078
4017
  // Schema: ( $s.1? $s.2? )? log:dtlit $o?
4079
4018
  // true iff $o is a datatyped literal with string value $s.1 and datatype IRI $s.2
4080
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'dtlit') {
4019
+ if (pv === LOG_NS + 'dtlit') {
4081
4020
  // Fully unbound (both arguments '?'-mode): treat as satisfiable, succeed once.
4082
4021
  // Required by notation3tests "success-fullUnbound-*".
4083
4022
  if (g.s instanceof Var && g.o instanceof Var) return [{ ...subst }];
@@ -4130,7 +4069,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4130
4069
  // log:langlit
4131
4070
  // Schema: ( $s.1? $s.2? )? log:langlit $o?
4132
4071
  // true iff $o is a language-tagged literal with string value $s.1 and language tag $s.2
4133
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'langlit') {
4072
+ if (pv === LOG_NS + 'langlit') {
4134
4073
  // Fully unbound (both arguments '?'-mode): treat as satisfiable, succeed once.
4135
4074
  if (g.s instanceof Var && g.o instanceof Var) return [{ ...subst }];
4136
4075
  const results = [];
@@ -4184,7 +4123,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4184
4123
  }
4185
4124
 
4186
4125
  // log:implies — expose internal forward rules as data
4187
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'implies') {
4126
+ if (pv === LOG_NS + 'implies') {
4188
4127
  const allFw = backRules.__allForwardRules || [];
4189
4128
  const results = [];
4190
4129
 
@@ -4212,7 +4151,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4212
4151
  }
4213
4152
 
4214
4153
  // log:impliedBy — expose internal backward rules as data
4215
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'impliedBy') {
4154
+ if (pv === LOG_NS + 'impliedBy') {
4216
4155
  const allBw = backRules.__allBackwardRules || backRules;
4217
4156
  const results = [];
4218
4157
 
@@ -4242,7 +4181,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4242
4181
 
4243
4182
  // log:notIncludes (EYE-style: "not provable in scope")
4244
4183
  // Delay until we have a frozen scope snapshot to avoid early success.
4245
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'notIncludes') {
4184
+ if (pv === LOG_NS + 'notIncludes') {
4246
4185
  if (!(g.o instanceof FormulaTerm)) return [];
4247
4186
 
4248
4187
  let scopeFacts = null;
@@ -4265,7 +4204,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4265
4204
  }
4266
4205
 
4267
4206
  // log:collectAllIn (scoped)
4268
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'collectAllIn') {
4207
+ if (pv === LOG_NS + 'collectAllIn') {
4269
4208
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 3) return [];
4270
4209
  const [valueTempl, clauseTerm, listTerm] = g.s.elems;
4271
4210
  if (!(clauseTerm instanceof FormulaTerm)) return [];
@@ -4294,7 +4233,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4294
4233
  }
4295
4234
 
4296
4235
  // log:forAllIn (scoped)
4297
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'forAllIn') {
4236
+ if (pv === LOG_NS + 'forAllIn') {
4298
4237
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
4299
4238
  const [whereClause, thenClause] = g.s.elems;
4300
4239
  if (!(whereClause instanceof FormulaTerm) || !(thenClause instanceof FormulaTerm)) return [];
@@ -4324,7 +4263,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4324
4263
  }
4325
4264
 
4326
4265
  // log:skolem
4327
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'skolem') {
4266
+ if (pv === LOG_NS + 'skolem') {
4328
4267
  // Subject must be ground; commonly a list, but we allow any ground term.
4329
4268
  if (!isGroundTerm(g.s)) return [];
4330
4269
 
@@ -4341,7 +4280,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4341
4280
  }
4342
4281
 
4343
4282
  // log:uri
4344
- if (g.p instanceof Iri && g.p.value === LOG_NS + 'uri') {
4283
+ if (pv === LOG_NS + 'uri') {
4345
4284
  // Direction 1: subject is an IRI -> object is its string representation
4346
4285
  if (g.s instanceof Iri) {
4347
4286
  const uriStr = g.s.value; // raw IRI string, e.g. "https://www.w3.org"
@@ -4370,7 +4309,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4370
4309
  // -----------------------------------------------------------------
4371
4310
 
4372
4311
  // string:concatenation
4373
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'concatenation') {
4312
+ if (pv === STRING_NS + 'concatenation') {
4374
4313
  if (!(g.s instanceof ListTerm)) return [];
4375
4314
  const parts = [];
4376
4315
  for (const t of g.s.elems) {
@@ -4390,7 +4329,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4390
4329
  }
4391
4330
 
4392
4331
  // string:contains
4393
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'contains') {
4332
+ if (pv === STRING_NS + 'contains') {
4394
4333
  const sStr = termToJsString(g.s);
4395
4334
  const oStr = termToJsString(g.o);
4396
4335
  if (sStr === null || oStr === null) return [];
@@ -4398,7 +4337,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4398
4337
  }
4399
4338
 
4400
4339
  // string:containsIgnoringCase
4401
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'containsIgnoringCase') {
4340
+ if (pv === STRING_NS + 'containsIgnoringCase') {
4402
4341
  const sStr = termToJsString(g.s);
4403
4342
  const oStr = termToJsString(g.o);
4404
4343
  if (sStr === null || oStr === null) return [];
@@ -4406,7 +4345,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4406
4345
  }
4407
4346
 
4408
4347
  // string:endsWith
4409
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'endsWith') {
4348
+ if (pv === STRING_NS + 'endsWith') {
4410
4349
  const sStr = termToJsString(g.s);
4411
4350
  const oStr = termToJsString(g.o);
4412
4351
  if (sStr === null || oStr === null) return [];
@@ -4414,7 +4353,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4414
4353
  }
4415
4354
 
4416
4355
  // string:equalIgnoringCase
4417
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'equalIgnoringCase') {
4356
+ if (pv === STRING_NS + 'equalIgnoringCase') {
4418
4357
  const sStr = termToJsString(g.s);
4419
4358
  const oStr = termToJsString(g.o);
4420
4359
  if (sStr === null || oStr === null) return [];
@@ -4423,7 +4362,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4423
4362
 
4424
4363
  // string:format
4425
4364
  // (limited: only %s and %% are supported, anything else ⇒ builtin fails)
4426
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'format') {
4365
+ if (pv === STRING_NS + 'format') {
4427
4366
  if (!(g.s instanceof ListTerm) || g.s.elems.length < 1) return [];
4428
4367
  const fmtStr = termToJsString(g.s.elems[0]);
4429
4368
  if (fmtStr === null) return [];
@@ -4450,10 +4389,10 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4450
4389
 
4451
4390
  // string:jsonPointer
4452
4391
  // Schema: ( $jsonText $pointer ) string:jsonPointer $value
4453
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'jsonPointer') {
4392
+ if (pv === STRING_NS + 'jsonPointer') {
4454
4393
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
4455
4394
 
4456
- const jsonText = termToJsonText(g.s.elems[0]); // <-- changed
4395
+ const jsonText = termToJsonText(g.s.elems[0]);
4457
4396
  const ptr = termToJsStringDecoded(g.s.elems[1]);
4458
4397
  if (jsonText === null || ptr === null) return [];
4459
4398
 
@@ -4465,7 +4404,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4465
4404
  }
4466
4405
 
4467
4406
  // string:greaterThan
4468
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'greaterThan') {
4407
+ if (pv === STRING_NS + 'greaterThan') {
4469
4408
  const sStr = termToJsString(g.s);
4470
4409
  const oStr = termToJsString(g.o);
4471
4410
  if (sStr === null || oStr === null) return [];
@@ -4473,7 +4412,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4473
4412
  }
4474
4413
 
4475
4414
  // string:lessThan
4476
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'lessThan') {
4415
+ if (pv === STRING_NS + 'lessThan') {
4477
4416
  const sStr = termToJsString(g.s);
4478
4417
  const oStr = termToJsString(g.o);
4479
4418
  if (sStr === null || oStr === null) return [];
@@ -4481,7 +4420,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4481
4420
  }
4482
4421
 
4483
4422
  // string:matches
4484
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'matches') {
4423
+ if (pv === STRING_NS + 'matches') {
4485
4424
  const sStr = termToJsString(g.s);
4486
4425
  const pattern = termToJsString(g.o);
4487
4426
  if (sStr === null || pattern === null) return [];
@@ -4496,7 +4435,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4496
4435
  }
4497
4436
 
4498
4437
  // string:notEqualIgnoringCase
4499
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'notEqualIgnoringCase') {
4438
+ if (pv === STRING_NS + 'notEqualIgnoringCase') {
4500
4439
  const sStr = termToJsString(g.s);
4501
4440
  const oStr = termToJsString(g.o);
4502
4441
  if (sStr === null || oStr === null) return [];
@@ -4504,7 +4443,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4504
4443
  }
4505
4444
 
4506
4445
  // string:notGreaterThan (≤ in Unicode code order)
4507
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'notGreaterThan') {
4446
+ if (pv === STRING_NS + 'notGreaterThan') {
4508
4447
  const sStr = termToJsString(g.s);
4509
4448
  const oStr = termToJsString(g.o);
4510
4449
  if (sStr === null || oStr === null) return [];
@@ -4512,7 +4451,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4512
4451
  }
4513
4452
 
4514
4453
  // string:notLessThan (≥ in Unicode code order)
4515
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'notLessThan') {
4454
+ if (pv === STRING_NS + 'notLessThan') {
4516
4455
  const sStr = termToJsString(g.s);
4517
4456
  const oStr = termToJsString(g.o);
4518
4457
  if (sStr === null || oStr === null) return [];
@@ -4520,7 +4459,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4520
4459
  }
4521
4460
 
4522
4461
  // string:notMatches
4523
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'notMatches') {
4462
+ if (pv === STRING_NS + 'notMatches') {
4524
4463
  const sStr = termToJsString(g.s);
4525
4464
  const pattern = termToJsString(g.o);
4526
4465
  if (sStr === null || pattern === null) return [];
@@ -4534,7 +4473,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4534
4473
  }
4535
4474
 
4536
4475
  // string:replace
4537
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'replace') {
4476
+ if (pv === STRING_NS + 'replace') {
4538
4477
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 3) return [];
4539
4478
  const dataStr = termToJsString(g.s.elems[0]);
4540
4479
  const searchStr = termToJsString(g.s.elems[1]);
@@ -4562,7 +4501,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4562
4501
  }
4563
4502
 
4564
4503
  // string:scrape
4565
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'scrape') {
4504
+ if (pv === STRING_NS + 'scrape') {
4566
4505
  if (!(g.s instanceof ListTerm) || g.s.elems.length !== 2) return [];
4567
4506
  const dataStr = termToJsString(g.s.elems[0]);
4568
4507
  const pattern = termToJsString(g.s.elems[1]);
@@ -4591,7 +4530,7 @@ function evalBuiltin(goal, subst, facts, backRules, depth, varGen) {
4591
4530
  }
4592
4531
 
4593
4532
  // string:startsWith
4594
- if (g.p instanceof Iri && g.p.value === STRING_NS + 'startsWith') {
4533
+ if (pv === STRING_NS + 'startsWith') {
4595
4534
  const sStr = termToJsString(g.s);
4596
4535
  const oStr = termToJsString(g.o);
4597
4536
  if (sStr === null || oStr === null) return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eyeling",
3
- "version": "1.6.16",
3
+ "version": "1.6.17",
4
4
  "description": "A minimal Notation3 (N3) reasoner in JavaScript.",
5
5
  "main": "./index.js",
6
6
  "keywords": [