eyeling 1.26.1 → 1.26.3

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/lib/engine.js CHANGED
@@ -43,7 +43,7 @@ const EMPTY_LIST_TERM = new ListTerm([]);
43
43
  const { lex, N3SyntaxError } = require('./lexer');
44
44
  const { Parser } = require('./parser');
45
45
  const { liftBlankRuleVars } = require('./rules');
46
- const { parseN3Text, parseN3SourceList } = require('./multisource');
46
+ const { parseN3SourceList, parseN3Text } = require('./multisource');
47
47
 
48
48
  const {
49
49
  makeBuiltins,
@@ -100,6 +100,10 @@ function __cloneSubst(subst) {
100
100
  return out;
101
101
  }
102
102
 
103
+ function __defineHiddenWritable(obj, name, value) {
104
+ Object.defineProperty(obj, name, { value, enumerable: false, writable: true });
105
+ }
106
+
103
107
  let version = 'dev';
104
108
  try {
105
109
  // Node: keep package.json version if available
@@ -411,44 +415,29 @@ function __logNaturalPriorityFromTerm(t) {
411
415
  function __computeMaxScopedClosurePriorityNeeded(forwardRules, backRules) {
412
416
  let maxP = 0;
413
417
 
418
+ function bumpMaxPriority(term) {
419
+ if (term instanceof GraphTerm) return;
420
+ if (term instanceof Var) {
421
+ if (maxP < 1) maxP = 1;
422
+ return;
423
+ }
424
+ const p0 = __logNaturalPriorityFromTerm(term);
425
+ const priority = p0 !== null ? p0 : 1;
426
+ if (priority > maxP) maxP = priority;
427
+ }
428
+
414
429
  function scanTriple(tr) {
415
430
  if (!(tr && tr.p instanceof Iri)) return;
416
431
  const pv = tr.p.value;
417
432
 
418
433
  // log:collectAllIn / log:forAllIn use the object position for the priority.
419
434
  if (pv === LOG_NS + 'collectAllIn' || pv === LOG_NS + 'forAllIn') {
420
- // Explicit scope graphs are immediate and do not require a closure.
421
- if (tr.o instanceof GraphTerm) return;
422
- // Variable or non-numeric object => default priority 1 (if used).
423
- if (tr.o instanceof Var) {
424
- if (maxP < 1) maxP = 1;
425
- return;
426
- }
427
- const p0 = __logNaturalPriorityFromTerm(tr.o);
428
- if (p0 !== null) {
429
- if (p0 > maxP) maxP = p0;
430
- } else {
431
- if (maxP < 1) maxP = 1;
432
- }
435
+ bumpMaxPriority(tr.o);
433
436
  return;
434
437
  }
435
438
 
436
439
  // log:includes / log:notIncludes use the subject position for the priority.
437
- if (pv === LOG_NS + 'includes' || pv === LOG_NS + 'notIncludes') {
438
- // Explicit scope graphs are immediate and do not require a closure.
439
- if (tr.s instanceof GraphTerm) return;
440
- // Variable or non-numeric subject => default priority 1 (if used).
441
- if (tr.s instanceof Var) {
442
- if (maxP < 1) maxP = 1;
443
- return;
444
- }
445
- const p0 = __logNaturalPriorityFromTerm(tr.s);
446
- if (p0 !== null) {
447
- if (p0 > maxP) maxP = p0;
448
- } else {
449
- if (maxP < 1) maxP = 1;
450
- }
451
- }
440
+ if (pv === LOG_NS + 'includes' || pv === LOG_NS + 'notIncludes') bumpMaxPriority(tr.s);
452
441
  }
453
442
 
454
443
  for (const r of forwardRules) {
@@ -485,7 +474,6 @@ function __varOccursElsewhereInPremise(premise, name, idx, field) {
485
474
  return false;
486
475
  }
487
476
 
488
-
489
477
  function __scopedPriorityForTerm(t) {
490
478
  if (t instanceof GraphTerm) return 0;
491
479
  const p0 = __logNaturalPriorityFromTerm(t);
@@ -627,7 +615,6 @@ function __computeForwardRuleScopedStrata(forwardRules) {
627
615
  if (!changed) break;
628
616
  }
629
617
 
630
-
631
618
  maxLevel = 0;
632
619
  for (let i = 0; i < forwardRules.length; i++) {
633
620
  __setForwardRuleScopedStratumInfo(forwardRules[i], levels[i]);
@@ -641,42 +628,33 @@ function __computeForwardRuleScopedSkipInfo(rule) {
641
628
  let needsSnap = false;
642
629
  let requiredLevel = 0;
643
630
 
631
+ function addScopedUse(scopeTerm, idx, field) {
632
+ if (scopeTerm instanceof GraphTerm) return true; // explicit scope
633
+
634
+ // If scope term is a Var that appears elsewhere, it might be bound to a GraphTerm.
635
+ // Be conservative and do not skip in that case.
636
+ if (scopeTerm instanceof Var) {
637
+ if (__varOccursElsewhereInPremise(rule.premise, scopeTerm.name, idx, field)) return false;
638
+ needsSnap = true;
639
+ requiredLevel = Math.max(requiredLevel, 1);
640
+ return true;
641
+ }
642
+
643
+ needsSnap = true;
644
+ const p0 = __logNaturalPriorityFromTerm(scopeTerm);
645
+ requiredLevel = Math.max(requiredLevel, p0 !== null ? p0 : 1);
646
+ return true;
647
+ }
648
+
644
649
  for (let i = 0; i < rule.premise.length; i++) {
645
650
  const tr = rule.premise[i];
646
651
  if (!(tr && tr.p instanceof Iri)) continue;
647
652
  const pv = tr.p.value;
648
653
 
649
654
  if (pv === LOG_NS + 'collectAllIn' || pv === LOG_NS + 'forAllIn') {
650
- if (tr.o instanceof GraphTerm) continue; // explicit scope
651
- // If scope term is a Var that appears elsewhere, it might be bound to a GraphTerm.
652
- // Be conservative and do not skip in that case.
653
- if (tr.o instanceof Var) {
654
- if (__varOccursElsewhereInPremise(rule.premise, tr.o.name, i, 'o')) return null;
655
- needsSnap = true;
656
- requiredLevel = Math.max(requiredLevel, 1);
657
- } else {
658
- needsSnap = true;
659
- let prio = 1;
660
- const p0 = __logNaturalPriorityFromTerm(tr.o);
661
- if (p0 !== null) prio = p0;
662
- requiredLevel = Math.max(requiredLevel, prio);
663
- }
664
- continue;
665
- }
666
-
667
- if (pv === LOG_NS + 'includes' || pv === LOG_NS + 'notIncludes') {
668
- if (tr.s instanceof GraphTerm) continue; // explicit scope
669
- if (tr.s instanceof Var) {
670
- if (__varOccursElsewhereInPremise(rule.premise, tr.s.name, i, 's')) return null;
671
- needsSnap = true;
672
- requiredLevel = Math.max(requiredLevel, 1);
673
- } else {
674
- needsSnap = true;
675
- let prio = 1;
676
- const p0 = __logNaturalPriorityFromTerm(tr.s);
677
- if (p0 !== null) prio = p0;
678
- requiredLevel = Math.max(requiredLevel, prio);
679
- }
655
+ if (!addScopedUse(tr.o, i, 'o')) return null;
656
+ } else if (pv === LOG_NS + 'includes' || pv === LOG_NS + 'notIncludes') {
657
+ if (!addScopedUse(tr.s, i, 's')) return null;
680
658
  }
681
659
  }
682
660
 
@@ -859,140 +837,70 @@ function skolemizeTripleForHeadBlanks(tr, headBlankLabels, mapping, skCounter, f
859
837
  // Alpha equivalence helpers
860
838
  // ===========================================================================
861
839
 
862
- function termsEqual(a, b) {
863
- if (a === b) return true;
864
- if (!a || !b) return false;
865
- if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
866
-
867
- // rdf:nil is equivalent to the empty list ()
868
- if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
869
- if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
870
- if (a.constructor !== b.constructor) return false;
871
-
872
- if (a instanceof Iri) return a.value === b.value;
873
-
874
- if (a instanceof Literal) {
875
- if (a.value === b.value) return true;
876
-
877
- // Plain "abc" == "abc"^^xsd:string (but not language-tagged strings)
878
- if (literalsEquivalentAsXsdString(a.value, b.value)) return true;
879
-
880
- // Keep in sync with unifyTerm(): numeric-value equality, datatype-aware.
881
- const ai = parseNumericLiteralInfo(a);
882
- const bi = parseNumericLiteralInfo(b);
840
+ function __isRdfNilEmptyListPair(a, b) {
841
+ return a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0;
842
+ }
883
843
 
884
- if (ai && bi) {
885
- // Same datatype => compare values
886
- if (ai.dt === bi.dt) {
887
- if (ai.kind === 'bigint' && bi.kind === 'bigint') return ai.value === bi.value;
844
+ function __numericInfosSameDatatypeEqual(ai, bi, exactDecimal) {
845
+ if (!ai || !bi || ai.dt !== bi.dt) return false;
846
+ if (ai.kind === 'bigint' && bi.kind === 'bigint') return ai.value === bi.value;
888
847
 
889
- const an = ai.kind === 'bigint' ? Number(ai.value) : ai.value;
890
- const bn = bi.kind === 'bigint' ? Number(bi.value) : bi.value;
891
- return !Number.isNaN(an) && !Number.isNaN(bn) && an === bn;
892
- }
848
+ if (exactDecimal && ai.dt === XSD_NS + 'decimal') {
849
+ const da = parseXsdDecimalToBigIntScale(ai.lexStr);
850
+ const db = parseXsdDecimalToBigIntScale(bi.lexStr);
851
+ if (da && db) {
852
+ const scale = Math.max(da.scale, db.scale);
853
+ return da.num * pow10n(scale - da.scale) === db.num * pow10n(scale - db.scale);
893
854
  }
894
-
895
- return false;
896
855
  }
897
856
 
898
- if (a instanceof Var) return a.name === b.name;
899
- if (a instanceof Blank) return a.label === b.label;
900
-
901
- if (a instanceof ListTerm) {
902
- if (a.elems.length !== b.elems.length) return false;
903
- for (let i = 0; i < a.elems.length; i++) {
904
- if (!termsEqual(a.elems[i], b.elems[i])) return false;
905
- }
906
- return true;
907
- }
857
+ const an = ai.kind === 'bigint' ? Number(ai.value) : ai.value;
858
+ const bn = bi.kind === 'bigint' ? Number(bi.value) : bi.value;
859
+ return !Number.isNaN(an) && !Number.isNaN(bn) && an === bn;
860
+ }
908
861
 
909
- if (a instanceof OpenListTerm) {
910
- if (a.tailVar !== b.tailVar) return false;
911
- if (a.prefix.length !== b.prefix.length) return false;
912
- for (let i = 0; i < a.prefix.length; i++) {
913
- if (!termsEqual(a.prefix[i], b.prefix[i])) return false;
914
- }
915
- return true;
916
- }
862
+ function __literalsEqual(a, b, exactDecimal) {
863
+ if (a.value === b.value) return true;
864
+ if (literalsEquivalentAsXsdString(a.value, b.value)) return true;
865
+ return __numericInfosSameDatatypeEqual(parseNumericLiteralInfo(a), parseNumericLiteralInfo(b), exactDecimal);
866
+ }
917
867
 
918
- if (a instanceof GraphTerm) {
919
- return alphaEqGraphTriples(a.triples, b.triples);
868
+ function __termArraysEqual(xs, ys, eq) {
869
+ if (xs.length !== ys.length) return false;
870
+ for (let i = 0; i < xs.length; i++) {
871
+ if (!eq(xs[i], ys[i])) return false;
920
872
  }
921
-
922
- return false;
873
+ return true;
923
874
  }
924
875
 
925
- function termsEqualNoIntDecimal(a, b) {
876
+ function __termsEqual(a, b, exactDecimal) {
926
877
  if (a === b) return true;
927
878
  if (!a || !b) return false;
928
879
  if (a.__tid && b.__tid && a.__tid === b.__tid) return true;
929
880
 
930
881
  // rdf:nil is equivalent to the empty list ()
931
- if (a instanceof Iri && a.value === RDF_NIL_IRI && b instanceof ListTerm && b.elems.length === 0) return true;
932
- if (b instanceof Iri && b.value === RDF_NIL_IRI && a instanceof ListTerm && a.elems.length === 0) return true;
882
+ if (__isRdfNilEmptyListPair(a, b) || __isRdfNilEmptyListPair(b, a)) return true;
933
883
  if (a.constructor !== b.constructor) return false;
934
884
 
935
885
  if (a instanceof Iri) return a.value === b.value;
936
-
937
- if (a instanceof Literal) {
938
- if (a.value === b.value) return true;
939
-
940
- // Plain "abc" == "abc"^^xsd:string (but not language-tagged)
941
- if (literalsEquivalentAsXsdString(a.value, b.value)) return true;
942
-
943
- // Numeric equality ONLY when datatypes agree (no integer<->decimal here)
944
- const ai = parseNumericLiteralInfo(a);
945
- const bi = parseNumericLiteralInfo(b);
946
- if (ai && bi && ai.dt === bi.dt) {
947
- // integer: exact bigint
948
- if (ai.kind === 'bigint' && bi.kind === 'bigint') return ai.value === bi.value;
949
-
950
- // decimal: compare exactly via num/scale if possible
951
- if (ai.dt === XSD_NS + 'decimal') {
952
- const da = parseXsdDecimalToBigIntScale(ai.lexStr);
953
- const db = parseXsdDecimalToBigIntScale(bi.lexStr);
954
- if (da && db) {
955
- const scale = Math.max(da.scale, db.scale);
956
- const na = da.num * pow10n(scale - da.scale);
957
- const nb = db.num * pow10n(scale - db.scale);
958
- return na === nb;
959
- }
960
- }
961
-
962
- // double/float-ish: JS number (same as your normal same-dt path)
963
- const an = ai.kind === 'bigint' ? Number(ai.value) : ai.value;
964
- const bn = bi.kind === 'bigint' ? Number(bi.value) : bi.value;
965
- return !Number.isNaN(an) && !Number.isNaN(bn) && an === bn;
966
- }
967
-
968
- return false;
969
- }
970
-
886
+ if (a instanceof Literal) return __literalsEqual(a, b, exactDecimal);
971
887
  if (a instanceof Var) return a.name === b.name;
972
888
  if (a instanceof Blank) return a.label === b.label;
889
+ if (a instanceof ListTerm) return __termArraysEqual(a.elems, b.elems, (x, y) => __termsEqual(x, y, exactDecimal));
890
+ if (a instanceof OpenListTerm)
891
+ return a.tailVar === b.tailVar && __termArraysEqual(a.prefix, b.prefix, (x, y) => __termsEqual(x, y, exactDecimal));
892
+ if (a instanceof GraphTerm) return alphaEqGraphTriples(a.triples, b.triples);
893
+ return false;
894
+ }
973
895
 
974
- if (a instanceof ListTerm) {
975
- if (a.elems.length !== b.elems.length) return false;
976
- for (let i = 0; i < a.elems.length; i++) {
977
- if (!termsEqualNoIntDecimal(a.elems[i], b.elems[i])) return false;
978
- }
979
- return true;
980
- }
981
-
982
- if (a instanceof OpenListTerm) {
983
- if (a.tailVar !== b.tailVar) return false;
984
- if (a.prefix.length !== b.prefix.length) return false;
985
- for (let i = 0; i < a.prefix.length; i++) {
986
- if (!termsEqualNoIntDecimal(a.prefix[i], b.prefix[i])) return false;
987
- }
988
- return true;
989
- }
990
-
991
- if (a instanceof GraphTerm) {
992
- return alphaEqGraphTriples(a.triples, b.triples);
993
- }
896
+ function termsEqual(a, b) {
897
+ // Keep in sync with unifyTerm(): numeric-value equality, datatype-aware.
898
+ return __termsEqual(a, b, false);
899
+ }
994
900
 
995
- return false;
901
+ function termsEqualNoIntDecimal(a, b) {
902
+ // Numeric equality ONLY when datatypes agree; decimals are compared exactly.
903
+ return __termsEqual(a, b, true);
996
904
  }
997
905
 
998
906
  function triplesEqual(a, b) {
@@ -1352,66 +1260,18 @@ function ensureFactIndexes(facts) {
1352
1260
  )
1353
1261
  return;
1354
1262
 
1355
- Object.defineProperty(facts, '__byPred', {
1356
- value: new Map(),
1357
- enumerable: false,
1358
- writable: true,
1359
- });
1360
- Object.defineProperty(facts, '__byPS', {
1361
- value: new Map(),
1362
- enumerable: false,
1363
- writable: true,
1364
- });
1365
- Object.defineProperty(facts, '__byPO', {
1366
- value: new Map(),
1367
- enumerable: false,
1368
- writable: true,
1369
- });
1370
- Object.defineProperty(facts, '__byPNonFastS', {
1371
- value: new Map(),
1372
- enumerable: false,
1373
- writable: true,
1374
- });
1375
- Object.defineProperty(facts, '__byPNonFastO', {
1376
- value: new Map(),
1377
- enumerable: false,
1378
- writable: true,
1379
- });
1380
- Object.defineProperty(facts, '__varPred', {
1381
- value: [],
1382
- enumerable: false,
1383
- writable: true,
1384
- });
1385
- Object.defineProperty(facts, '__varPredPS', {
1386
- value: new Map(),
1387
- enumerable: false,
1388
- writable: true,
1389
- });
1390
- Object.defineProperty(facts, '__varPredPO', {
1391
- value: new Map(),
1392
- enumerable: false,
1393
- writable: true,
1394
- });
1395
- Object.defineProperty(facts, '__varPredNonFastS', {
1396
- value: [],
1397
- enumerable: false,
1398
- writable: true,
1399
- });
1400
- Object.defineProperty(facts, '__varPredNonFastO', {
1401
- value: [],
1402
- enumerable: false,
1403
- writable: true,
1404
- });
1405
- Object.defineProperty(facts, '__keySet', {
1406
- value: new Set(),
1407
- enumerable: false,
1408
- writable: true,
1409
- });
1410
- Object.defineProperty(facts, '__keySetComplete', {
1411
- value: false,
1412
- enumerable: false,
1413
- writable: true,
1414
- });
1263
+ __defineHiddenWritable(facts, '__byPred', new Map());
1264
+ __defineHiddenWritable(facts, '__byPS', new Map());
1265
+ __defineHiddenWritable(facts, '__byPO', new Map());
1266
+ __defineHiddenWritable(facts, '__byPNonFastS', new Map());
1267
+ __defineHiddenWritable(facts, '__byPNonFastO', new Map());
1268
+ __defineHiddenWritable(facts, '__varPred', []);
1269
+ __defineHiddenWritable(facts, '__varPredPS', new Map());
1270
+ __defineHiddenWritable(facts, '__varPredPO', new Map());
1271
+ __defineHiddenWritable(facts, '__varPredNonFastS', []);
1272
+ __defineHiddenWritable(facts, '__varPredNonFastO', []);
1273
+ __defineHiddenWritable(facts, '__keySet', new Set());
1274
+ __defineHiddenWritable(facts, '__keySetComplete', false);
1415
1275
 
1416
1276
  // Build lookup indexes eagerly, but do not populate the duplicate-detection
1417
1277
  // string Set for every input fact. The predicate/subject/object indexes are
@@ -1439,45 +1299,21 @@ function cloneFactIndexesForSnapshot(src, dest) {
1439
1299
  return out;
1440
1300
  }
1441
1301
 
1442
- Object.defineProperty(dest, '__byPred', { value: cloneArrayMap(src.__byPred), enumerable: false, writable: true });
1443
- Object.defineProperty(dest, '__byPS', { value: cloneNestedArrayMap(src.__byPS), enumerable: false, writable: true });
1444
- Object.defineProperty(dest, '__byPO', { value: cloneNestedArrayMap(src.__byPO), enumerable: false, writable: true });
1445
- Object.defineProperty(dest, '__byPNonFastS', {
1446
- value: cloneArrayMap(src.__byPNonFastS),
1447
- enumerable: false,
1448
- writable: true,
1449
- });
1450
- Object.defineProperty(dest, '__byPNonFastO', {
1451
- value: cloneArrayMap(src.__byPNonFastO),
1452
- enumerable: false,
1453
- writable: true,
1454
- });
1455
- Object.defineProperty(dest, '__varPred', { value: src.__varPred.slice(), enumerable: false, writable: true });
1456
- Object.defineProperty(dest, '__varPredPS', {
1457
- value: cloneArrayMap(src.__varPredPS),
1458
- enumerable: false,
1459
- writable: true,
1460
- });
1461
- Object.defineProperty(dest, '__varPredPO', {
1462
- value: cloneArrayMap(src.__varPredPO),
1463
- enumerable: false,
1464
- writable: true,
1465
- });
1466
- Object.defineProperty(dest, '__varPredNonFastS', {
1467
- value: src.__varPredNonFastS.slice(),
1468
- enumerable: false,
1469
- writable: true,
1470
- });
1471
- Object.defineProperty(dest, '__varPredNonFastO', {
1472
- value: src.__varPredNonFastO.slice(),
1473
- enumerable: false,
1474
- writable: true,
1475
- });
1476
- Object.defineProperty(dest, '__keySet', { value: new Set(src.__keySet), enumerable: false, writable: true });
1477
- Object.defineProperty(dest, '__keySetComplete', { value: !!src.__keySetComplete, enumerable: false, writable: true });
1302
+ __defineHiddenWritable(dest, '__byPred', cloneArrayMap(src.__byPred));
1303
+ __defineHiddenWritable(dest, '__byPS', cloneNestedArrayMap(src.__byPS));
1304
+ __defineHiddenWritable(dest, '__byPO', cloneNestedArrayMap(src.__byPO));
1305
+ __defineHiddenWritable(dest, '__byPNonFastS', cloneArrayMap(src.__byPNonFastS));
1306
+ __defineHiddenWritable(dest, '__byPNonFastO', cloneArrayMap(src.__byPNonFastO));
1307
+ __defineHiddenWritable(dest, '__varPred', src.__varPred.slice());
1308
+ __defineHiddenWritable(dest, '__varPredPS', cloneArrayMap(src.__varPredPS));
1309
+ __defineHiddenWritable(dest, '__varPredPO', cloneArrayMap(src.__varPredPO));
1310
+ __defineHiddenWritable(dest, '__varPredNonFastS', src.__varPredNonFastS.slice());
1311
+ __defineHiddenWritable(dest, '__varPredNonFastO', src.__varPredNonFastO.slice());
1312
+ __defineHiddenWritable(dest, '__keySet', new Set(src.__keySet));
1313
+ __defineHiddenWritable(dest, '__keySetComplete', !!src.__keySetComplete);
1478
1314
  }
1479
1315
 
1480
- function addToIndexArrayMap(map, key, value) {
1316
+ function pushMapArray(map, key, value) {
1481
1317
  let bucket = map.get(key);
1482
1318
  if (!bucket) {
1483
1319
  bucket = [];
@@ -1486,6 +1322,15 @@ function addToIndexArrayMap(map, key, value) {
1486
1322
  bucket.push(value);
1487
1323
  }
1488
1324
 
1325
+ function getOrCreateMap(map, key) {
1326
+ let inner = map.get(key);
1327
+ if (!inner) {
1328
+ inner = new Map();
1329
+ map.set(key, inner);
1330
+ }
1331
+ return inner;
1332
+ }
1333
+
1489
1334
  function indexFact(facts, tr, idx, addKeySet = true) {
1490
1335
  const sk = termLookupKey(tr.s);
1491
1336
  const ok = termLookupKey(tr.o);
@@ -1496,45 +1341,30 @@ function indexFact(facts, tr, idx, addKeySet = true) {
1496
1341
  const pk = tr.p.__tid;
1497
1342
  pkForKey = pk;
1498
1343
 
1499
- let pb = facts.__byPred.get(pk);
1500
- if (!pb) {
1501
- pb = [];
1502
- facts.__byPred.set(pk, pb);
1503
- }
1504
- pb.push(idx);
1344
+ pushMapArray(facts.__byPred, pk, idx);
1505
1345
 
1506
1346
  if (sk !== null) {
1507
- let ps = facts.__byPS.get(pk);
1508
- if (!ps) {
1509
- ps = new Map();
1510
- facts.__byPS.set(pk, ps);
1511
- }
1512
- addToIndexArrayMap(ps, sk, idx);
1347
+ pushMapArray(getOrCreateMap(facts.__byPS, pk), sk, idx);
1513
1348
  } else {
1514
- addToIndexArrayMap(facts.__byPNonFastS, pk, idx);
1349
+ pushMapArray(facts.__byPNonFastS, pk, idx);
1515
1350
  }
1516
1351
 
1517
1352
  if (ok !== null) {
1518
- let po = facts.__byPO.get(pk);
1519
- if (!po) {
1520
- po = new Map();
1521
- facts.__byPO.set(pk, po);
1522
- }
1523
- addToIndexArrayMap(po, ok, idx);
1353
+ pushMapArray(getOrCreateMap(facts.__byPO, pk), ok, idx);
1524
1354
  } else {
1525
- addToIndexArrayMap(facts.__byPNonFastO, pk, idx);
1355
+ pushMapArray(facts.__byPNonFastO, pk, idx);
1526
1356
  }
1527
1357
  } else if (tr.p instanceof Var) {
1528
1358
  facts.__varPred.push(idx);
1529
1359
 
1530
1360
  if (sk !== null) {
1531
- addToIndexArrayMap(facts.__varPredPS, sk, idx);
1361
+ pushMapArray(facts.__varPredPS, sk, idx);
1532
1362
  } else {
1533
1363
  facts.__varPredNonFastS.push(idx);
1534
1364
  }
1535
1365
 
1536
1366
  if (ok !== null) {
1537
- addToIndexArrayMap(facts.__varPredPO, ok, idx);
1367
+ pushMapArray(facts.__varPredPO, ok, idx);
1538
1368
  } else {
1539
1369
  facts.__varPredNonFastO.push(idx);
1540
1370
  }
@@ -1688,16 +1518,8 @@ function makeDerivedRecord(fact, rule, premises, subst, captureExplanations) {
1688
1518
  function ensureBackRuleIndexes(backRules) {
1689
1519
  if (backRules.__byHeadPred && backRules.__wildHeadPred) return;
1690
1520
 
1691
- Object.defineProperty(backRules, '__byHeadPred', {
1692
- value: new Map(),
1693
- enumerable: false,
1694
- writable: true,
1695
- });
1696
- Object.defineProperty(backRules, '__wildHeadPred', {
1697
- value: [],
1698
- enumerable: false,
1699
- writable: true,
1700
- });
1521
+ __defineHiddenWritable(backRules, '__byHeadPred', new Map());
1522
+ __defineHiddenWritable(backRules, '__wildHeadPred', []);
1701
1523
 
1702
1524
  for (const r of backRules) indexBackRule(backRules, r);
1703
1525
  }
@@ -1706,13 +1528,7 @@ function indexBackRule(backRules, r) {
1706
1528
  if (!r || !r.conclusion || r.conclusion.length !== 1) return;
1707
1529
  const head = r.conclusion[0];
1708
1530
  if (head && head.p instanceof Iri) {
1709
- const k = head.p.__tid;
1710
- let bucket = backRules.__byHeadPred.get(k);
1711
- if (!bucket) {
1712
- bucket = [];
1713
- backRules.__byHeadPred.set(k, bucket);
1714
- }
1715
- bucket.push(r);
1531
+ pushMapArray(backRules.__byHeadPred, head.p.__tid, r);
1716
1532
  } else {
1717
1533
  backRules.__wildHeadPred.push(r);
1718
1534
  }
@@ -1747,12 +1563,11 @@ function isSinglePremiseAgendaRuleSafe(r, backRules) {
1747
1563
  return backRules.__wildHeadPred.length === 0;
1748
1564
  }
1749
1565
 
1750
- function mergeSinglePremiseAgendaBuckets() {
1566
+ function mergeSinglePremiseAgendaBuckets(...buckets) {
1751
1567
  let out = null;
1752
1568
  let seen = null;
1753
1569
 
1754
- for (let i = 0; i < arguments.length; i++) {
1755
- const bucket = arguments[i];
1570
+ for (const bucket of buckets) {
1756
1571
  if (!bucket || bucket.length === 0) continue;
1757
1572
 
1758
1573
  if (out === null) {
@@ -1762,8 +1577,7 @@ function mergeSinglePremiseAgendaBuckets() {
1762
1577
  }
1763
1578
 
1764
1579
  if (!seen) seen = new Set(out);
1765
- for (let j = 0; j < bucket.length; j++) {
1766
- const entry = bucket[j];
1580
+ for (const entry of bucket) {
1767
1581
  if (seen.has(entry)) continue;
1768
1582
  seen.add(entry);
1769
1583
  out.push(entry);
@@ -1773,14 +1587,14 @@ function mergeSinglePremiseAgendaBuckets() {
1773
1587
  return out;
1774
1588
  }
1775
1589
 
1776
- function termContainsVarForAgenda(t) {
1590
+ function termContainsVar(t) {
1777
1591
  if (t instanceof Var) return true;
1778
- if (t instanceof ListTerm) return t.elems.some(termContainsVarForAgenda);
1592
+ if (t instanceof ListTerm) return t.elems.some(termContainsVar);
1779
1593
  if (t instanceof OpenListTerm) return true;
1780
1594
  if (t instanceof GraphTerm)
1781
1595
  return t.triples.some(
1782
1596
  (tr) =>
1783
- termContainsVarForAgenda(tr.s) || termContainsVarForAgenda(tr.p) || termContainsVarForAgenda(tr.o),
1597
+ termContainsVar(tr.s) || termContainsVar(tr.p) || termContainsVar(tr.o),
1784
1598
  );
1785
1599
  return false;
1786
1600
  }
@@ -1799,15 +1613,6 @@ function makeSinglePremiseAgendaIndex(forwardRules, backRules) {
1799
1613
  size: 0,
1800
1614
  };
1801
1615
 
1802
- function addToMapArray(m, k, v) {
1803
- let bucket = m.get(k);
1804
- if (!bucket) {
1805
- bucket = [];
1806
- m.set(k, bucket);
1807
- }
1808
- bucket.push(v);
1809
- }
1810
-
1811
1616
  for (let i = 0; i < forwardRules.length; i++) {
1812
1617
  const r = forwardRules[i];
1813
1618
  if (!isSinglePremiseAgendaRuleSafe(r, backRules)) continue;
@@ -1833,29 +1638,15 @@ function makeSinglePremiseAgendaIndex(forwardRules, backRules) {
1833
1638
  index.size += 1;
1834
1639
 
1835
1640
  if (entry.goalPredTid !== null) {
1836
- addToMapArray(index.byPredAll, entry.goalPredTid, entry);
1641
+ pushMapArray(index.byPredAll, entry.goalPredTid, entry);
1837
1642
  index.allIriPred.push(entry);
1838
- if (entry.goalSKey === null && entry.goalOKey === null) addToMapArray(index.byPred, entry.goalPredTid, entry);
1839
- if (entry.goalSKey !== null) {
1840
- let ps = index.byPS.get(entry.goalPredTid);
1841
- if (!ps) {
1842
- ps = new Map();
1843
- index.byPS.set(entry.goalPredTid, ps);
1844
- }
1845
- addToMapArray(ps, entry.goalSKey, entry);
1846
- }
1847
- if (entry.goalOKey !== null) {
1848
- let po = index.byPO.get(entry.goalPredTid);
1849
- if (!po) {
1850
- po = new Map();
1851
- index.byPO.set(entry.goalPredTid, po);
1852
- }
1853
- addToMapArray(po, entry.goalOKey, entry);
1854
- }
1643
+ if (entry.goalSKey === null && entry.goalOKey === null) pushMapArray(index.byPred, entry.goalPredTid, entry);
1644
+ if (entry.goalSKey !== null) pushMapArray(getOrCreateMap(index.byPS, entry.goalPredTid), entry.goalSKey, entry);
1645
+ if (entry.goalOKey !== null) pushMapArray(getOrCreateMap(index.byPO, entry.goalPredTid), entry.goalOKey, entry);
1855
1646
  } else {
1856
1647
  if (entry.goalSKey === null && entry.goalOKey === null) index.wildPred.push(entry);
1857
- if (entry.goalSKey !== null) addToMapArray(index.wildPS, entry.goalSKey, entry);
1858
- if (entry.goalOKey !== null) addToMapArray(index.wildPO, entry.goalOKey, entry);
1648
+ if (entry.goalSKey !== null) pushMapArray(index.wildPS, entry.goalSKey, entry);
1649
+ if (entry.goalOKey !== null) pushMapArray(index.wildPO, entry.goalOKey, entry);
1859
1650
  }
1860
1651
  }
1861
1652
 
@@ -1871,7 +1662,7 @@ function getSinglePremiseAgendaCandidates(index, fact) {
1871
1662
  let exact = null;
1872
1663
  if (fact.p instanceof Iri) {
1873
1664
  const pk = fact.p.__tid;
1874
- if ((sk === null && termContainsVarForAgenda(fact.s)) || (ok === null && termContainsVarForAgenda(fact.o))) {
1665
+ if ((sk === null && termContainsVar(fact.s)) || (ok === null && termContainsVar(fact.o))) {
1875
1666
  // A fact with a variable-bearing subject/object (most importantly a
1876
1667
  // top-level variable fact such as `?S :p ?O.`) can match rules whose
1877
1668
  // premise is fixed in that position. The ordinary `(p,s)` / `(p,o)` lookup
@@ -2226,16 +2017,8 @@ function unifyOpenWithList(prefix, tailv, ys, subst) {
2226
2017
  }
2227
2018
 
2228
2019
  function graphTriplesContainVars(triples) {
2229
- function termHasVar(t) {
2230
- if (t instanceof Var) return true;
2231
- if (t instanceof ListTerm) return t.elems.some(termHasVar);
2232
- if (t instanceof OpenListTerm) return t.prefix.some(termHasVar) || true;
2233
- if (t instanceof GraphTerm) return t.triples.some((tr) => termHasVar(tr.s) || termHasVar(tr.p) || termHasVar(tr.o));
2234
- return false;
2235
- }
2236
-
2237
2020
  for (const tr of triples) {
2238
- if (termHasVar(tr.s) || termHasVar(tr.p) || termHasVar(tr.o)) return true;
2021
+ if (termContainsVar(tr.s) || termContainsVar(tr.p) || termContainsVar(tr.o)) return true;
2239
2022
  }
2240
2023
  return false;
2241
2024
  }
@@ -3952,12 +3735,22 @@ function reasonStream(input, opts = {}) {
3952
3735
  skipUnsupportedRdfJs = false,
3953
3736
  builtinModules = null,
3954
3737
  rdf = false,
3738
+ sourceLabel = '<input>',
3955
3739
  } = opts;
3956
3740
 
3957
3741
  const useRdfCompatibility = !!rdf;
3958
3742
 
3959
3743
  const parsedSourceList = parseN3SourceList(input, { baseIri, rdf: useRdfCompatibility, sourceLocations: proof });
3960
- const parsedInput = parsedSourceList || normalizeParsedReasonerInputSync(input);
3744
+ const parsedTextInput = (!parsedSourceList && proof && typeof input === 'string')
3745
+ ? parseN3Text(input, {
3746
+ baseIri: baseIri || '',
3747
+ label: sourceLabel || '<input>',
3748
+ keepSourceArtifacts: false,
3749
+ sourceLocations: true,
3750
+ rdf: useRdfCompatibility,
3751
+ })
3752
+ : null;
3753
+ const parsedInput = parsedSourceList || parsedTextInput || normalizeParsedReasonerInputSync(input);
3961
3754
  const rdfFactory = rdfjs ? getDataFactory(dataFactory) : null;
3962
3755
 
3963
3756
  const __oldEnforceHttps = deref.getEnforceHttpsEnabled();
@@ -3992,22 +3785,11 @@ function reasonStream(input, opts = {}) {
3992
3785
  if (baseIri) prefixes.setBase(baseIri);
3993
3786
  } else {
3994
3787
  const n3Text = normalizeReasonerInputSync(input);
3995
- if (proof) {
3996
- const parsed = parseN3Text(n3Text, {
3997
- label: 'input.n3',
3998
- baseIri: baseIri || '',
3999
- keepSourceArtifacts: false,
4000
- sourceLocations: true,
4001
- rdf: useRdfCompatibility,
4002
- });
4003
- ({ prefixes, triples, frules, brules, logQueryRules } = parsed);
4004
- } else {
4005
- const toks = lex(n3Text, { rdf: useRdfCompatibility });
4006
- const parser = new Parser(toks);
4007
- if (baseIri) parser.prefixes.setBase(baseIri);
3788
+ const toks = lex(n3Text, { rdf: useRdfCompatibility });
3789
+ const parser = new Parser(toks);
3790
+ if (baseIri) parser.prefixes.setBase(baseIri);
4008
3791
 
4009
- [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
4010
- }
3792
+ [prefixes, triples, frules, brules, logQueryRules] = parser.parseDocument();
4011
3793
  }
4012
3794
  // Make the parsed prefixes available to log:trace output
4013
3795
  trace.setTracePrefixes(prefixes);