@gabrielbryk/jq-ts 1.3.6 → 1.4.0

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/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
-
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region src/errors.ts
3
3
  var BaseError = class extends Error {
4
4
  kind;
@@ -42,7 +42,6 @@ var RuntimeError = class extends BaseError {
42
42
  super("runtime", message, span);
43
43
  }
44
44
  };
45
-
46
45
  //#endregion
47
46
  //#region src/tokens.ts
48
47
  const keywordKinds = {
@@ -66,7 +65,6 @@ const keywordKinds = {
66
65
  label: "Label",
67
66
  break: "Break"
68
67
  };
69
-
70
68
  //#endregion
71
69
  //#region src/lexer.ts
72
70
  /**
@@ -380,7 +378,6 @@ const lex = (text) => {
380
378
  }
381
379
  };
382
380
  const isHexDigit = (ch) => !!ch && (ch >= "0" && ch <= "9" || ch >= "a" && ch <= "f" || ch >= "A" && ch <= "F");
383
-
384
381
  //#endregion
385
382
  //#region src/parser.ts
386
383
  /**
@@ -447,19 +444,93 @@ var Parser = class {
447
444
  }
448
445
  let expr = this.parsePipe(allowComma);
449
446
  while (this.match("As")) {
450
- const varToken = this.consume("Variable", "Expected variable name after \"as\"");
451
- this.consume("Pipe", "Expected \"|\" after variable binding");
447
+ const pattern = this.parseBindingPattern();
448
+ this.consume("Pipe", "Expected \"|\" after binding pattern");
452
449
  const body = this.parseBinding(allowComma);
453
450
  expr = {
454
451
  kind: "As",
455
452
  bind: expr,
456
- name: String(varToken.value),
453
+ pattern,
457
454
  body,
458
455
  span: spanBetween(expr.span, body.span)
459
456
  };
460
457
  }
461
458
  return expr;
462
459
  }
460
+ parseBindingPattern() {
461
+ if (this.match("Variable")) {
462
+ const token = this.previous();
463
+ return {
464
+ kind: "VariablePattern",
465
+ name: String(token.value),
466
+ span: token.span
467
+ };
468
+ }
469
+ if (this.match("LBracket")) {
470
+ const start = this.previous();
471
+ const items = [];
472
+ if (!this.match("RBracket")) {
473
+ do
474
+ items.push(this.parseBindingPattern());
475
+ while (this.match("Comma"));
476
+ this.consume("RBracket", "Expected \"]\" after array binding pattern");
477
+ }
478
+ return {
479
+ kind: "ArrayPattern",
480
+ items,
481
+ span: spanBetween(start.span, this.previous().span)
482
+ };
483
+ }
484
+ if (this.match("LBrace")) {
485
+ const start = this.previous();
486
+ const entries = [];
487
+ if (!this.match("RBrace")) {
488
+ do
489
+ entries.push(this.parseObjectBindingPatternEntry());
490
+ while (this.match("Comma"));
491
+ this.consume("RBrace", "Expected \"}\" after object binding pattern");
492
+ }
493
+ return {
494
+ kind: "ObjectPattern",
495
+ entries,
496
+ span: spanBetween(start.span, this.previous().span)
497
+ };
498
+ }
499
+ throw this.error(this.peek(), "Expected variable or destructuring pattern after \"as\"");
500
+ }
501
+ parseObjectBindingPatternEntry() {
502
+ if (this.match("Variable")) {
503
+ const token = this.previous();
504
+ const name = String(token.value);
505
+ return {
506
+ key: name,
507
+ pattern: {
508
+ kind: "VariablePattern",
509
+ name,
510
+ span: token.span
511
+ },
512
+ span: token.span
513
+ };
514
+ }
515
+ let key;
516
+ let keySpan;
517
+ if (this.match("Identifier")) {
518
+ const token = this.previous();
519
+ key = String(token.value);
520
+ keySpan = token.span;
521
+ } else if (this.match("String")) {
522
+ const token = this.previous();
523
+ key = String(token.value);
524
+ keySpan = token.span;
525
+ } else throw this.error(this.peek(), "Expected identifier, string, or variable shorthand in object binding pattern");
526
+ this.consume("Colon", "Expected \":\" after object binding pattern key");
527
+ const pattern = this.parseBindingPattern();
528
+ return {
529
+ key,
530
+ pattern,
531
+ span: spanBetween(keySpan, pattern.span)
532
+ };
533
+ }
463
534
  parsePipe(allowComma = true) {
464
535
  let expr = this.parseComma(allowComma);
465
536
  while (this.match("Pipe")) {
@@ -693,10 +764,7 @@ var Parser = class {
693
764
  expr = {
694
765
  kind: "Try",
695
766
  body: expr,
696
- handler: {
697
- kind: "Identity",
698
- span: op.span
699
- },
767
+ handler: void 0,
700
768
  span: spanBetween(expr.span, op.span)
701
769
  };
702
770
  continue;
@@ -754,8 +822,8 @@ var Parser = class {
754
822
  parseReduce(start) {
755
823
  const source = this.parsePipe();
756
824
  this.consume("As", "Expected \"as\" after reduce source");
757
- const varToken = this.consume("Variable", "Expected variable after \"as\"");
758
- this.consume("LParen", "Expected \"(\" after variable");
825
+ const pattern = this.parseBindingPattern();
826
+ this.consume("LParen", "Expected \"(\" after binding pattern");
759
827
  const init = this.parseComma();
760
828
  this.consume("Semicolon", "Expected \";\" after init");
761
829
  const update = this.parseComma();
@@ -763,7 +831,7 @@ var Parser = class {
763
831
  return {
764
832
  kind: "Reduce",
765
833
  source,
766
- var: String(varToken.value),
834
+ pattern,
767
835
  init,
768
836
  update,
769
837
  span: spanBetween(start.span, end.span)
@@ -772,8 +840,8 @@ var Parser = class {
772
840
  parseForeach(start) {
773
841
  const source = this.parsePipe();
774
842
  this.consume("As", "Expected \"as\" after foreach source");
775
- const varToken = this.consume("Variable", "Expected variable after \"as\"");
776
- this.consume("LParen", "Expected \"(\" after variable");
843
+ const pattern = this.parseBindingPattern();
844
+ this.consume("LParen", "Expected \"(\" after binding pattern");
777
845
  const init = this.parseComma();
778
846
  this.consume("Semicolon", "Expected \";\" after init");
779
847
  const update = this.parseComma();
@@ -783,7 +851,7 @@ var Parser = class {
783
851
  return {
784
852
  kind: "Foreach",
785
853
  source,
786
- var: String(varToken.value),
854
+ pattern,
787
855
  init,
788
856
  update,
789
857
  extract,
@@ -1005,10 +1073,7 @@ var Parser = class {
1005
1073
  expr = {
1006
1074
  kind: "Try",
1007
1075
  body: expr,
1008
- handler: {
1009
- kind: "Identity",
1010
- span: op.span
1011
- },
1076
+ handler: void 0,
1012
1077
  span: spanBetween(expr.span, op.span)
1013
1078
  };
1014
1079
  continue;
@@ -1154,7 +1219,6 @@ const spanBetween = (a, b) => ({
1154
1219
  start: Math.min(a.start, b.start),
1155
1220
  end: Math.max(a.end, b.end)
1156
1221
  });
1157
-
1158
1222
  //#endregion
1159
1223
  //#region src/builtins/registry.ts
1160
1224
  const builtins = {};
@@ -1165,7 +1229,6 @@ const registerBuiltin = (spec) => {
1165
1229
  const registerBuiltins = (specs) => {
1166
1230
  for (const spec of specs) registerBuiltin(spec);
1167
1231
  };
1168
-
1169
1232
  //#endregion
1170
1233
  //#region src/value.ts
1171
1234
  /**
@@ -1192,7 +1255,7 @@ const valueEquals = (a, b) => {
1192
1255
  for (let i = 0; i < a.length; i += 1) if (!valueEquals(a[i], b[i])) return false;
1193
1256
  return true;
1194
1257
  }
1195
- if (isPlainObject(a) && isPlainObject(b)) {
1258
+ if (isPlainObject$1(a) && isPlainObject$1(b)) {
1196
1259
  const aKeys = Object.keys(a).sort();
1197
1260
  const bKeys = Object.keys(b).sort();
1198
1261
  if (aKeys.length !== bKeys.length) return false;
@@ -1229,7 +1292,7 @@ const compareValues = (a, b) => {
1229
1292
  }
1230
1293
  return a.length < b.length ? -1 : 1;
1231
1294
  }
1232
- if (isPlainObject(a) && isPlainObject(b)) {
1295
+ if (isPlainObject$1(a) && isPlainObject$1(b)) {
1233
1296
  const aKeys = Object.keys(a).sort();
1234
1297
  const bKeys = Object.keys(b).sort();
1235
1298
  const len = Math.min(aKeys.length, bKeys.length);
@@ -1263,7 +1326,7 @@ const typeRank = (value) => {
1263
1326
  * @param value - The value to check.
1264
1327
  * @returns `true` if `value` is a non-null object (and not an array).
1265
1328
  */
1266
- const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1329
+ const isPlainObject$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1267
1330
  /**
1268
1331
  * Checks if a value is a JSON array.
1269
1332
  *
@@ -1286,7 +1349,6 @@ const describeType = (value) => {
1286
1349
  if (Array.isArray(value)) return "array";
1287
1350
  return "object";
1288
1351
  };
1289
-
1290
1352
  //#endregion
1291
1353
  //#region src/builtins/utils.ts
1292
1354
  const emit$1 = (value, span, tracker) => {
@@ -1308,7 +1370,6 @@ const stableStringify = (value) => {
1308
1370
  if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
1309
1371
  return `{${Object.keys(value).sort().map((k) => `${JSON.stringify(k)}:${stableStringify(value[k])}`).join(",")}}`;
1310
1372
  };
1311
-
1312
1373
  //#endregion
1313
1374
  //#region src/builtins/std.ts
1314
1375
  const toJqString = (value) => {
@@ -1354,9 +1415,87 @@ const stdBuiltins = [
1354
1415
  if (typeof input === "string") yield emit$1(Array.from(input).length, span, tracker);
1355
1416
  else if (Array.isArray(input)) yield emit$1(input.length, span, tracker);
1356
1417
  else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input).length, span, tracker);
1418
+ else if (typeof input === "number") yield emit$1(Math.abs(input), span, tracker);
1357
1419
  else throw new RuntimeError(`Cannot take length of ${describeType(input)}`, span);
1358
1420
  }
1359
1421
  },
1422
+ {
1423
+ name: "arrays",
1424
+ arity: 0,
1425
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1426
+ if (Array.isArray(input)) yield emit$1(input, span, tracker);
1427
+ }
1428
+ },
1429
+ {
1430
+ name: "objects",
1431
+ arity: 0,
1432
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1433
+ if (isPlainObject$1(input)) yield emit$1(input, span, tracker);
1434
+ }
1435
+ },
1436
+ {
1437
+ name: "iterables",
1438
+ arity: 0,
1439
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1440
+ if (Array.isArray(input) || isPlainObject$1(input)) yield emit$1(input, span, tracker);
1441
+ }
1442
+ },
1443
+ {
1444
+ name: "booleans",
1445
+ arity: 0,
1446
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1447
+ if (typeof input === "boolean") yield emit$1(input, span, tracker);
1448
+ }
1449
+ },
1450
+ {
1451
+ name: "numbers",
1452
+ arity: 0,
1453
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1454
+ if (typeof input === "number") yield emit$1(input, span, tracker);
1455
+ }
1456
+ },
1457
+ {
1458
+ name: "strings",
1459
+ arity: 0,
1460
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1461
+ if (typeof input === "string") yield emit$1(input, span, tracker);
1462
+ }
1463
+ },
1464
+ {
1465
+ name: "nulls",
1466
+ arity: 0,
1467
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1468
+ if (input === null) yield emit$1(input, span, tracker);
1469
+ }
1470
+ },
1471
+ {
1472
+ name: "values",
1473
+ arity: 0,
1474
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1475
+ if (input !== null) yield emit$1(input, span, tracker);
1476
+ }
1477
+ },
1478
+ {
1479
+ name: "scalars",
1480
+ arity: 0,
1481
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1482
+ if (input === null || typeof input !== "object") yield emit$1(input, span, tracker);
1483
+ }
1484
+ },
1485
+ {
1486
+ name: "finites",
1487
+ arity: 0,
1488
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1489
+ if (typeof input === "number" && Number.isFinite(input)) yield emit$1(input, span, tracker);
1490
+ }
1491
+ },
1492
+ {
1493
+ name: "normals",
1494
+ arity: 0,
1495
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1496
+ if (typeof input === "number" && Number.isFinite(input) && input !== 0) yield emit$1(input, span, tracker);
1497
+ }
1498
+ },
1360
1499
  {
1361
1500
  name: "empty",
1362
1501
  arity: 0,
@@ -1379,7 +1518,7 @@ const stdBuiltins = [
1379
1518
  {
1380
1519
  name: "walk",
1381
1520
  arity: 1,
1382
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1521
+ apply: function* (input, args, env, tracker, evaluate, span) {
1383
1522
  const f = args[0];
1384
1523
  const walkRec = function* (curr) {
1385
1524
  tracker.step(span);
@@ -1388,7 +1527,7 @@ const stdBuiltins = [
1388
1527
  const newArr = [];
1389
1528
  for (const item of curr) for (const walkedItem of walkRec(item)) newArr.push(walkedItem);
1390
1529
  newStruct = newArr;
1391
- } else if (isPlainObject(curr)) {
1530
+ } else if (isPlainObject$1(curr)) {
1392
1531
  const newObj = {};
1393
1532
  const keys = Object.keys(curr).sort();
1394
1533
  let objValid = true;
@@ -1409,23 +1548,27 @@ const stdBuiltins = [
1409
1548
  if (!objValid) return;
1410
1549
  newStruct = newObj;
1411
1550
  }
1412
- yield* evaluate$1(f, newStruct, env, tracker);
1551
+ yield* evaluate(f, newStruct, env, tracker);
1413
1552
  };
1414
1553
  yield* walkRec(input);
1415
1554
  }
1416
1555
  }
1417
1556
  ];
1418
-
1419
1557
  //#endregion
1420
1558
  //#region src/builtins/errors.ts
1421
1559
  const errorBuiltins = [{
1560
+ name: "error",
1561
+ arity: 0,
1562
+ apply: function* (_input, _args, _env, _tracker, _eval, span) {
1563
+ throw new RuntimeError("null", span);
1564
+ }
1565
+ }, {
1422
1566
  name: "error",
1423
1567
  arity: 1,
1424
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1425
- for (const msg of evaluate$1(args[0], input, env, tracker)) throw new RuntimeError(typeof msg === "string" ? msg : stableStringify(msg), span);
1568
+ apply: function* (input, args, env, tracker, evaluate, span) {
1569
+ for (const msg of evaluate(args[0], input, env, tracker)) throw new RuntimeError(typeof msg === "string" ? msg : stableStringify(msg), span);
1426
1570
  }
1427
1571
  }];
1428
-
1429
1572
  //#endregion
1430
1573
  //#region src/builtins/strings.ts
1431
1574
  const checkContains = (a, b) => {
@@ -1433,7 +1576,7 @@ const checkContains = (a, b) => {
1433
1576
  if (typeof a !== typeof b) return false;
1434
1577
  if (typeof a === "string" && typeof b === "string") return a.includes(b);
1435
1578
  if (Array.isArray(a) && Array.isArray(b)) return b.every((bItem) => a.some((aItem) => checkContains(aItem, bItem)));
1436
- if (isPlainObject(a) && isPlainObject(b)) {
1579
+ if (isPlainObject$1(a) && isPlainObject$1(b)) {
1437
1580
  const keys = Object.keys(b);
1438
1581
  for (const key of keys) {
1439
1582
  if (!Object.prototype.hasOwnProperty.call(a, key)) return false;
@@ -1449,9 +1592,9 @@ const stringBuiltins = [
1449
1592
  {
1450
1593
  name: "split",
1451
1594
  arity: 1,
1452
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1595
+ apply: function* (input, args, env, tracker, evaluate, span) {
1453
1596
  if (typeof input !== "string") throw new RuntimeError("split input must be a string", span);
1454
- const sepGen = evaluate$1(args[0], input, env, tracker);
1597
+ const sepGen = evaluate(args[0], input, env, tracker);
1455
1598
  for (const sep of sepGen) {
1456
1599
  if (typeof sep !== "string") throw new RuntimeError("split separator must be a string", span);
1457
1600
  yield emit$1(input.split(sep), span, tracker);
@@ -1461,16 +1604,15 @@ const stringBuiltins = [
1461
1604
  {
1462
1605
  name: "join",
1463
1606
  arity: 1,
1464
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1607
+ apply: function* (input, args, env, tracker, evaluate, span) {
1465
1608
  if (!Array.isArray(input)) throw new RuntimeError("join input must be an array", span);
1466
- const sepGen = evaluate$1(args[0], input, env, tracker);
1609
+ const sepGen = evaluate(args[0], input, env, tracker);
1467
1610
  for (const sep of sepGen) {
1468
1611
  if (typeof sep !== "string") throw new RuntimeError("join separator must be a string", span);
1469
1612
  const parts = [];
1470
- for (const item of input) {
1471
- if (typeof item !== "string") throw new RuntimeError(`join expects strings, but got ${describeType(item)}`, span);
1472
- parts.push(item);
1473
- }
1613
+ for (const item of input) if (item === null) parts.push("");
1614
+ else if (typeof item === "string" || typeof item === "number" || typeof item === "boolean") parts.push(String(item));
1615
+ else throw new RuntimeError(`join cannot join ${describeType(item)}`, span);
1474
1616
  yield emit$1(parts.join(sep), span, tracker);
1475
1617
  }
1476
1618
  }
@@ -1478,9 +1620,9 @@ const stringBuiltins = [
1478
1620
  {
1479
1621
  name: "startswith",
1480
1622
  arity: 1,
1481
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1623
+ apply: function* (input, args, env, tracker, evaluate, span) {
1482
1624
  if (typeof input !== "string") throw new RuntimeError("startswith input must be a string", span);
1483
- const prefixGen = evaluate$1(args[0], input, env, tracker);
1625
+ const prefixGen = evaluate(args[0], input, env, tracker);
1484
1626
  for (const prefix of prefixGen) {
1485
1627
  if (typeof prefix !== "string") throw new RuntimeError("startswith prefix must be a string", span);
1486
1628
  yield emit$1(input.startsWith(prefix), span, tracker);
@@ -1490,9 +1632,9 @@ const stringBuiltins = [
1490
1632
  {
1491
1633
  name: "endswith",
1492
1634
  arity: 1,
1493
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1635
+ apply: function* (input, args, env, tracker, evaluate, span) {
1494
1636
  if (typeof input !== "string") throw new RuntimeError("endswith input must be a string", span);
1495
- const suffixGen = evaluate$1(args[0], input, env, tracker);
1637
+ const suffixGen = evaluate(args[0], input, env, tracker);
1496
1638
  for (const suffix of suffixGen) {
1497
1639
  if (typeof suffix !== "string") throw new RuntimeError("endswith suffix must be a string", span);
1498
1640
  yield emit$1(input.endsWith(suffix), span, tracker);
@@ -1502,16 +1644,16 @@ const stringBuiltins = [
1502
1644
  {
1503
1645
  name: "contains",
1504
1646
  arity: 1,
1505
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1506
- const bGen = evaluate$1(args[0], input, env, tracker);
1647
+ apply: function* (input, args, env, tracker, evaluate, span) {
1648
+ const bGen = evaluate(args[0], input, env, tracker);
1507
1649
  for (const b of bGen) yield emit$1(checkContains(input, b), span, tracker);
1508
1650
  }
1509
1651
  },
1510
1652
  {
1511
1653
  name: "index",
1512
1654
  arity: 1,
1513
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1514
- const searchGen = evaluate$1(args[0], input, env, tracker);
1655
+ apply: function* (input, args, env, tracker, evaluate, span) {
1656
+ const searchGen = evaluate(args[0], input, env, tracker);
1515
1657
  for (const search of searchGen) if (Array.isArray(input)) {
1516
1658
  let foundIndex = null;
1517
1659
  for (let i = 0; i < input.length; i++) {
@@ -1533,8 +1675,8 @@ const stringBuiltins = [
1533
1675
  {
1534
1676
  name: "rindex",
1535
1677
  arity: 1,
1536
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1537
- const searchGen = evaluate$1(args[0], input, env, tracker);
1678
+ apply: function* (input, args, env, tracker, evaluate, span) {
1679
+ const searchGen = evaluate(args[0], input, env, tracker);
1538
1680
  for (const search of searchGen) if (Array.isArray(input)) {
1539
1681
  let foundIndex = null;
1540
1682
  for (let i = input.length - 1; i >= 0; i--) {
@@ -1556,8 +1698,8 @@ const stringBuiltins = [
1556
1698
  {
1557
1699
  name: "indices",
1558
1700
  arity: 1,
1559
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1560
- const searchGen = evaluate$1(args[0], input, env, tracker);
1701
+ apply: function* (input, args, env, tracker, evaluate, span) {
1702
+ const searchGen = evaluate(args[0], input, env, tracker);
1561
1703
  for (const search of searchGen) {
1562
1704
  const indices = [];
1563
1705
  if (Array.isArray(input)) for (let i = 0; i < input.length; i++) {
@@ -1595,6 +1737,14 @@ const stringBuiltins = [
1595
1737
  yield emit$1(Array.from(input).map((c) => c.codePointAt(0)), span, tracker);
1596
1738
  }
1597
1739
  },
1740
+ {
1741
+ name: "utf8bytelength",
1742
+ arity: 0,
1743
+ apply: function* (input, _args, _env, tracker, _eval, span) {
1744
+ if (typeof input !== "string") throw new RuntimeError("utf8bytelength expects string", span);
1745
+ yield emit$1(utf8ByteLength(input), span, tracker);
1746
+ }
1747
+ },
1598
1748
  {
1599
1749
  name: "implode",
1600
1750
  arity: 0,
@@ -1611,9 +1761,9 @@ const stringBuiltins = [
1611
1761
  {
1612
1762
  name: "ltrimstr",
1613
1763
  arity: 1,
1614
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1764
+ apply: function* (input, args, env, tracker, evaluate, span) {
1615
1765
  if (typeof input !== "string") throw new RuntimeError("ltrimstr expects string", span);
1616
- const prefixGen = evaluate$1(args[0], input, env, tracker);
1766
+ const prefixGen = evaluate(args[0], input, env, tracker);
1617
1767
  for (const prefix of prefixGen) {
1618
1768
  if (typeof prefix !== "string") throw new RuntimeError("ltrimstr prefix must be a string", span);
1619
1769
  if (input.startsWith(prefix)) yield emit$1(input.slice(prefix.length), span, tracker);
@@ -1622,435 +1772,103 @@ const stringBuiltins = [
1622
1772
  }
1623
1773
  },
1624
1774
  {
1625
- name: "rtrimstr",
1775
+ name: "trimstr",
1626
1776
  arity: 1,
1627
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1628
- if (typeof input !== "string") throw new RuntimeError("rtrimstr expects string", span);
1629
- const suffixGen = evaluate$1(args[0], input, env, tracker);
1630
- for (const suffix of suffixGen) {
1631
- if (typeof suffix !== "string") throw new RuntimeError("rtrimstr suffix must be a string", span);
1632
- if (input.endsWith(suffix)) yield emit$1(input.slice(0, input.length - suffix.length), span, tracker);
1633
- else yield emit$1(input, span, tracker);
1777
+ apply: function* (input, args, env, tracker, evaluate, span) {
1778
+ if (typeof input !== "string") throw new RuntimeError("trimstr expects string", span);
1779
+ for (const trim of evaluate(args[0], input, env, tracker)) {
1780
+ if (typeof trim !== "string") throw new RuntimeError("trimstr argument must be string", span);
1781
+ let result = input;
1782
+ if (result.startsWith(trim)) result = result.slice(trim.length);
1783
+ if (result.endsWith(trim)) result = result.slice(0, result.length - trim.length);
1784
+ yield emit$1(result, span, tracker);
1634
1785
  }
1635
1786
  }
1636
1787
  },
1637
1788
  {
1638
- name: "ascii_downcase",
1789
+ name: "trim",
1639
1790
  arity: 0,
1640
1791
  apply: function* (input, _args, _env, tracker, _eval, span) {
1641
- if (typeof input !== "string") throw new RuntimeError("ascii_downcase expects string", span);
1642
- yield emit$1(input.toLowerCase(), span, tracker);
1792
+ if (typeof input !== "string") throw new RuntimeError("trim expects string", span);
1793
+ yield emit$1(input.trim(), span, tracker);
1643
1794
  }
1644
1795
  },
1645
1796
  {
1646
- name: "ascii_upcase",
1797
+ name: "ltrim",
1647
1798
  arity: 0,
1648
1799
  apply: function* (input, _args, _env, tracker, _eval, span) {
1649
- if (typeof input !== "string") throw new RuntimeError("ascii_upcase expects string", span);
1650
- yield emit$1(input.toUpperCase(), span, tracker);
1800
+ if (typeof input !== "string") throw new RuntimeError("ltrim expects string", span);
1801
+ yield emit$1(input.trimStart(), span, tracker);
1651
1802
  }
1652
- }
1653
- ];
1654
-
1655
- //#endregion
1656
- //#region src/builtins/collections.ts
1657
- function sortStable(arr, compare$1) {
1658
- return arr.map((item, index) => ({
1659
- item,
1660
- index
1661
- })).sort((a, b) => {
1662
- const cmp = compare$1(a.item, b.item);
1663
- return cmp !== 0 ? cmp : a.index - b.index;
1664
- }).map((p) => p.item);
1665
- }
1666
- const collectionBuiltins = [
1803
+ },
1667
1804
  {
1668
- name: "keys",
1805
+ name: "rtrim",
1669
1806
  arity: 0,
1670
1807
  apply: function* (input, _args, _env, tracker, _eval, span) {
1671
- if (Array.isArray(input)) yield emit$1(Array.from({ length: input.length }, (_, i) => i), span, tracker);
1672
- else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input).sort(), span, tracker);
1673
- else throw new RuntimeError(`keys expects an array or object`, span);
1674
- }
1675
- },
1676
- {
1677
- name: "has",
1678
- arity: 1,
1679
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1680
- const keyFilter = args[0];
1681
- for (const key of evaluate$1(keyFilter, input, env, tracker)) if (Array.isArray(input)) {
1682
- const idx = ensureIndex(key);
1683
- yield emit$1(idx !== void 0 && idx >= 0 && idx < input.length, span, tracker);
1684
- } else if (input !== null && typeof input === "object") {
1685
- let keyStr;
1686
- if (typeof key === "string") keyStr = key;
1687
- else if (typeof key === "number") keyStr = key.toString();
1688
- else throw new RuntimeError(`has() key must be string or number for object input`, span);
1689
- yield emit$1(Object.prototype.hasOwnProperty.call(input, keyStr), span, tracker);
1690
- } else throw new RuntimeError(`has() expects an array or object input`, span);
1691
- }
1692
- },
1693
- {
1694
- name: "map",
1695
- arity: 1,
1696
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1697
- if (!Array.isArray(input)) throw new RuntimeError("map expects an array", span);
1698
- const result = [];
1699
- const filter = args[0];
1700
- for (const item of input) {
1701
- tracker.step(span);
1702
- for (const output of evaluate$1(filter, item, env, tracker)) result.push(output);
1703
- }
1704
- yield emit$1(result, span, tracker);
1808
+ if (typeof input !== "string") throw new RuntimeError("rtrim expects string", span);
1809
+ yield emit$1(input.trimEnd(), span, tracker);
1705
1810
  }
1706
1811
  },
1707
1812
  {
1708
- name: "select",
1813
+ name: "rtrimstr",
1709
1814
  arity: 1,
1710
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1711
- const filter = args[0];
1712
- for (const res of evaluate$1(filter, input, env, tracker)) if (isTruthy(res)) {
1713
- yield emit$1(input, span, tracker);
1714
- return;
1815
+ apply: function* (input, args, env, tracker, evaluate, span) {
1816
+ if (typeof input !== "string") throw new RuntimeError("rtrimstr expects string", span);
1817
+ const suffixGen = evaluate(args[0], input, env, tracker);
1818
+ for (const suffix of suffixGen) {
1819
+ if (typeof suffix !== "string") throw new RuntimeError("rtrimstr suffix must be a string", span);
1820
+ if (input.endsWith(suffix)) yield emit$1(input.slice(0, input.length - suffix.length), span, tracker);
1821
+ else yield emit$1(input, span, tracker);
1715
1822
  }
1716
1823
  }
1717
1824
  },
1718
1825
  {
1719
- name: "sort",
1826
+ name: "ascii_downcase",
1720
1827
  arity: 0,
1721
1828
  apply: function* (input, _args, _env, tracker, _eval, span) {
1722
- if (!Array.isArray(input)) throw new RuntimeError("sort expects an array", span);
1723
- const sorted = sortStable(input, (a, b) => compareValues(a, b));
1724
- tracker.step(span);
1725
- yield emit$1(sorted, span, tracker);
1726
- }
1727
- },
1728
- {
1729
- name: "sort_by",
1730
- arity: 1,
1731
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1732
- if (!Array.isArray(input)) throw new RuntimeError("sort_by expects an array", span);
1733
- const filter = args[0];
1734
- const pairs = [];
1735
- for (const item of input) {
1736
- tracker.step(span);
1737
- const keys = Array.from(evaluate$1(filter, item, env, tracker));
1738
- if (keys.length !== 1) throw new RuntimeError("sort_by key expression must return exactly one value", span);
1739
- pairs.push({
1740
- val: item,
1741
- key: keys[0]
1742
- });
1743
- }
1744
- yield emit$1(sortStable(pairs, (a, b) => compareValues(a.key, b.key)).map((p) => p.val), span, tracker);
1829
+ if (typeof input !== "string") throw new RuntimeError("ascii_downcase expects string", span);
1830
+ yield emit$1(input.replace(/[A-Z]/g, (char) => char.toLowerCase()), span, tracker);
1745
1831
  }
1746
1832
  },
1747
1833
  {
1748
- name: "unique",
1834
+ name: "ascii_upcase",
1749
1835
  arity: 0,
1750
1836
  apply: function* (input, _args, _env, tracker, _eval, span) {
1751
- if (!Array.isArray(input)) throw new RuntimeError("unique expects an array", span);
1752
- const seen = [];
1753
- const result = [];
1754
- for (const item of input) {
1755
- tracker.step(span);
1756
- if (!seen.some((s) => valueEquals(s, item))) {
1757
- seen.push(item);
1758
- result.push(item);
1759
- }
1760
- }
1761
- yield emit$1(result, span, tracker);
1762
- }
1763
- },
1764
- {
1765
- name: "unique_by",
1766
- arity: 1,
1767
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1768
- if (!Array.isArray(input)) throw new RuntimeError("unique_by expects an array", span);
1769
- const filter = args[0];
1770
- const seenKeys = [];
1771
- const result = [];
1772
- for (const item of input) {
1773
- tracker.step(span);
1774
- const keys = Array.from(evaluate$1(filter, item, env, tracker));
1775
- if (keys.length !== 1) throw new RuntimeError("unique_by key expression must return exactly one value", span);
1776
- const key = keys[0];
1777
- if (!seenKeys.some((s) => valueEquals(s, key))) {
1778
- seenKeys.push(key);
1779
- result.push(item);
1780
- }
1781
- }
1782
- yield emit$1(result, span, tracker);
1837
+ if (typeof input !== "string") throw new RuntimeError("ascii_upcase expects string", span);
1838
+ yield emit$1(input.replace(/[a-z]/g, (char) => char.toUpperCase()), span, tracker);
1783
1839
  }
1784
1840
  },
1785
1841
  {
1786
- name: "to_entries",
1842
+ name: "tojson",
1787
1843
  arity: 0,
1788
1844
  apply: function* (input, _args, _env, tracker, _eval, span) {
1789
- if (Array.isArray(input)) yield emit$1(input.map((v, i) => ({
1790
- key: i,
1791
- value: v
1792
- })), span, tracker);
1793
- else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input).sort().map((k) => ({
1794
- key: k,
1795
- value: input[k]
1796
- })), span, tracker);
1797
- else throw new RuntimeError("to_entries expects array or object", span);
1845
+ yield emit$1(stableStringify(input), span, tracker);
1798
1846
  }
1799
1847
  },
1800
1848
  {
1801
- name: "from_entries",
1849
+ name: "fromjson",
1802
1850
  arity: 0,
1803
1851
  apply: function* (input, _args, _env, tracker, _eval, span) {
1804
- if (!Array.isArray(input)) throw new RuntimeError("from_entries expects an array", span);
1805
- const result = {};
1806
- for (const item of input) {
1807
- tracker.step(span);
1808
- if (item === null || typeof item !== "object" || Array.isArray(item)) throw new RuntimeError("from_entries expects array of objects", span);
1809
- const obj = item;
1810
- if (!("key" in obj) || !("value" in obj)) throw new RuntimeError("from_entries items must have \"key\" and \"value\"", span);
1811
- const key = obj["key"];
1812
- if (typeof key !== "string") throw new RuntimeError("from_entries object keys must be strings", span);
1813
- result[key] = obj["value"];
1852
+ if (typeof input !== "string") throw new RuntimeError("fromjson expects string", span);
1853
+ try {
1854
+ yield emit$1(JSON.parse(input), span, tracker);
1855
+ } catch {
1856
+ throw new RuntimeError("fromjson could not parse JSON", span);
1814
1857
  }
1815
- yield emit$1(result, span, tracker);
1816
- }
1817
- },
1818
- {
1819
- name: "with_entries",
1820
- arity: 1,
1821
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1822
- let entries;
1823
- if (Array.isArray(input)) entries = input.map((v, i) => ({
1824
- key: i,
1825
- value: v
1826
- }));
1827
- else if (input !== null && typeof input === "object") entries = Object.keys(input).sort().map((k) => ({
1828
- key: k,
1829
- value: input[k]
1830
- }));
1831
- else throw new RuntimeError("with_entries expects array or object", span);
1832
- const transformed = [];
1833
- const filter = args[0];
1834
- for (const entry of entries) {
1835
- tracker.step(span);
1836
- for (const outVar of evaluate$1(filter, entry, env, tracker)) transformed.push(outVar);
1837
- }
1838
- const result = {};
1839
- for (const item of transformed) {
1840
- if (item === null || typeof item !== "object" || Array.isArray(item)) throw new RuntimeError("with_entries filter must produce objects", span);
1841
- const obj = item;
1842
- if (!("key" in obj) || !("value" in obj)) throw new RuntimeError("with_entries items must have \"key\" and \"value\"", span);
1843
- const key = obj["key"];
1844
- if (typeof key !== "string") throw new RuntimeError("with_entries keys must be strings", span);
1845
- result[key] = obj["value"];
1846
- }
1847
- yield emit$1(result, span, tracker);
1848
- }
1849
- },
1850
- {
1851
- name: "group_by",
1852
- arity: 1,
1853
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1854
- if (!Array.isArray(input)) throw new RuntimeError("group_by expects an array", span);
1855
- const pairs = [];
1856
- const filter = args[0];
1857
- for (const item of input) {
1858
- tracker.step(span);
1859
- const keys = Array.from(evaluate$1(filter, item, env, tracker));
1860
- if (keys.length !== 1) throw new RuntimeError("group_by key expression must return exactly one value", span);
1861
- pairs.push({
1862
- val: item,
1863
- key: keys[0]
1864
- });
1865
- }
1866
- const sorted = sortStable(pairs, (a, b) => compareValues(a.key, b.key));
1867
- const groups = [];
1868
- if (sorted.length > 0) {
1869
- let currentGroup = [sorted[0].val];
1870
- let currentKey = sorted[0].key;
1871
- for (let i = 1; i < sorted.length; i++) {
1872
- const pair = sorted[i];
1873
- if (compareValues(pair.key, currentKey) === 0) currentGroup.push(pair.val);
1874
- else {
1875
- groups.push(currentGroup);
1876
- currentGroup = [pair.val];
1877
- currentKey = pair.key;
1878
- }
1879
- }
1880
- groups.push(currentGroup);
1881
- }
1882
- yield emit$1(groups, span, tracker);
1883
- }
1884
- },
1885
- {
1886
- name: "reverse",
1887
- arity: 0,
1888
- apply: function* (input, _args, _env, tracker, _eval, span) {
1889
- if (!Array.isArray(input)) throw new RuntimeError("reverse expects an array", span);
1890
- yield emit$1([...input].reverse(), span, tracker);
1891
- }
1892
- },
1893
- {
1894
- name: "flatten",
1895
- arity: 0,
1896
- apply: function* (input, _args, _env, tracker, _eval, span) {
1897
- if (!Array.isArray(input)) throw new RuntimeError("flatten expects an array", span);
1898
- const flattenRec = (arr) => {
1899
- let res = [];
1900
- for (const item of arr) if (Array.isArray(item)) res = res.concat(flattenRec(item));
1901
- else res.push(item);
1902
- return res;
1903
- };
1904
- yield emit$1(flattenRec(input), span, tracker);
1905
- }
1906
- },
1907
- {
1908
- name: "flatten",
1909
- arity: 1,
1910
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1911
- if (!Array.isArray(input)) throw new RuntimeError("flatten expects an array", span);
1912
- const depths = evaluate$1(args[0], input, env, tracker);
1913
- for (const depthVal of depths) {
1914
- if (typeof depthVal !== "number") throw new RuntimeError("flatten depth must be a number", span);
1915
- const flattenDepth = (arr, d) => {
1916
- if (d <= 0) return arr;
1917
- let res = [];
1918
- for (const item of arr) if (Array.isArray(item)) res = res.concat(flattenDepth(item, d - 1));
1919
- else res.push(item);
1920
- return res;
1921
- };
1922
- yield emit$1(flattenDepth(input, depthVal), span, tracker);
1923
- }
1924
- }
1925
- },
1926
- {
1927
- name: "keys_unsorted",
1928
- arity: 0,
1929
- apply: function* (input, _args, _env, tracker, _eval, span) {
1930
- if (Array.isArray(input)) yield emit$1(Array.from({ length: input.length }, (_, i) => i), span, tracker);
1931
- else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input), span, tracker);
1932
- else throw new RuntimeError(`keys_unsorted expects an array or object`, span);
1933
- }
1934
- },
1935
- {
1936
- name: "transpose",
1937
- arity: 0,
1938
- apply: function* (input, _args, _env, tracker, _eval, span) {
1939
- if (!Array.isArray(input)) throw new RuntimeError("transpose expects an array", span);
1940
- const arr = input;
1941
- if (arr.length === 0) {
1942
- yield emit$1([], span, tracker);
1943
- return;
1944
- }
1945
- let maxLen = 0;
1946
- for (const row of arr) {
1947
- if (!Array.isArray(row)) throw new RuntimeError("transpose input must be array of arrays", span);
1948
- if (row.length > maxLen) maxLen = row.length;
1949
- }
1950
- const result = [];
1951
- for (let j = 0; j < maxLen; j++) {
1952
- const newRow = [];
1953
- for (let i = 0; i < arr.length; i++) {
1954
- const row = arr[i];
1955
- const val = j < row.length ? row[j] : null;
1956
- newRow.push(val);
1957
- }
1958
- result.push(newRow);
1959
- }
1960
- yield emit$1(result, span, tracker);
1961
- }
1962
- },
1963
- {
1964
- name: "bsearch",
1965
- arity: 1,
1966
- apply: function* (input, args, env, tracker, evaluate$1, span) {
1967
- if (!Array.isArray(input)) throw new RuntimeError("bsearch expects an array", span);
1968
- const targetGen = evaluate$1(args[0], input, env, tracker);
1969
- for (const target of targetGen) {
1970
- let low = 0;
1971
- let high = input.length - 1;
1972
- let idx = -1;
1973
- while (low <= high) {
1974
- const mid = Math.floor((low + high) / 2);
1975
- const cmp = compareValues(input[mid], target);
1976
- if (cmp === 0) {
1977
- idx = mid;
1978
- break;
1979
- } else if (cmp < 0) low = mid + 1;
1980
- else high = mid - 1;
1981
- }
1982
- if (idx !== -1) yield emit$1(idx, span, tracker);
1983
- else yield emit$1(-low - 1, span, tracker);
1984
- }
1985
- }
1986
- },
1987
- {
1988
- name: "combinations",
1989
- arity: 0,
1990
- apply: function* (input, _args, _env, tracker, _eval, span) {
1991
- if (!Array.isArray(input)) throw new RuntimeError("combinations expects an array", span);
1992
- if (input.some((x) => !Array.isArray(x))) throw new RuntimeError("combinations input must be array of arrays", span);
1993
- const arrays = input;
1994
- if (arrays.length === 0) {
1995
- yield emit$1([], span, tracker);
1996
- return;
1997
- }
1998
- const helper = function* (idx, current) {
1999
- if (idx === arrays.length) {
2000
- yield [...current];
2001
- return;
2002
- }
2003
- const arr = arrays[idx];
2004
- if (arr.length === 0) return;
2005
- for (const item of arr) {
2006
- current.push(item);
2007
- yield* helper(idx + 1, current);
2008
- current.pop();
2009
- }
2010
- };
2011
- for (const combo of helper(0, [])) yield emit$1(combo, span, tracker);
2012
- }
2013
- },
2014
- {
2015
- name: "combinations",
2016
- arity: 1,
2017
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2018
- if (!Array.isArray(input)) throw new RuntimeError("combinations expects an array", span);
2019
- const nGen = evaluate$1(args[0], input, env, tracker);
2020
- for (const nVal of nGen) {
2021
- if (typeof nVal !== "number") throw new RuntimeError("combinations(n) expects n to be number", span);
2022
- if (nVal === 0) {
2023
- yield emit$1([], span, tracker);
2024
- continue;
2025
- }
2026
- const arrays = [];
2027
- for (let i = 0; i < nVal; i++) arrays.push(input);
2028
- const helper = function* (idx, current) {
2029
- if (idx === arrays.length) {
2030
- yield [...current];
2031
- return;
2032
- }
2033
- const arr = arrays[idx];
2034
- for (const item of arr) {
2035
- current.push(item);
2036
- yield* helper(idx + 1, current);
2037
- current.pop();
2038
- }
2039
- };
2040
- if (input.length === 0 && nVal > 0) {} else for (const combo of helper(0, [])) yield emit$1(combo, span, tracker);
2041
- }
2042
- }
2043
- },
2044
- {
2045
- name: "inside",
2046
- arity: 1,
2047
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2048
- const bGen = evaluate$1(args[0], input, env, tracker);
2049
- for (const b of bGen) yield emit$1(checkContains(b, input), span, tracker);
2050
1858
  }
2051
1859
  }
2052
1860
  ];
2053
-
1861
+ const utf8ByteLength = (input) => {
1862
+ let length = 0;
1863
+ for (const char of input) {
1864
+ const codePoint = char.codePointAt(0);
1865
+ if (codePoint <= 127) length += 1;
1866
+ else if (codePoint <= 2047) length += 2;
1867
+ else if (codePoint <= 65535) length += 3;
1868
+ else length += 4;
1869
+ }
1870
+ return length;
1871
+ };
2054
1872
  //#endregion
2055
1873
  //#region src/eval/path_eval.ts
2056
1874
  /**
@@ -2063,17 +1881,17 @@ const collectionBuiltins = [
2063
1881
  * @param tracker - Limits tracker.
2064
1882
  * @param evaluate - Recursive evaluator.
2065
1883
  */
2066
- const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
1884
+ const evaluatePath = function* (node, input, env, tracker, evaluate) {
2067
1885
  switch (node.kind) {
2068
1886
  case "Identity":
2069
1887
  yield [];
2070
1888
  return;
2071
1889
  case "FieldAccess":
2072
- for (const parent of evaluatePath(node.target, input, env, tracker, evaluate$1)) yield [...parent, node.field];
1890
+ for (const parent of evaluatePath(node.target, input, env, tracker, evaluate)) yield [...parent, node.field];
2073
1891
  return;
2074
1892
  case "IndexAccess": {
2075
- const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate$1));
2076
- const output = evaluate$1(node.index, input, env, tracker);
1893
+ const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate));
1894
+ const output = evaluate(node.index, input, env, tracker);
2077
1895
  for (const keyVal of output) {
2078
1896
  let key;
2079
1897
  if (typeof keyVal === "string") key = keyVal;
@@ -2084,19 +1902,19 @@ const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
2084
1902
  return;
2085
1903
  }
2086
1904
  case "Pipe": {
2087
- const leftPaths = Array.from(evaluatePath(node.left, input, env, tracker, evaluate$1));
1905
+ const leftPaths = Array.from(evaluatePath(node.left, input, env, tracker, evaluate));
2088
1906
  for (const p of leftPaths) {
2089
1907
  const val = getPath(input, p) ?? null;
2090
- for (const q of evaluatePath(node.right, val, env, tracker, evaluate$1)) yield [...p, ...q];
1908
+ for (const q of evaluatePath(node.right, val, env, tracker, evaluate)) yield [...p, ...q];
2091
1909
  }
2092
1910
  return;
2093
1911
  }
2094
1912
  case "Comma":
2095
- yield* evaluatePath(node.left, input, env, tracker, evaluate$1);
2096
- yield* evaluatePath(node.right, input, env, tracker, evaluate$1);
1913
+ yield* evaluatePath(node.left, input, env, tracker, evaluate);
1914
+ yield* evaluatePath(node.right, input, env, tracker, evaluate);
2097
1915
  return;
2098
1916
  case "Iterate": {
2099
- const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate$1));
1917
+ const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate));
2100
1918
  for (const p of parentPaths) {
2101
1919
  const val = getPath(input, p);
2102
1920
  if (Array.isArray(val)) for (let i = 0; i < val.length; i++) yield [...p, i];
@@ -2110,7 +1928,7 @@ const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
2110
1928
  }
2111
1929
  case "Call":
2112
1930
  if (node.name === "select") {
2113
- const conds = evaluate$1(node.args[0], input, env, tracker);
1931
+ const conds = evaluate(node.args[0], input, env, tracker);
2114
1932
  let matched = false;
2115
1933
  for (const c of conds) if (c !== null && c !== false) matched = true;
2116
1934
  if (matched) yield [];
@@ -2118,9 +1936,9 @@ const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
2118
1936
  }
2119
1937
  throw new RuntimeError(`Function ${node.name} not supported in path expression`, node.span);
2120
1938
  case "Slice": {
2121
- const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate$1));
2122
- const startRes = node.start ? Array.from(evaluate$1(node.start, input, env, tracker)) : [null];
2123
- const endRes = node.end ? Array.from(evaluate$1(node.end, input, env, tracker)) : [null];
1939
+ const parentPaths = Array.from(evaluatePath(node.target, input, env, tracker, evaluate));
1940
+ const startRes = node.start ? Array.from(evaluate(node.start, input, env, tracker)) : [null];
1941
+ const endRes = node.end ? Array.from(evaluate(node.end, input, env, tracker)) : [null];
2124
1942
  for (const startVal of startRes) for (const endVal of endRes) {
2125
1943
  const sliceSpec = {
2126
1944
  start: typeof startVal === "number" ? startVal : null,
@@ -2132,7 +1950,7 @@ const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
2132
1950
  }
2133
1951
  case "Try":
2134
1952
  try {
2135
- yield* evaluatePath(node.body, input, env, tracker, evaluate$1);
1953
+ yield* evaluatePath(node.body, input, env, tracker, evaluate);
2136
1954
  } catch (e) {
2137
1955
  if (!(e instanceof RuntimeError)) throw e;
2138
1956
  }
@@ -2143,24 +1961,27 @@ const evaluatePath = function* (node, input, env, tracker, evaluate$1) {
2143
1961
  default: throw new RuntimeError("Invalid path expression", node.span);
2144
1962
  }
2145
1963
  };
2146
-
2147
1964
  //#endregion
2148
1965
  //#region src/builtins/paths.ts
2149
1966
  function* traversePaths(root, currentPath, span, tracker) {
2150
1967
  tracker.step(span);
2151
- if (root === null || typeof root !== "object" || Array.isArray(root) && root.length === 0 || isPlainObject(root) && Object.keys(root).length === 0) {
2152
- yield emit$1([...currentPath], span, tracker);
2153
- return;
1968
+ if (Array.isArray(root)) for (let i = 0; i < root.length; i++) {
1969
+ const path = [...currentPath, i];
1970
+ yield emit$1(path, span, tracker);
1971
+ yield* traversePaths(root[i], path, span, tracker);
2154
1972
  }
2155
- if (Array.isArray(root)) for (let i = 0; i < root.length; i++) yield* traversePaths(root[i], [...currentPath, i], span, tracker);
2156
- else if (isPlainObject(root)) {
1973
+ else if (isPlainObject$1(root)) {
2157
1974
  const keys = Object.keys(root).sort();
2158
- for (const key of keys) yield* traversePaths(root[key], [...currentPath, key], span, tracker);
1975
+ for (const key of keys) {
1976
+ const path = [...currentPath, key];
1977
+ yield emit$1(path, span, tracker);
1978
+ yield* traversePaths(root[key], path, span, tracker);
1979
+ }
2159
1980
  }
2160
1981
  }
2161
1982
  const isPath = (val) => {
2162
1983
  if (!Array.isArray(val)) return false;
2163
- return val.every((p) => typeof p === "string" || typeof p === "number" && Number.isInteger(p) || isPlainObject(p) && ("start" in p || "end" in p));
1984
+ return val.every((p) => typeof p === "string" || typeof p === "number" && Number.isInteger(p) || isPlainObject$1(p) && ("start" in p || "end" in p));
2164
1985
  };
2165
1986
  const ensurePath = (val, span) => {
2166
1987
  if (isPath(val)) return val;
@@ -2170,7 +1991,7 @@ const getPath = (root, path) => {
2170
1991
  let curr = root;
2171
1992
  for (const part of path) {
2172
1993
  if (curr === null) return void 0;
2173
- if (typeof part === "string" && isPlainObject(curr)) {
1994
+ if (typeof part === "string" && isPlainObject$1(curr)) {
2174
1995
  if (!Object.prototype.hasOwnProperty.call(curr, part)) return void 0;
2175
1996
  curr = curr[part];
2176
1997
  } else if (typeof part === "number" && Array.isArray(curr)) {
@@ -2185,7 +2006,7 @@ const updatePath = (root, path, updateFn, span, depth = 0) => {
2185
2006
  const [head, ...tail] = path;
2186
2007
  if (typeof head === "string") {
2187
2008
  let obj = {};
2188
- if (isPlainObject(root)) obj = { ...root };
2009
+ if (isPlainObject$1(root)) obj = { ...root };
2189
2010
  else if (root === null) obj = {};
2190
2011
  else throw new RuntimeError(`Cannot index ${describeType(root)} with string "${head}"`, span);
2191
2012
  const newVal = updatePath((Object.prototype.hasOwnProperty.call(obj, head) ? obj[head] : void 0) ?? null, tail, updateFn, span, depth + 1);
@@ -2225,7 +2046,7 @@ const updatePath = (root, path, updateFn, span, depth = 0) => {
2225
2046
  };
2226
2047
  const deletePaths = (root, paths, span) => {
2227
2048
  if (paths.some((p) => p.length === 0)) return null;
2228
- if (isPlainObject(root)) {
2049
+ if (isPlainObject$1(root)) {
2229
2050
  const result = { ...root };
2230
2051
  const relevantPaths = paths.filter((p) => p.length > 0 && typeof p[0] === "string");
2231
2052
  const byKey = {};
@@ -2270,19 +2091,35 @@ const pathBuiltins = [
2270
2091
  yield* traversePaths(input, [], span, tracker);
2271
2092
  }
2272
2093
  },
2094
+ {
2095
+ name: "paths",
2096
+ arity: 1,
2097
+ apply: function* (input, args, env, tracker, evaluate, span) {
2098
+ for (const pathVal of traversePaths(input, [], span, tracker)) {
2099
+ const path = ensurePath(pathVal, span);
2100
+ const value = getPath(input, path) ?? null;
2101
+ let matched = false;
2102
+ for (const result of evaluate(args[0], value, env, tracker)) if (result !== null && result !== false) {
2103
+ matched = true;
2104
+ break;
2105
+ }
2106
+ if (matched) yield emit$1(path, span, tracker);
2107
+ }
2108
+ }
2109
+ },
2273
2110
  {
2274
2111
  name: "getpath",
2275
2112
  arity: 1,
2276
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2277
- for (const pathVal of evaluate$1(args[0], input, env, tracker)) yield emit$1(getPath(input, ensurePath(pathVal, span)) ?? null, span, tracker);
2113
+ apply: function* (input, args, env, tracker, evaluate, span) {
2114
+ for (const pathVal of evaluate(args[0], input, env, tracker)) yield emit$1(getPath(input, ensurePath(pathVal, span)) ?? null, span, tracker);
2278
2115
  }
2279
2116
  },
2280
2117
  {
2281
2118
  name: "setpath",
2282
2119
  arity: 2,
2283
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2284
- const paths = Array.from(evaluate$1(args[0], input, env, tracker));
2285
- const values = Array.from(evaluate$1(args[1], input, env, tracker));
2120
+ apply: function* (input, args, env, tracker, evaluate, span) {
2121
+ const paths = Array.from(evaluate(args[0], input, env, tracker));
2122
+ const values = Array.from(evaluate(args[1], input, env, tracker));
2286
2123
  for (const pathVal of paths) {
2287
2124
  const path = ensurePath(pathVal, span);
2288
2125
  for (const val of values) yield emit$1(updatePath(input, path, () => val, span) ?? null, span, tracker);
@@ -2292,30 +2129,508 @@ const pathBuiltins = [
2292
2129
  {
2293
2130
  name: "delpaths",
2294
2131
  arity: 1,
2295
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2296
- for (const pathsVal of evaluate$1(args[0], input, env, tracker)) {
2132
+ apply: function* (input, args, env, tracker, evaluate, span) {
2133
+ for (const pathsVal of evaluate(args[0], input, env, tracker)) {
2297
2134
  if (!Array.isArray(pathsVal)) throw new RuntimeError("delpaths expects an array of paths", span);
2298
2135
  yield emit$1(deletePaths(input, pathsVal.map((p) => ensurePath(p, span)), span), span, tracker);
2299
2136
  }
2300
2137
  }
2301
2138
  },
2302
2139
  {
2303
- name: "path",
2140
+ name: "path",
2141
+ arity: 1,
2142
+ apply: function* (input, args, env, tracker, evaluate, span) {
2143
+ for (const p of evaluatePath(args[0], input, env, tracker, evaluate)) yield emit$1(p, span, tracker);
2144
+ }
2145
+ }
2146
+ ];
2147
+ //#endregion
2148
+ //#region src/builtins/collections.ts
2149
+ function sortStable(arr, compare) {
2150
+ return arr.map((item, index) => ({
2151
+ item,
2152
+ index
2153
+ })).sort((a, b) => {
2154
+ const cmp = compare(a.item, b.item);
2155
+ return cmp !== 0 ? cmp : a.index - b.index;
2156
+ }).map((p) => p.item);
2157
+ }
2158
+ const collectionBuiltins = [
2159
+ {
2160
+ name: "keys",
2161
+ arity: 0,
2162
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2163
+ if (Array.isArray(input)) yield emit$1(Array.from({ length: input.length }, (_, i) => i), span, tracker);
2164
+ else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input).sort(), span, tracker);
2165
+ else throw new RuntimeError(`keys expects an array or object`, span);
2166
+ }
2167
+ },
2168
+ {
2169
+ name: "has",
2170
+ arity: 1,
2171
+ apply: function* (input, args, env, tracker, evaluate, span) {
2172
+ const keyFilter = args[0];
2173
+ for (const key of evaluate(keyFilter, input, env, tracker)) if (Array.isArray(input)) {
2174
+ const idx = ensureIndex(key);
2175
+ yield emit$1(idx !== void 0 && idx >= 0 && idx < input.length, span, tracker);
2176
+ } else if (input !== null && typeof input === "object") {
2177
+ let keyStr;
2178
+ if (typeof key === "string") keyStr = key;
2179
+ else if (typeof key === "number") keyStr = key.toString();
2180
+ else throw new RuntimeError(`has() key must be string or number for object input`, span);
2181
+ yield emit$1(Object.prototype.hasOwnProperty.call(input, keyStr), span, tracker);
2182
+ } else throw new RuntimeError(`has() expects an array or object input`, span);
2183
+ }
2184
+ },
2185
+ {
2186
+ name: "map",
2187
+ arity: 1,
2188
+ apply: function* (input, args, env, tracker, evaluate, span) {
2189
+ if (!Array.isArray(input)) throw new RuntimeError("map expects an array", span);
2190
+ const result = [];
2191
+ const filter = args[0];
2192
+ for (const item of input) {
2193
+ tracker.step(span);
2194
+ for (const output of evaluate(filter, item, env, tracker)) result.push(output);
2195
+ }
2196
+ yield emit$1(result, span, tracker);
2197
+ }
2198
+ },
2199
+ {
2200
+ name: "map_values",
2201
+ arity: 1,
2202
+ apply: function* (input, args, env, tracker, evaluate, span) {
2203
+ const filter = args[0];
2204
+ if (Array.isArray(input)) {
2205
+ const result = [];
2206
+ for (const item of input) {
2207
+ tracker.step(span);
2208
+ for (const output of evaluate(filter, item, env, tracker)) result.push(output);
2209
+ }
2210
+ yield emit$1(result, span, tracker);
2211
+ return;
2212
+ }
2213
+ if (input !== null && typeof input === "object") {
2214
+ const result = {};
2215
+ for (const key of Object.keys(input)) {
2216
+ tracker.step(span);
2217
+ let last;
2218
+ let found = false;
2219
+ for (const output of evaluate(filter, input[key], env, tracker)) {
2220
+ last = output;
2221
+ found = true;
2222
+ }
2223
+ if (found) result[key] = last;
2224
+ }
2225
+ yield emit$1(result, span, tracker);
2226
+ return;
2227
+ }
2228
+ throw new RuntimeError("map_values expects an array or object", span);
2229
+ }
2230
+ },
2231
+ {
2232
+ name: "select",
2233
+ arity: 1,
2234
+ apply: function* (input, args, env, tracker, evaluate, span) {
2235
+ const filter = args[0];
2236
+ for (const res of evaluate(filter, input, env, tracker)) if (isTruthy(res)) {
2237
+ yield emit$1(input, span, tracker);
2238
+ return;
2239
+ }
2240
+ }
2241
+ },
2242
+ {
2243
+ name: "sort",
2244
+ arity: 0,
2245
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2246
+ if (!Array.isArray(input)) throw new RuntimeError("sort expects an array", span);
2247
+ const sorted = sortStable(input, (a, b) => compareValues(a, b));
2248
+ tracker.step(span);
2249
+ yield emit$1(sorted, span, tracker);
2250
+ }
2251
+ },
2252
+ {
2253
+ name: "sort_by",
2254
+ arity: 1,
2255
+ apply: function* (input, args, env, tracker, evaluate, span) {
2256
+ if (!Array.isArray(input)) throw new RuntimeError("sort_by expects an array", span);
2257
+ const filter = args[0];
2258
+ const pairs = [];
2259
+ for (const item of input) {
2260
+ tracker.step(span);
2261
+ const keys = Array.from(evaluate(filter, item, env, tracker));
2262
+ if (keys.length !== 1) throw new RuntimeError("sort_by key expression must return exactly one value", span);
2263
+ pairs.push({
2264
+ val: item,
2265
+ key: keys[0]
2266
+ });
2267
+ }
2268
+ yield emit$1(sortStable(pairs, (a, b) => compareValues(a.key, b.key)).map((p) => p.val), span, tracker);
2269
+ }
2270
+ },
2271
+ {
2272
+ name: "unique",
2273
+ arity: 0,
2274
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2275
+ if (!Array.isArray(input)) throw new RuntimeError("unique expects an array", span);
2276
+ const seen = [];
2277
+ const result = [];
2278
+ for (const item of input) {
2279
+ tracker.step(span);
2280
+ if (!seen.some((s) => valueEquals(s, item))) {
2281
+ seen.push(item);
2282
+ result.push(item);
2283
+ }
2284
+ }
2285
+ yield emit$1(result, span, tracker);
2286
+ }
2287
+ },
2288
+ {
2289
+ name: "unique_by",
2290
+ arity: 1,
2291
+ apply: function* (input, args, env, tracker, evaluate, span) {
2292
+ if (!Array.isArray(input)) throw new RuntimeError("unique_by expects an array", span);
2293
+ const filter = args[0];
2294
+ const seenKeys = [];
2295
+ const result = [];
2296
+ for (const item of input) {
2297
+ tracker.step(span);
2298
+ const keys = Array.from(evaluate(filter, item, env, tracker));
2299
+ if (keys.length !== 1) throw new RuntimeError("unique_by key expression must return exactly one value", span);
2300
+ const key = keys[0];
2301
+ if (!seenKeys.some((s) => valueEquals(s, key))) {
2302
+ seenKeys.push(key);
2303
+ result.push(item);
2304
+ }
2305
+ }
2306
+ yield emit$1(result, span, tracker);
2307
+ }
2308
+ },
2309
+ {
2310
+ name: "to_entries",
2311
+ arity: 0,
2312
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2313
+ if (Array.isArray(input)) yield emit$1(input.map((v, i) => ({
2314
+ key: i,
2315
+ value: v
2316
+ })), span, tracker);
2317
+ else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input).sort().map((k) => ({
2318
+ key: k,
2319
+ value: input[k]
2320
+ })), span, tracker);
2321
+ else throw new RuntimeError("to_entries expects array or object", span);
2322
+ }
2323
+ },
2324
+ {
2325
+ name: "from_entries",
2326
+ arity: 0,
2327
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2328
+ if (!Array.isArray(input)) throw new RuntimeError("from_entries expects an array", span);
2329
+ const result = {};
2330
+ for (const item of input) {
2331
+ tracker.step(span);
2332
+ if (item === null || typeof item !== "object" || Array.isArray(item)) throw new RuntimeError("from_entries expects array of objects", span);
2333
+ const obj = item;
2334
+ const key = getEntryField(obj, [
2335
+ "key",
2336
+ "Key",
2337
+ "name",
2338
+ "Name"
2339
+ ]);
2340
+ const value = getEntryField(obj, ["value", "Value"]);
2341
+ if (key === void 0 || value === void 0) throw new RuntimeError("from_entries items must have key/name and value fields", span);
2342
+ if (typeof key !== "string") throw new RuntimeError("from_entries object keys must be strings", span);
2343
+ result[key] = value;
2344
+ }
2345
+ yield emit$1(result, span, tracker);
2346
+ }
2347
+ },
2348
+ {
2349
+ name: "with_entries",
2350
+ arity: 1,
2351
+ apply: function* (input, args, env, tracker, evaluate, span) {
2352
+ let entries;
2353
+ if (Array.isArray(input)) entries = input.map((v, i) => ({
2354
+ key: i,
2355
+ value: v
2356
+ }));
2357
+ else if (input !== null && typeof input === "object") entries = Object.keys(input).sort().map((k) => ({
2358
+ key: k,
2359
+ value: input[k]
2360
+ }));
2361
+ else throw new RuntimeError("with_entries expects array or object", span);
2362
+ const transformed = [];
2363
+ const filter = args[0];
2364
+ for (const entry of entries) {
2365
+ tracker.step(span);
2366
+ for (const outVar of evaluate(filter, entry, env, tracker)) transformed.push(outVar);
2367
+ }
2368
+ const result = {};
2369
+ for (const item of transformed) {
2370
+ if (item === null || typeof item !== "object" || Array.isArray(item)) throw new RuntimeError("with_entries filter must produce objects", span);
2371
+ const obj = item;
2372
+ if (!("key" in obj) || !("value" in obj)) throw new RuntimeError("with_entries items must have \"key\" and \"value\"", span);
2373
+ const key = obj["key"];
2374
+ if (typeof key !== "string") throw new RuntimeError("with_entries keys must be strings", span);
2375
+ result[key] = obj["value"];
2376
+ }
2377
+ yield emit$1(result, span, tracker);
2378
+ }
2379
+ },
2380
+ {
2381
+ name: "group_by",
2382
+ arity: 1,
2383
+ apply: function* (input, args, env, tracker, evaluate, span) {
2384
+ if (!Array.isArray(input)) throw new RuntimeError("group_by expects an array", span);
2385
+ const pairs = [];
2386
+ const filter = args[0];
2387
+ for (const item of input) {
2388
+ tracker.step(span);
2389
+ const keys = Array.from(evaluate(filter, item, env, tracker));
2390
+ if (keys.length !== 1) throw new RuntimeError("group_by key expression must return exactly one value", span);
2391
+ pairs.push({
2392
+ val: item,
2393
+ key: keys[0]
2394
+ });
2395
+ }
2396
+ const sorted = sortStable(pairs, (a, b) => compareValues(a.key, b.key));
2397
+ const groups = [];
2398
+ if (sorted.length > 0) {
2399
+ let currentGroup = [sorted[0].val];
2400
+ let currentKey = sorted[0].key;
2401
+ for (let i = 1; i < sorted.length; i++) {
2402
+ const pair = sorted[i];
2403
+ if (compareValues(pair.key, currentKey) === 0) currentGroup.push(pair.val);
2404
+ else {
2405
+ groups.push(currentGroup);
2406
+ currentGroup = [pair.val];
2407
+ currentKey = pair.key;
2408
+ }
2409
+ }
2410
+ groups.push(currentGroup);
2411
+ }
2412
+ yield emit$1(groups, span, tracker);
2413
+ }
2414
+ },
2415
+ {
2416
+ name: "reverse",
2417
+ arity: 0,
2418
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2419
+ if (!Array.isArray(input)) throw new RuntimeError("reverse expects an array", span);
2420
+ yield emit$1([...input].reverse(), span, tracker);
2421
+ }
2422
+ },
2423
+ {
2424
+ name: "in",
2425
+ arity: 1,
2426
+ apply: function* (input, args, env, tracker, evaluate, span) {
2427
+ for (const container of evaluate(args[0], input, env, tracker)) {
2428
+ if (Array.isArray(container)) {
2429
+ if (typeof input !== "number") throw new RuntimeError(`Cannot check whether array has a ${typeof input} key`, span);
2430
+ const idx = ensureIndex(input);
2431
+ yield emit$1(idx !== void 0 && idx >= 0 && idx < container.length, span, tracker);
2432
+ continue;
2433
+ }
2434
+ if (container !== null && typeof container === "object") {
2435
+ if (typeof input !== "string") throw new RuntimeError(`Cannot check whether object has a ${typeof input} key`, span);
2436
+ yield emit$1(Object.prototype.hasOwnProperty.call(container, input), span, tracker);
2437
+ continue;
2438
+ }
2439
+ throw new RuntimeError("in expects an array or object argument", span);
2440
+ }
2441
+ }
2442
+ },
2443
+ {
2444
+ name: "del",
2445
+ arity: 1,
2446
+ apply: function* (input, args, env, tracker, evaluate, span) {
2447
+ yield emit$1(deletePaths(input, Array.from(evaluatePath(args[0], input, env, tracker, evaluate)), span), span, tracker);
2448
+ }
2449
+ },
2450
+ {
2451
+ name: "pick",
2452
+ arity: 1,
2453
+ apply: function* (input, args, env, tracker, evaluate, span) {
2454
+ const paths = Array.from(evaluatePath(args[0], input, env, tracker, evaluate));
2455
+ let result = null;
2456
+ for (const path of paths) {
2457
+ const value = getPath(input, path);
2458
+ result = updatePath(result, path, () => value ?? null, span) ?? null;
2459
+ }
2460
+ yield emit$1(result, span, tracker);
2461
+ }
2462
+ },
2463
+ {
2464
+ name: "flatten",
2465
+ arity: 0,
2466
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2467
+ if (!Array.isArray(input)) throw new RuntimeError("flatten expects an array", span);
2468
+ const flattenRec = (arr) => {
2469
+ let res = [];
2470
+ for (const item of arr) if (Array.isArray(item)) res = res.concat(flattenRec(item));
2471
+ else res.push(item);
2472
+ return res;
2473
+ };
2474
+ yield emit$1(flattenRec(input), span, tracker);
2475
+ }
2476
+ },
2477
+ {
2478
+ name: "flatten",
2479
+ arity: 1,
2480
+ apply: function* (input, args, env, tracker, evaluate, span) {
2481
+ if (!Array.isArray(input)) throw new RuntimeError("flatten expects an array", span);
2482
+ const depths = evaluate(args[0], input, env, tracker);
2483
+ for (const depthVal of depths) {
2484
+ if (typeof depthVal !== "number") throw new RuntimeError("flatten depth must be a number", span);
2485
+ const flattenDepth = (arr, d) => {
2486
+ if (d <= 0) return arr;
2487
+ let res = [];
2488
+ for (const item of arr) if (Array.isArray(item)) res = res.concat(flattenDepth(item, d - 1));
2489
+ else res.push(item);
2490
+ return res;
2491
+ };
2492
+ yield emit$1(flattenDepth(input, depthVal), span, tracker);
2493
+ }
2494
+ }
2495
+ },
2496
+ {
2497
+ name: "keys_unsorted",
2498
+ arity: 0,
2499
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2500
+ if (Array.isArray(input)) yield emit$1(Array.from({ length: input.length }, (_, i) => i), span, tracker);
2501
+ else if (input !== null && typeof input === "object") yield emit$1(Object.keys(input), span, tracker);
2502
+ else throw new RuntimeError(`keys_unsorted expects an array or object`, span);
2503
+ }
2504
+ },
2505
+ {
2506
+ name: "transpose",
2507
+ arity: 0,
2508
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2509
+ if (!Array.isArray(input)) throw new RuntimeError("transpose expects an array", span);
2510
+ const arr = input;
2511
+ if (arr.length === 0) {
2512
+ yield emit$1([], span, tracker);
2513
+ return;
2514
+ }
2515
+ let maxLen = 0;
2516
+ for (const row of arr) {
2517
+ if (!Array.isArray(row)) throw new RuntimeError("transpose input must be array of arrays", span);
2518
+ if (row.length > maxLen) maxLen = row.length;
2519
+ }
2520
+ const result = [];
2521
+ for (let j = 0; j < maxLen; j++) {
2522
+ const newRow = [];
2523
+ for (let i = 0; i < arr.length; i++) {
2524
+ const row = arr[i];
2525
+ const val = j < row.length ? row[j] : null;
2526
+ newRow.push(val);
2527
+ }
2528
+ result.push(newRow);
2529
+ }
2530
+ yield emit$1(result, span, tracker);
2531
+ }
2532
+ },
2533
+ {
2534
+ name: "bsearch",
2535
+ arity: 1,
2536
+ apply: function* (input, args, env, tracker, evaluate, span) {
2537
+ if (!Array.isArray(input)) throw new RuntimeError("bsearch expects an array", span);
2538
+ const targetGen = evaluate(args[0], input, env, tracker);
2539
+ for (const target of targetGen) {
2540
+ let low = 0;
2541
+ let high = input.length - 1;
2542
+ let idx = -1;
2543
+ while (low <= high) {
2544
+ const mid = Math.floor((low + high) / 2);
2545
+ const cmp = compareValues(input[mid], target);
2546
+ if (cmp === 0) {
2547
+ idx = mid;
2548
+ break;
2549
+ } else if (cmp < 0) low = mid + 1;
2550
+ else high = mid - 1;
2551
+ }
2552
+ if (idx !== -1) yield emit$1(idx, span, tracker);
2553
+ else yield emit$1(-low - 1, span, tracker);
2554
+ }
2555
+ }
2556
+ },
2557
+ {
2558
+ name: "combinations",
2559
+ arity: 0,
2560
+ apply: function* (input, _args, _env, tracker, _eval, span) {
2561
+ if (!Array.isArray(input)) throw new RuntimeError("combinations expects an array", span);
2562
+ if (input.some((x) => !Array.isArray(x))) throw new RuntimeError("combinations input must be array of arrays", span);
2563
+ const arrays = input;
2564
+ if (arrays.length === 0) {
2565
+ yield emit$1([], span, tracker);
2566
+ return;
2567
+ }
2568
+ const helper = function* (idx, current) {
2569
+ if (idx === arrays.length) {
2570
+ yield [...current];
2571
+ return;
2572
+ }
2573
+ const arr = arrays[idx];
2574
+ if (arr.length === 0) return;
2575
+ for (const item of arr) {
2576
+ current.push(item);
2577
+ yield* helper(idx + 1, current);
2578
+ current.pop();
2579
+ }
2580
+ };
2581
+ for (const combo of helper(0, [])) yield emit$1(combo, span, tracker);
2582
+ }
2583
+ },
2584
+ {
2585
+ name: "combinations",
2586
+ arity: 1,
2587
+ apply: function* (input, args, env, tracker, evaluate, span) {
2588
+ if (!Array.isArray(input)) throw new RuntimeError("combinations expects an array", span);
2589
+ const nGen = evaluate(args[0], input, env, tracker);
2590
+ for (const nVal of nGen) {
2591
+ if (typeof nVal !== "number") throw new RuntimeError("combinations(n) expects n to be number", span);
2592
+ if (nVal === 0) {
2593
+ yield emit$1([], span, tracker);
2594
+ continue;
2595
+ }
2596
+ const arrays = [];
2597
+ for (let i = 0; i < nVal; i++) arrays.push(input);
2598
+ const helper = function* (idx, current) {
2599
+ if (idx === arrays.length) {
2600
+ yield [...current];
2601
+ return;
2602
+ }
2603
+ const arr = arrays[idx];
2604
+ for (const item of arr) {
2605
+ current.push(item);
2606
+ yield* helper(idx + 1, current);
2607
+ current.pop();
2608
+ }
2609
+ };
2610
+ if (input.length === 0 && nVal > 0) {} else for (const combo of helper(0, [])) yield emit$1(combo, span, tracker);
2611
+ }
2612
+ }
2613
+ },
2614
+ {
2615
+ name: "inside",
2304
2616
  arity: 1,
2305
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2306
- for (const p of evaluatePath(args[0], input, env, tracker, evaluate$1)) yield emit$1(p, span, tracker);
2617
+ apply: function* (input, args, env, tracker, evaluate, span) {
2618
+ const bGen = evaluate(args[0], input, env, tracker);
2619
+ for (const b of bGen) yield emit$1(checkContains(b, input), span, tracker);
2307
2620
  }
2308
2621
  }
2309
2622
  ];
2310
-
2623
+ const getEntryField = (obj, names) => {
2624
+ for (const name of names) if (Object.prototype.hasOwnProperty.call(obj, name)) return obj[name];
2625
+ };
2311
2626
  //#endregion
2312
2627
  //#region src/builtins/iterators.ts
2313
2628
  const iteratorBuiltins = [
2314
2629
  {
2315
2630
  name: "range",
2316
2631
  arity: 1,
2317
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2318
- const ends = evaluate$1(args[0], input, env, tracker);
2632
+ apply: function* (input, args, env, tracker, evaluate, span) {
2633
+ const ends = evaluate(args[0], input, env, tracker);
2319
2634
  for (const end of ends) {
2320
2635
  if (typeof end !== "number") throw new RuntimeError("range expects numbers", span);
2321
2636
  for (let i = 0; i < end; i++) yield emit$1(i, span, tracker);
@@ -2325,9 +2640,9 @@ const iteratorBuiltins = [
2325
2640
  {
2326
2641
  name: "range",
2327
2642
  arity: 2,
2328
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2329
- const starts = Array.from(evaluate$1(args[0], input, env, tracker));
2330
- const ends = Array.from(evaluate$1(args[1], input, env, tracker));
2643
+ apply: function* (input, args, env, tracker, evaluate, span) {
2644
+ const starts = Array.from(evaluate(args[0], input, env, tracker));
2645
+ const ends = Array.from(evaluate(args[1], input, env, tracker));
2331
2646
  for (const start of starts) for (const end of ends) {
2332
2647
  if (typeof start !== "number" || typeof end !== "number") throw new RuntimeError("range expects numbers", span);
2333
2648
  if (start < end) for (let i = start; i < end; i++) yield emit$1(i, span, tracker);
@@ -2337,10 +2652,10 @@ const iteratorBuiltins = [
2337
2652
  {
2338
2653
  name: "range",
2339
2654
  arity: 3,
2340
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2341
- const starts = Array.from(evaluate$1(args[0], input, env, tracker));
2342
- const ends = Array.from(evaluate$1(args[1], input, env, tracker));
2343
- const steps = Array.from(evaluate$1(args[2], input, env, tracker));
2655
+ apply: function* (input, args, env, tracker, evaluate, span) {
2656
+ const starts = Array.from(evaluate(args[0], input, env, tracker));
2657
+ const ends = Array.from(evaluate(args[1], input, env, tracker));
2658
+ const steps = Array.from(evaluate(args[2], input, env, tracker));
2344
2659
  for (const start of starts) for (const end of ends) for (const step of steps) {
2345
2660
  if (typeof start !== "number" || typeof end !== "number" || typeof step !== "number") throw new RuntimeError("range expects numbers", span);
2346
2661
  if (step === 0) throw new RuntimeError("range step cannot be zero", span);
@@ -2352,12 +2667,12 @@ const iteratorBuiltins = [
2352
2667
  {
2353
2668
  name: "limit",
2354
2669
  arity: 2,
2355
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2356
- const limits = evaluate$1(args[0], input, env, tracker);
2670
+ apply: function* (input, args, env, tracker, evaluate, span) {
2671
+ const limits = evaluate(args[0], input, env, tracker);
2357
2672
  for (const n of limits) {
2358
2673
  if (typeof n !== "number") throw new RuntimeError("limit expects number", span);
2359
2674
  let count = 0;
2360
- if (n > 0) for (const val of evaluate$1(args[1], input, env, tracker)) {
2675
+ if (n > 0) for (const val of evaluate(args[1], input, env, tracker)) {
2361
2676
  yield val;
2362
2677
  count++;
2363
2678
  if (count >= n) break;
@@ -2365,38 +2680,78 @@ const iteratorBuiltins = [
2365
2680
  }
2366
2681
  }
2367
2682
  },
2683
+ {
2684
+ name: "skip",
2685
+ arity: 2,
2686
+ apply: function* (input, args, env, tracker, evaluate, span) {
2687
+ for (const n of evaluate(args[0], input, env, tracker)) {
2688
+ if (typeof n !== "number") throw new RuntimeError("skip expects number", span);
2689
+ let count = 0;
2690
+ for (const val of evaluate(args[1], input, env, tracker)) {
2691
+ if (count >= n) yield val;
2692
+ count++;
2693
+ }
2694
+ }
2695
+ }
2696
+ },
2697
+ {
2698
+ name: "first",
2699
+ arity: 0,
2700
+ apply: function* (input) {
2701
+ if (Array.isArray(input) && input.length > 0) yield input[0];
2702
+ }
2703
+ },
2368
2704
  {
2369
2705
  name: "first",
2370
2706
  arity: 1,
2371
- apply: function* (input, args, env, tracker, evaluate$1) {
2372
- for (const val of evaluate$1(args[0], input, env, tracker)) {
2707
+ apply: function* (input, args, env, tracker, evaluate) {
2708
+ for (const val of evaluate(args[0], input, env, tracker)) {
2373
2709
  yield val;
2374
2710
  break;
2375
2711
  }
2376
2712
  }
2377
2713
  },
2714
+ {
2715
+ name: "last",
2716
+ arity: 0,
2717
+ apply: function* (input) {
2718
+ if (Array.isArray(input) && input.length > 0) yield input[input.length - 1];
2719
+ }
2720
+ },
2378
2721
  {
2379
2722
  name: "last",
2380
2723
  arity: 1,
2381
- apply: function* (input, args, env, tracker, evaluate$1) {
2724
+ apply: function* (input, args, env, tracker, evaluate) {
2382
2725
  let lastVal;
2383
2726
  let found = false;
2384
- for (const val of evaluate$1(args[0], input, env, tracker)) {
2727
+ for (const val of evaluate(args[0], input, env, tracker)) {
2385
2728
  lastVal = val;
2386
2729
  found = true;
2387
2730
  }
2388
2731
  if (found) yield lastVal;
2389
2732
  }
2390
2733
  },
2734
+ {
2735
+ name: "nth",
2736
+ arity: 1,
2737
+ apply: function* (input, args, env, tracker, evaluate, span) {
2738
+ if (!Array.isArray(input)) throw new RuntimeError("nth expects array input", span);
2739
+ for (const n of evaluate(args[0], input, env, tracker)) {
2740
+ if (typeof n !== "number") throw new RuntimeError("nth expects number", span);
2741
+ const idx = Math.trunc(n);
2742
+ if (idx >= 0 && idx < input.length) yield input[idx];
2743
+ }
2744
+ }
2745
+ },
2391
2746
  {
2392
2747
  name: "nth",
2393
2748
  arity: 2,
2394
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2395
- const indices = evaluate$1(args[0], input, env, tracker);
2749
+ apply: function* (input, args, env, tracker, evaluate, span) {
2750
+ const indices = evaluate(args[0], input, env, tracker);
2396
2751
  for (const n of indices) {
2397
2752
  if (typeof n !== "number") throw new RuntimeError("nth expects number", span);
2398
2753
  let count = 0;
2399
- for (const val of evaluate$1(args[1], input, env, tracker)) {
2754
+ for (const val of evaluate(args[1], input, env, tracker)) {
2400
2755
  if (count === n) {
2401
2756
  yield val;
2402
2757
  break;
@@ -2409,67 +2764,161 @@ const iteratorBuiltins = [
2409
2764
  {
2410
2765
  name: "isempty",
2411
2766
  arity: 1,
2412
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2767
+ apply: function* (input, args, env, tracker, evaluate, span) {
2413
2768
  let empty = true;
2414
- for (const _ of evaluate$1(args[0], input, env, tracker)) {
2769
+ for (const _ of evaluate(args[0], input, env, tracker)) {
2415
2770
  empty = false;
2416
2771
  break;
2417
2772
  }
2418
2773
  yield emit$1(empty, span, tracker);
2419
2774
  }
2420
2775
  },
2776
+ {
2777
+ name: "all",
2778
+ arity: 0,
2779
+ apply: function* (input, _args, _env, tracker, _evaluate, span) {
2780
+ if (!Array.isArray(input)) throw new RuntimeError("all expects an array", span);
2781
+ yield emit$1(input.every(isTruthy), span, tracker);
2782
+ }
2783
+ },
2421
2784
  {
2422
2785
  name: "all",
2423
2786
  arity: 1,
2424
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2787
+ apply: function* (input, args, env, tracker, evaluate, span) {
2788
+ if (!Array.isArray(input)) throw new RuntimeError("all expects an array", span);
2425
2789
  let result = true;
2426
- for (const val of evaluate$1(args[0], input, env, tracker)) if (!isTruthy(val)) {
2427
- result = false;
2428
- break;
2790
+ for (const item of input) {
2791
+ let itemResult = false;
2792
+ for (const val of evaluate(args[0], item, env, tracker)) if (isTruthy(val)) {
2793
+ itemResult = true;
2794
+ break;
2795
+ }
2796
+ if (!itemResult) {
2797
+ result = false;
2798
+ break;
2799
+ }
2800
+ }
2801
+ yield emit$1(result, span, tracker);
2802
+ }
2803
+ },
2804
+ {
2805
+ name: "all",
2806
+ arity: 2,
2807
+ apply: function* (input, args, env, tracker, evaluate, span) {
2808
+ let result = true;
2809
+ for (const item of evaluate(args[0], input, env, tracker)) {
2810
+ let itemResult = false;
2811
+ for (const condition of evaluate(args[1], item, env, tracker)) if (isTruthy(condition)) {
2812
+ itemResult = true;
2813
+ break;
2814
+ }
2815
+ if (!itemResult) {
2816
+ result = false;
2817
+ break;
2818
+ }
2429
2819
  }
2430
2820
  yield emit$1(result, span, tracker);
2431
2821
  }
2432
2822
  },
2823
+ {
2824
+ name: "any",
2825
+ arity: 0,
2826
+ apply: function* (input, _args, _env, tracker, _evaluate, span) {
2827
+ if (!Array.isArray(input)) throw new RuntimeError("any expects an array", span);
2828
+ yield emit$1(input.some(isTruthy), span, tracker);
2829
+ }
2830
+ },
2433
2831
  {
2434
2832
  name: "any",
2435
2833
  arity: 1,
2436
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2834
+ apply: function* (input, args, env, tracker, evaluate, span) {
2835
+ if (!Array.isArray(input)) throw new RuntimeError("any expects an array", span);
2437
2836
  let result = false;
2438
- for (const val of evaluate$1(args[0], input, env, tracker)) if (isTruthy(val)) {
2439
- result = true;
2440
- break;
2837
+ for (const item of input) {
2838
+ for (const val of evaluate(args[0], item, env, tracker)) if (isTruthy(val)) {
2839
+ result = true;
2840
+ break;
2841
+ }
2842
+ if (result) break;
2843
+ }
2844
+ yield emit$1(result, span, tracker);
2845
+ }
2846
+ },
2847
+ {
2848
+ name: "any",
2849
+ arity: 2,
2850
+ apply: function* (input, args, env, tracker, evaluate, span) {
2851
+ let result = false;
2852
+ for (const item of evaluate(args[0], input, env, tracker)) {
2853
+ for (const condition of evaluate(args[1], item, env, tracker)) if (isTruthy(condition)) {
2854
+ result = true;
2855
+ break;
2856
+ }
2857
+ if (result) break;
2441
2858
  }
2442
2859
  yield emit$1(result, span, tracker);
2443
2860
  }
2444
2861
  },
2862
+ {
2863
+ name: "recurse",
2864
+ arity: 0,
2865
+ apply: function* (input, _args, _env, tracker, _evaluate, span) {
2866
+ const rec = function* (curr) {
2867
+ yield emit$1(curr, span, tracker);
2868
+ if (Array.isArray(curr)) for (const item of curr) yield* rec(item);
2869
+ else if (curr !== null && typeof curr === "object") {
2870
+ const keys = Object.keys(curr).sort();
2871
+ for (const key of keys) yield* rec(curr[key]);
2872
+ }
2873
+ };
2874
+ yield* rec(input);
2875
+ }
2876
+ },
2445
2877
  {
2446
2878
  name: "recurse",
2447
2879
  arity: 1,
2448
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2880
+ apply: function* (input, args, env, tracker, evaluate, span) {
2449
2881
  const rec = function* (curr) {
2450
2882
  yield emit$1(curr, span, tracker);
2451
- const nexts = evaluate$1(args[0], curr, env, tracker);
2883
+ const nexts = evaluate(args[0], curr, env, tracker);
2452
2884
  for (const next of nexts) yield* rec(next);
2453
2885
  };
2454
2886
  yield* rec(input);
2455
2887
  }
2456
2888
  },
2889
+ {
2890
+ name: "recurse",
2891
+ arity: 2,
2892
+ apply: function* (input, args, env, tracker, evaluate, span) {
2893
+ const stepExpr = args[0];
2894
+ const conditionExpr = args[1];
2895
+ const rec = function* (curr) {
2896
+ yield emit$1(curr, span, tracker);
2897
+ for (const condition of evaluate(conditionExpr, curr, env, tracker)) {
2898
+ if (!isTruthy(condition)) return;
2899
+ break;
2900
+ }
2901
+ for (const next of evaluate(stepExpr, curr, env, tracker)) yield* rec(next);
2902
+ };
2903
+ yield* rec(input);
2904
+ }
2905
+ },
2457
2906
  {
2458
2907
  name: "while",
2459
2908
  arity: 2,
2460
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2909
+ apply: function* (input, args, env, tracker, evaluate, span) {
2461
2910
  const condExpr = args[0];
2462
2911
  const updateExpr = args[1];
2463
2912
  const rec = function* (curr) {
2464
2913
  tracker.step(span);
2465
2914
  let condMatches = false;
2466
- for (const c of evaluate$1(condExpr, curr, env, tracker)) if (isTruthy(c)) {
2915
+ for (const c of evaluate(condExpr, curr, env, tracker)) if (isTruthy(c)) {
2467
2916
  condMatches = true;
2468
2917
  break;
2469
2918
  }
2470
2919
  if (condMatches) {
2471
2920
  yield emit$1(curr, span, tracker);
2472
- for (const next of evaluate$1(updateExpr, curr, env, tracker)) yield* rec(next);
2921
+ for (const next of evaluate(updateExpr, curr, env, tracker)) yield* rec(next);
2473
2922
  }
2474
2923
  };
2475
2924
  yield* rec(input);
@@ -2478,18 +2927,18 @@ const iteratorBuiltins = [
2478
2927
  {
2479
2928
  name: "until",
2480
2929
  arity: 2,
2481
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2930
+ apply: function* (input, args, env, tracker, evaluate, span) {
2482
2931
  const condExpr = args[0];
2483
2932
  const updateExpr = args[1];
2484
2933
  const rec = function* (curr) {
2485
2934
  tracker.step(span);
2486
2935
  let condMatches = false;
2487
- for (const c of evaluate$1(condExpr, curr, env, tracker)) if (isTruthy(c)) {
2936
+ for (const c of evaluate(condExpr, curr, env, tracker)) if (isTruthy(c)) {
2488
2937
  condMatches = true;
2489
2938
  break;
2490
2939
  }
2491
2940
  if (condMatches) yield emit$1(curr, span, tracker);
2492
- else for (const next of evaluate$1(updateExpr, curr, env, tracker)) yield* rec(next);
2941
+ else for (const next of evaluate(updateExpr, curr, env, tracker)) yield* rec(next);
2493
2942
  };
2494
2943
  yield* rec(input);
2495
2944
  }
@@ -2497,15 +2946,14 @@ const iteratorBuiltins = [
2497
2946
  {
2498
2947
  name: "repeat",
2499
2948
  arity: 1,
2500
- apply: function* (input, args, env, tracker, evaluate$1, span) {
2949
+ apply: function* (input, args, env, tracker, evaluate, span) {
2501
2950
  while (true) {
2502
2951
  tracker.step(span);
2503
- yield* evaluate$1(args[0], input, env, tracker);
2952
+ yield* evaluate(args[0], input, env, tracker);
2504
2953
  }
2505
2954
  }
2506
2955
  }
2507
2956
  ];
2508
-
2509
2957
  //#endregion
2510
2958
  //#region src/eval/ops.ts
2511
2959
  /**
@@ -2554,7 +3002,7 @@ function isEqual(a, b) {
2554
3002
  if (a.length !== b.length) return false;
2555
3003
  return a.every((v, i) => isEqual(v, b[i]));
2556
3004
  }
2557
- if (isPlainObject$1(a) && isPlainObject$1(b)) {
3005
+ if (isPlainObject(a) && isPlainObject(b)) {
2558
3006
  const ka = Object.keys(a).sort();
2559
3007
  const kb = Object.keys(b).sort();
2560
3008
  if (ka.length !== kb.length) return false;
@@ -2571,7 +3019,7 @@ function compare(a, b) {
2571
3019
  if (typeof v === "number") return 2;
2572
3020
  if (typeof v === "string") return 3;
2573
3021
  if (Array.isArray(v)) return 4;
2574
- if (isPlainObject$1(v)) return 5;
3022
+ if (isPlainObject(v)) return 5;
2575
3023
  return 6;
2576
3024
  };
2577
3025
  const ta = typeOrder(a);
@@ -2587,7 +3035,7 @@ function compare(a, b) {
2587
3035
  }
2588
3036
  return a.length - b.length;
2589
3037
  }
2590
- if (isPlainObject$1(a) && isPlainObject$1(b)) {
3038
+ if (isPlainObject(a) && isPlainObject(b)) {
2591
3039
  const keysA = Object.keys(a).sort();
2592
3040
  const keysB = Object.keys(b).sort();
2593
3041
  for (let i = 0; i < Math.min(keysA.length, keysB.length); i++) {
@@ -2607,7 +3055,7 @@ function add(left, right, span) {
2607
3055
  if (typeof left === "number" && typeof right === "number") return left + right;
2608
3056
  if (typeof left === "string" && typeof right === "string") return left + right;
2609
3057
  if (Array.isArray(left) && Array.isArray(right)) return [...left, ...right];
2610
- if (isPlainObject$1(left) && isPlainObject$1(right)) return {
3058
+ if (isPlainObject(left) && isPlainObject(right)) return {
2611
3059
  ...left,
2612
3060
  ...right
2613
3061
  };
@@ -2625,7 +3073,7 @@ function mul(left, right, span) {
2625
3073
  if (typeof left === "number" && typeof right === "number") return left * right;
2626
3074
  if (typeof left === "string" && typeof right === "number") return repeatString(left, right);
2627
3075
  if (typeof left === "number" && typeof right === "string") return repeatString(right, left);
2628
- if (isPlainObject$1(left) && isPlainObject$1(right)) return mergeDeep(left, right);
3076
+ if (isPlainObject(left) && isPlainObject(right)) return mergeDeep(left, right);
2629
3077
  throw new RuntimeError(`Cannot multiply ${describeType(left)} by ${describeType(right)}`, span);
2630
3078
  }
2631
3079
  function div(left, right, span) {
@@ -2654,15 +3102,14 @@ function mergeDeep(target, source) {
2654
3102
  for (const key of Object.keys(source)) {
2655
3103
  const sVal = source[key];
2656
3104
  const tVal = result[key];
2657
- if (isPlainObject$1(sVal) && tVal !== void 0 && isPlainObject$1(tVal)) result[key] = mergeDeep(tVal, sVal);
3105
+ if (isPlainObject(sVal) && tVal !== void 0 && isPlainObject(tVal)) result[key] = mergeDeep(tVal, sVal);
2658
3106
  else result[key] = sVal;
2659
3107
  }
2660
3108
  return result;
2661
3109
  }
2662
- function isPlainObject$1(v) {
3110
+ function isPlainObject(v) {
2663
3111
  return typeof v === "object" && v !== null && !Array.isArray(v);
2664
3112
  }
2665
-
2666
3113
  //#endregion
2667
3114
  //#region src/builtins/math.ts
2668
3115
  const mathBuiltins = [
@@ -2720,12 +3167,22 @@ const mathBuiltins = [
2720
3167
  {
2721
3168
  name: "infinite",
2722
3169
  arity: 0,
3170
+ apply: function* (_input, _args, _env, tracker, _eval, span) {
3171
+ yield emit$1(Infinity, span, tracker);
3172
+ }
3173
+ },
3174
+ {
3175
+ name: "nan",
3176
+ arity: 0,
3177
+ apply: function* (_input, _args, _env, tracker, _eval, span) {
3178
+ yield emit$1(NaN, span, tracker);
3179
+ }
3180
+ },
3181
+ {
3182
+ name: "isinfinite",
3183
+ arity: 0,
2723
3184
  apply: function* (input, _args, _env, tracker, _eval, span) {
2724
- if (typeof input !== "number") {
2725
- yield emit$1(false, span, tracker);
2726
- return;
2727
- }
2728
- yield emit$1(!Number.isFinite(input) && !Number.isNaN(input), span, tracker);
3185
+ yield emit$1(typeof input === "number" && !Number.isFinite(input) && !Number.isNaN(input), span, tracker);
2729
3186
  }
2730
3187
  },
2731
3188
  {
@@ -2754,6 +3211,13 @@ const mathBuiltins = [
2754
3211
  yield emit$1(true, span, tracker);
2755
3212
  }
2756
3213
  },
3214
+ {
3215
+ name: "isnormal",
3216
+ arity: 0,
3217
+ apply: function* (input, _args, _env, tracker, _eval, span) {
3218
+ yield emit$1(typeof input === "number" && Number.isFinite(input) && input !== 0, span, tracker);
3219
+ }
3220
+ },
2757
3221
  {
2758
3222
  name: "subnormal",
2759
3223
  arity: 0,
@@ -2796,7 +3260,7 @@ const mathBuiltins = [
2796
3260
  {
2797
3261
  name: "min_by",
2798
3262
  arity: 1,
2799
- apply: function* (input, args, env, tracker, evaluate$1, span) {
3263
+ apply: function* (input, args, env, tracker, evaluate, span) {
2800
3264
  if (!Array.isArray(input)) throw new RuntimeError("min_by expects an array", span);
2801
3265
  if (input.length === 0) {
2802
3266
  yield emit$1(null, span, tracker);
@@ -2804,12 +3268,12 @@ const mathBuiltins = [
2804
3268
  }
2805
3269
  let minItem = input[0];
2806
3270
  let minKey;
2807
- const keys0 = Array.from(evaluate$1(args[0], minItem, env, tracker));
3271
+ const keys0 = Array.from(evaluate(args[0], minItem, env, tracker));
2808
3272
  if (keys0.length !== 1) throw new RuntimeError("min_by key must return one value", span);
2809
3273
  minKey = keys0[0];
2810
3274
  for (let i = 1; i < input.length; i++) {
2811
3275
  const item = input[i];
2812
- const keys = Array.from(evaluate$1(args[0], item, env, tracker));
3276
+ const keys = Array.from(evaluate(args[0], item, env, tracker));
2813
3277
  if (keys.length !== 1) throw new RuntimeError("min_by key must return one value", span);
2814
3278
  const key = keys[0];
2815
3279
  if (compareValues(key, minKey) < 0) {
@@ -2823,7 +3287,7 @@ const mathBuiltins = [
2823
3287
  {
2824
3288
  name: "max_by",
2825
3289
  arity: 1,
2826
- apply: function* (input, args, env, tracker, evaluate$1, span) {
3290
+ apply: function* (input, args, env, tracker, evaluate, span) {
2827
3291
  if (!Array.isArray(input)) throw new RuntimeError("max_by expects an array", span);
2828
3292
  if (input.length === 0) {
2829
3293
  yield emit$1(null, span, tracker);
@@ -2831,12 +3295,12 @@ const mathBuiltins = [
2831
3295
  }
2832
3296
  let maxItem = input[0];
2833
3297
  let maxKey;
2834
- const keys0 = Array.from(evaluate$1(args[0], maxItem, env, tracker));
3298
+ const keys0 = Array.from(evaluate(args[0], maxItem, env, tracker));
2835
3299
  if (keys0.length !== 1) throw new RuntimeError("max_by key must return one value", span);
2836
3300
  maxKey = keys0[0];
2837
3301
  for (let i = 1; i < input.length; i++) {
2838
3302
  const item = input[i];
2839
- const keys = Array.from(evaluate$1(args[0], item, env, tracker));
3303
+ const keys = Array.from(evaluate(args[0], item, env, tracker));
2840
3304
  if (keys.length !== 1) throw new RuntimeError("max_by key must return one value", span);
2841
3305
  const key = keys[0];
2842
3306
  if (compareValues(key, maxKey) > 0) {
@@ -2863,9 +3327,25 @@ const mathBuiltins = [
2863
3327
  }
2864
3328
  yield emit$1(acc, span, tracker);
2865
3329
  }
3330
+ },
3331
+ {
3332
+ name: "add",
3333
+ arity: 1,
3334
+ apply: function* (input, args, env, tracker, evaluate, span) {
3335
+ const values = Array.from(evaluate(args[0], input, env, tracker));
3336
+ if (values.length === 0) {
3337
+ yield emit$1(null, span, tracker);
3338
+ return;
3339
+ }
3340
+ let acc = values[0];
3341
+ for (let i = 1; i < values.length; i++) {
3342
+ tracker.step(span);
3343
+ acc = add(acc, values[i], span);
3344
+ }
3345
+ yield emit$1(acc, span, tracker);
3346
+ }
2866
3347
  }
2867
3348
  ];
2868
-
2869
3349
  //#endregion
2870
3350
  //#region src/builtins/index.ts
2871
3351
  const registerAllBuiltins = () => {
@@ -2877,11 +3357,9 @@ const registerAllBuiltins = () => {
2877
3357
  registerBuiltins(iteratorBuiltins);
2878
3358
  registerBuiltins(mathBuiltins);
2879
3359
  };
2880
-
2881
3360
  //#endregion
2882
3361
  //#region src/builtins.ts
2883
3362
  registerAllBuiltins();
2884
-
2885
3363
  //#endregion
2886
3364
  //#region src/validate.ts
2887
3365
  /**
@@ -2892,57 +3370,57 @@ registerAllBuiltins();
2892
3370
  * @throws {ValidationError} If validation fails.
2893
3371
  */
2894
3372
  const validate = (node) => {
2895
- visit(node, []);
3373
+ visit$1(node, []);
2896
3374
  };
2897
- const visit = (node, scope) => {
3375
+ const visit$1 = (node, scope) => {
2898
3376
  switch (node.kind) {
2899
3377
  case "Identity":
2900
3378
  case "Literal":
2901
3379
  case "Var": return;
2902
3380
  case "FieldAccess":
2903
- visit(node.target, scope);
3381
+ visit$1(node.target, scope);
2904
3382
  return;
2905
3383
  case "IndexAccess":
2906
- visit(node.target, scope);
2907
- visit(node.index, scope);
3384
+ visit$1(node.target, scope);
3385
+ visit$1(node.index, scope);
2908
3386
  return;
2909
3387
  case "Array":
2910
- node.items.forEach((n) => visit(n, scope));
3388
+ node.items.forEach((n) => visit$1(n, scope));
2911
3389
  return;
2912
3390
  case "Object":
2913
3391
  node.entries.forEach((entry) => {
2914
- if (entry.key.kind === "KeyExpr") visit(entry.key.expr, scope);
2915
- visit(entry.value, scope);
3392
+ if (entry.key.kind === "KeyExpr") visit$1(entry.key.expr, scope);
3393
+ visit$1(entry.value, scope);
2916
3394
  });
2917
3395
  return;
2918
3396
  case "Pipe":
2919
3397
  case "Comma":
2920
3398
  case "Alt":
2921
- visit(node.left, scope);
2922
- visit(node.right, scope);
3399
+ visit$1(node.left, scope);
3400
+ visit$1(node.right, scope);
2923
3401
  return;
2924
3402
  case "Binary":
2925
3403
  case "Bool":
2926
- visit(node.left, scope);
2927
- visit(node.right, scope);
3404
+ visit$1(node.left, scope);
3405
+ visit$1(node.right, scope);
2928
3406
  return;
2929
3407
  case "Unary":
2930
- visit(node.expr, scope);
3408
+ visit$1(node.expr, scope);
2931
3409
  return;
2932
3410
  case "If":
2933
3411
  node.branches.forEach((branch) => {
2934
- visit(branch.cond, scope);
2935
- visit(branch.then, scope);
3412
+ visit$1(branch.cond, scope);
3413
+ visit$1(branch.then, scope);
2936
3414
  });
2937
- visit(node.else, scope);
3415
+ visit$1(node.else, scope);
2938
3416
  return;
2939
3417
  case "As":
2940
- visit(node.bind, scope);
2941
- visit(node.body, scope);
3418
+ visit$1(node.bind, scope);
3419
+ visit$1(node.body, scope);
2942
3420
  return;
2943
3421
  case "Call": {
2944
3422
  for (let i = scope.length - 1; i >= 0; i--) if (scope[i].has(node.name)) {
2945
- for (const arg of node.args) visit(arg, scope);
3423
+ for (const arg of node.args) visit$1(arg, scope);
2946
3424
  return;
2947
3425
  }
2948
3426
  const specs = builtins[node.name];
@@ -2951,51 +3429,50 @@ const visit = (node, scope) => {
2951
3429
  const arities = specs.map((s) => s.arity).join(" or ");
2952
3430
  throw new ValidationError(`Function ${node.name} expects ${arities} arguments, but got ${node.args.length}`, node.span);
2953
3431
  }
2954
- for (const arg of node.args) visit(arg, scope);
3432
+ for (const arg of node.args) visit$1(arg, scope);
2955
3433
  return;
2956
3434
  }
2957
3435
  case "Assignment":
2958
- visit(node.left, scope);
2959
- visit(node.right, scope);
3436
+ visit$1(node.left, scope);
3437
+ visit$1(node.right, scope);
2960
3438
  return;
2961
3439
  case "Def": {
2962
3440
  const bodyScope = new Set(node.args);
2963
3441
  bodyScope.add(node.name);
2964
- visit(node.body, [...scope, bodyScope]);
3442
+ visit$1(node.body, [...scope, bodyScope]);
2965
3443
  const nextScope = new Set([node.name]);
2966
- visit(node.next, [...scope, nextScope]);
3444
+ visit$1(node.next, [...scope, nextScope]);
2967
3445
  return;
2968
3446
  }
2969
3447
  case "Reduce":
2970
- visit(node.source, scope);
2971
- visit(node.init, scope);
2972
- visit(node.update, scope);
3448
+ visit$1(node.source, scope);
3449
+ visit$1(node.init, scope);
3450
+ visit$1(node.update, scope);
2973
3451
  return;
2974
3452
  case "Foreach":
2975
- visit(node.source, scope);
2976
- visit(node.init, scope);
2977
- visit(node.update, scope);
2978
- if (node.extract) visit(node.extract, scope);
3453
+ visit$1(node.source, scope);
3454
+ visit$1(node.init, scope);
3455
+ visit$1(node.update, scope);
3456
+ if (node.extract) visit$1(node.extract, scope);
2979
3457
  return;
2980
3458
  case "Try":
2981
- visit(node.body, scope);
2982
- if (node.handler) visit(node.handler, scope);
3459
+ visit$1(node.body, scope);
3460
+ if (node.handler) visit$1(node.handler, scope);
2983
3461
  return;
2984
3462
  case "Recurse":
2985
3463
  case "Iterate":
2986
3464
  case "Break": return;
2987
3465
  case "Label":
2988
- visit(node.body, scope);
3466
+ visit$1(node.body, scope);
2989
3467
  return;
2990
3468
  case "Slice":
2991
- visit(node.target, scope);
2992
- if (node.start) visit(node.start, scope);
2993
- if (node.end) visit(node.end, scope);
3469
+ visit$1(node.target, scope);
3470
+ if (node.start) visit$1(node.start, scope);
3471
+ if (node.end) visit$1(node.end, scope);
2994
3472
  return;
2995
3473
  default: return node;
2996
3474
  }
2997
3475
  };
2998
-
2999
3476
  //#endregion
3000
3477
  //#region src/eval/break.ts
3001
3478
  /**
@@ -3009,7 +3486,6 @@ var BreakSignal = class BreakSignal extends Error {
3009
3486
  Object.setPrototypeOf(this, BreakSignal.prototype);
3010
3487
  }
3011
3488
  };
3012
-
3013
3489
  //#endregion
3014
3490
  //#region src/limits.ts
3015
3491
  const DEFAULT_LIMITS = {
@@ -3070,7 +3546,6 @@ var LimitTracker = class {
3070
3546
  if (this.outputs > this.limits.maxOutputs) throw new RuntimeError("Output limit exceeded", span);
3071
3547
  }
3072
3548
  };
3073
-
3074
3549
  //#endregion
3075
3550
  //#region src/eval/env.ts
3076
3551
  /**
@@ -3080,7 +3555,26 @@ var LimitTracker = class {
3080
3555
  const getVar = (env, name) => {
3081
3556
  for (let i = env.length - 1; i >= 0; i--) if (env[i].vars.has(name)) return env[i].vars.get(name);
3082
3557
  };
3083
-
3558
+ /**
3559
+ * Binds jq `as` destructuring patterns into a variable map.
3560
+ */
3561
+ const bindPattern = (pattern, value, bindings) => {
3562
+ switch (pattern.kind) {
3563
+ case "VariablePattern":
3564
+ bindings.set(pattern.name, value);
3565
+ return;
3566
+ case "ArrayPattern":
3567
+ if (!Array.isArray(value)) throw new RuntimeError(`Cannot index ${describeType(value)} with number`, pattern.span);
3568
+ pattern.items.forEach((item, index) => {
3569
+ bindPattern(item, index < value.length ? value[index] : null, bindings);
3570
+ });
3571
+ return;
3572
+ case "ObjectPattern":
3573
+ if (!isPlainObject$1(value)) throw new RuntimeError(`Cannot index ${describeType(value)} with string`, pattern.span);
3574
+ for (const entry of pattern.entries) bindPattern(entry.pattern, Object.prototype.hasOwnProperty.call(value, entry.key) ? value[entry.key] : null, bindings);
3575
+ return;
3576
+ }
3577
+ };
3084
3578
  //#endregion
3085
3579
  //#region src/eval/common.ts
3086
3580
  /**
@@ -3112,7 +3606,6 @@ const toIndex = (value, span) => {
3112
3606
  }
3113
3607
  throw new RuntimeError("Expected numeric index", span);
3114
3608
  };
3115
-
3116
3609
  //#endregion
3117
3610
  //#region src/eval/assignment.ts
3118
3611
  /**
@@ -3128,15 +3621,15 @@ const toIndex = (value, span) => {
3128
3621
  * @param tracker - Limits tracker.
3129
3622
  * @param evaluate - Recursive evaluator.
3130
3623
  */
3131
- const evalAssignment = function* (node, input, env, tracker, evaluate$1) {
3132
- const paths = Array.from(evaluatePath(node.left, input, env, tracker, evaluate$1));
3624
+ const evalAssignment = function* (node, input, env, tracker, evaluate) {
3625
+ const paths = Array.from(evaluatePath(node.left, input, env, tracker, evaluate));
3133
3626
  paths.sort((a, b) => compareValues(a, b) * -1);
3134
3627
  if (paths.length === 0) {
3135
3628
  yield emit(input, node.span, tracker);
3136
3629
  return;
3137
3630
  }
3138
3631
  if (node.op === "=") {
3139
- const rhsValues = Array.from(evaluate$1(node.right, input, env, tracker));
3632
+ const rhsValues = Array.from(evaluate(node.right, input, env, tracker));
3140
3633
  if (rhsValues.length === 0) return;
3141
3634
  for (const rhsVal of rhsValues) {
3142
3635
  let current = input;
@@ -3145,9 +3638,9 @@ const evalAssignment = function* (node, input, env, tracker, evaluate$1) {
3145
3638
  }
3146
3639
  return;
3147
3640
  }
3148
- yield* applyUpdates(input, paths, 0, node.op, node.right, input, env, tracker, evaluate$1);
3641
+ yield* applyUpdates(input, paths, 0, node.op, node.right, input, env, tracker, evaluate);
3149
3642
  };
3150
- function* applyUpdates(current, paths, index, op, rhsNode, contextInput, env, tracker, evaluate$1) {
3643
+ function* applyUpdates(current, paths, index, op, rhsNode, contextInput, env, tracker, evaluate) {
3151
3644
  if (index >= paths.length) {
3152
3645
  yield current;
3153
3646
  return;
@@ -3155,9 +3648,9 @@ function* applyUpdates(current, paths, index, op, rhsNode, contextInput, env, tr
3155
3648
  const path = paths[index];
3156
3649
  const oldValue = getPath(current, path) ?? null;
3157
3650
  let newValues = [];
3158
- if (op === "|=") newValues = Array.from(evaluate$1(rhsNode, oldValue, env, tracker));
3651
+ if (op === "|=") newValues = Array.from(evaluate(rhsNode, oldValue, env, tracker));
3159
3652
  else {
3160
- const rhsResults = Array.from(evaluate$1(rhsNode, contextInput, env, tracker));
3653
+ const rhsResults = Array.from(evaluate(rhsNode, contextInput, env, tracker));
3161
3654
  for (const rhs of rhsResults) {
3162
3655
  let res;
3163
3656
  switch (op) {
@@ -3185,12 +3678,11 @@ function* applyUpdates(current, paths, index, op, rhsNode, contextInput, env, tr
3185
3678
  }
3186
3679
  }
3187
3680
  if (newValues.length === 0) {
3188
- yield* applyUpdates(deletePaths(current, [path], rhsNode.span), paths, index + 1, op, rhsNode, contextInput, env, tracker, evaluate$1);
3681
+ yield* applyUpdates(deletePaths(current, [path], rhsNode.span), paths, index + 1, op, rhsNode, contextInput, env, tracker, evaluate);
3189
3682
  return;
3190
3683
  }
3191
- for (const val of newValues) yield* applyUpdates(updatePath(current, path, () => val, rhsNode.span) ?? current, paths, index + 1, op, rhsNode, contextInput, env, tracker, evaluate$1);
3684
+ for (const val of newValues) yield* applyUpdates(updatePath(current, path, () => val, rhsNode.span) ?? current, paths, index + 1, op, rhsNode, contextInput, env, tracker, evaluate);
3192
3685
  }
3193
-
3194
3686
  //#endregion
3195
3687
  //#region src/eval/iterators.ts
3196
3688
  /**
@@ -3202,14 +3694,14 @@ function* applyUpdates(current, paths, index, op, rhsNode, contextInput, env, tr
3202
3694
  * @param tracker - Limits tracker.
3203
3695
  * @param evaluate - Recursive evaluator.
3204
3696
  */
3205
- const evalIterate = function* (node, input, env, tracker, evaluate$1) {
3206
- for (const container of evaluate$1(node.target, input, env, tracker)) {
3697
+ const evalIterate = function* (node, input, env, tracker, evaluate) {
3698
+ for (const container of evaluate(node.target, input, env, tracker)) {
3207
3699
  if (container === null) continue;
3208
3700
  if (isValueArray(container)) {
3209
3701
  for (const item of container) yield emit(item, node.span, tracker);
3210
3702
  continue;
3211
3703
  }
3212
- if (isPlainObject(container)) {
3704
+ if (isPlainObject$1(container)) {
3213
3705
  const keys = Object.keys(container).sort();
3214
3706
  for (const key of keys) yield emit(container[key], node.span, tracker);
3215
3707
  continue;
@@ -3228,18 +3720,20 @@ const evalIterate = function* (node, input, env, tracker, evaluate$1) {
3228
3720
  * @param tracker - Limits tracker.
3229
3721
  * @param evaluate - Recursive evaluator.
3230
3722
  */
3231
- const evalReduce = function* (node, input, env, tracker, evaluate$1) {
3232
- const initValues = Array.from(evaluate$1(node.init, input, env, tracker));
3723
+ const evalReduce = function* (node, input, env, tracker, evaluate) {
3724
+ const initValues = Array.from(evaluate(node.init, input, env, tracker));
3233
3725
  if (initValues.length !== 1) throw new RuntimeError("Reduce init must single value", node.init.span);
3234
3726
  let acc = initValues[0];
3235
- for (const item of evaluate$1(node.source, input, env, tracker)) {
3727
+ for (const item of evaluate(node.source, input, env, tracker)) {
3236
3728
  tracker.step(node.span);
3729
+ const vars = /* @__PURE__ */ new Map();
3730
+ bindPattern(node.pattern, item, vars);
3237
3731
  const newFrame = {
3238
- vars: new Map([[node.var, item]]),
3732
+ vars,
3239
3733
  funcs: /* @__PURE__ */ new Map()
3240
3734
  };
3241
3735
  const newEnv = [...env, newFrame];
3242
- const updates = Array.from(evaluate$1(node.update, acc, newEnv, tracker));
3736
+ const updates = Array.from(evaluate(node.update, acc, newEnv, tracker));
3243
3737
  if (updates.length !== 1) throw new RuntimeError("Reduce update must produce single value", node.update.span);
3244
3738
  acc = updates[0];
3245
3739
  }
@@ -3256,21 +3750,23 @@ const evalReduce = function* (node, input, env, tracker, evaluate$1) {
3256
3750
  * @param tracker - Limits tracker.
3257
3751
  * @param evaluate - Recursive evaluator.
3258
3752
  */
3259
- const evalForeach = function* (node, input, env, tracker, evaluate$1) {
3260
- const initValues = Array.from(evaluate$1(node.init, input, env, tracker));
3753
+ const evalForeach = function* (node, input, env, tracker, evaluate) {
3754
+ const initValues = Array.from(evaluate(node.init, input, env, tracker));
3261
3755
  if (initValues.length !== 1) throw new RuntimeError("Foreach init must single value", node.init.span);
3262
3756
  let acc = initValues[0];
3263
- for (const item of evaluate$1(node.source, input, env, tracker)) {
3757
+ for (const item of evaluate(node.source, input, env, tracker)) {
3264
3758
  tracker.step(node.span);
3759
+ const vars = /* @__PURE__ */ new Map();
3760
+ bindPattern(node.pattern, item, vars);
3265
3761
  const newFrame = {
3266
- vars: new Map([[node.var, item]]),
3762
+ vars,
3267
3763
  funcs: /* @__PURE__ */ new Map()
3268
3764
  };
3269
3765
  const newEnv = [...env, newFrame];
3270
- const updates = Array.from(evaluate$1(node.update, acc, newEnv, tracker));
3766
+ const updates = Array.from(evaluate(node.update, acc, newEnv, tracker));
3271
3767
  if (updates.length !== 1) throw new RuntimeError("Foreach update must produce single value", node.update.span);
3272
3768
  acc = updates[0];
3273
- if (node.extract) for (const extracted of evaluate$1(node.extract, acc, newEnv, tracker)) yield emit(extracted, node.span, tracker);
3769
+ if (node.extract) for (const extracted of evaluate(node.extract, acc, newEnv, tracker)) yield emit(extracted, node.span, tracker);
3274
3770
  else yield emit(acc, node.span, tracker);
3275
3771
  }
3276
3772
  };
@@ -3284,17 +3780,16 @@ const evalForeach = function* (node, input, env, tracker, evaluate$1) {
3284
3780
  * @param tracker - Limits tracker.
3285
3781
  * @param evaluate - Recursive evaluator.
3286
3782
  */
3287
- const evalRecurse = function* (node, input, env, tracker, evaluate$1) {
3783
+ const evalRecurse = function* (node, input, env, tracker, evaluate) {
3288
3784
  yield emit(input, node.span, tracker);
3289
3785
  const children = [];
3290
3786
  if (isValueArray(input)) children.push(...input);
3291
- else if (isPlainObject(input)) {
3787
+ else if (isPlainObject$1(input)) {
3292
3788
  const keys = Object.keys(input).sort();
3293
3789
  for (const key of keys) children.push(input[key]);
3294
3790
  }
3295
- for (const child of children) yield* evalRecurse(node, child, env, tracker, evaluate$1);
3791
+ for (const child of children) yield* evalRecurse(node, child, env, tracker, evaluate);
3296
3792
  };
3297
-
3298
3793
  //#endregion
3299
3794
  //#region src/eval/access.ts
3300
3795
  /**
@@ -3306,13 +3801,13 @@ const evalRecurse = function* (node, input, env, tracker, evaluate$1) {
3306
3801
  * @param tracker - Limits tracker.
3307
3802
  * @param evaluate - Recursive evaluator.
3308
3803
  */
3309
- const evalField = function* (node, input, env, tracker, evaluate$1) {
3310
- for (const container of evaluate$1(node.target, input, env, tracker)) {
3804
+ const evalField = function* (node, input, env, tracker, evaluate) {
3805
+ for (const container of evaluate(node.target, input, env, tracker)) {
3311
3806
  if (container === null) {
3312
3807
  yield emit(null, node.span, tracker);
3313
3808
  continue;
3314
3809
  }
3315
- if (isPlainObject(container)) {
3810
+ if (isPlainObject$1(container)) {
3316
3811
  yield emit(Object.prototype.hasOwnProperty.call(container, node.field) ? container[node.field] : null, node.span, tracker);
3317
3812
  continue;
3318
3813
  }
@@ -3329,9 +3824,9 @@ const evalField = function* (node, input, env, tracker, evaluate$1) {
3329
3824
  * @param tracker - Limits tracker.
3330
3825
  * @param evaluate - Recursive evaluator.
3331
3826
  */
3332
- const evalIndex = function* (node, input, env, tracker, evaluate$1) {
3333
- const indexValues = Array.from(evaluate$1(node.index, input, env, tracker));
3334
- for (const container of evaluate$1(node.target, input, env, tracker)) {
3827
+ const evalIndex = function* (node, input, env, tracker, evaluate) {
3828
+ const indexValues = Array.from(evaluate(node.index, input, env, tracker));
3829
+ for (const container of evaluate(node.target, input, env, tracker)) {
3335
3830
  if (container === null) {
3336
3831
  yield emit(null, node.span, tracker);
3337
3832
  continue;
@@ -3349,7 +3844,7 @@ const evalIndex = function* (node, input, env, tracker, evaluate$1) {
3349
3844
  }
3350
3845
  continue;
3351
3846
  }
3352
- if (isPlainObject(container)) {
3847
+ if (isPlainObject$1(container)) {
3353
3848
  for (const keyValue of indexValues) {
3354
3849
  if (typeof keyValue !== "string") throw new RuntimeError(`Cannot index object with ${describeType(keyValue)}`, node.span);
3355
3850
  yield emit(Object.prototype.hasOwnProperty.call(container, keyValue) ? container[keyValue] : null, node.span, tracker);
@@ -3369,25 +3864,26 @@ const evalIndex = function* (node, input, env, tracker, evaluate$1) {
3369
3864
  * @param tracker - Limits tracker.
3370
3865
  * @param evaluate - Recursive evaluator.
3371
3866
  */
3372
- const evalSlice = function* (node, input, env, tracker, evaluate$1) {
3373
- for (const target of evaluate$1(node.target, input, env, tracker)) {
3867
+ const evalSlice = function* (node, input, env, tracker, evaluate) {
3868
+ for (const target of evaluate(node.target, input, env, tracker)) {
3374
3869
  if (typeof target !== "string" && !Array.isArray(target)) throw new RuntimeError("Slice expected string or array", node.span);
3375
3870
  const starts = [];
3376
- if (node.start) for (const s of evaluate$1(node.start, input, env, tracker)) {
3871
+ if (node.start) for (const s of evaluate(node.start, input, env, tracker)) {
3377
3872
  if (typeof s !== "number") throw new RuntimeError("Slice start must be number", node.span);
3378
3873
  starts.push(s);
3379
3874
  }
3380
3875
  else starts.push(0);
3381
3876
  const ends = [];
3382
- if (node.end) for (const e of evaluate$1(node.end, input, env, tracker)) {
3877
+ if (node.end) for (const e of evaluate(node.end, input, env, tracker)) {
3383
3878
  if (typeof e !== "number") throw new RuntimeError("Slice end must be number", node.span);
3384
3879
  ends.push(e);
3385
3880
  }
3386
3881
  else ends.push(target.length);
3387
- for (const s of starts) for (const e of ends) yield emit(target.slice(s, e), node.span, tracker);
3882
+ for (const s of starts) for (const e of ends) yield emit(target.slice(normalizeSliceStart(s), normalizeSliceEnd(e)), node.span, tracker);
3388
3883
  }
3389
3884
  };
3390
-
3885
+ const normalizeSliceStart = (value) => Math.floor(value);
3886
+ const normalizeSliceEnd = (value) => Math.ceil(value);
3391
3887
  //#endregion
3392
3888
  //#region src/eval/constructors.ts
3393
3889
  /**
@@ -3402,9 +3898,9 @@ const evalSlice = function* (node, input, env, tracker, evaluate$1) {
3402
3898
  * @param tracker - Limits tracker.
3403
3899
  * @param evaluate - Recursive evaluator.
3404
3900
  */
3405
- const buildArray = function* (node, input, env, tracker, evaluate$1) {
3901
+ const buildArray = function* (node, input, env, tracker, evaluate) {
3406
3902
  const result = [];
3407
- for (const itemNode of node.items) for (const itemVal of evaluate$1(itemNode, input, env, tracker)) result.push(itemVal);
3903
+ for (const itemNode of node.items) for (const itemVal of evaluate(itemNode, input, env, tracker)) result.push(itemVal);
3408
3904
  yield result;
3409
3905
  };
3410
3906
  /**
@@ -3419,10 +3915,10 @@ const buildArray = function* (node, input, env, tracker, evaluate$1) {
3419
3915
  * @param tracker - Limits tracker.
3420
3916
  * @param evaluate - Recursive evaluator.
3421
3917
  */
3422
- const buildObjects = function* (node, input, env, tracker, evaluate$1) {
3423
- yield* fillObject(node.entries, 0, {}, input, env, tracker, evaluate$1);
3918
+ const buildObjects = function* (node, input, env, tracker, evaluate) {
3919
+ yield* fillObject(node.entries, 0, {}, input, env, tracker, evaluate);
3424
3920
  };
3425
- function* fillObject(entries, index, current, input, env, tracker, evaluate$1) {
3921
+ function* fillObject(entries, index, current, input, env, tracker, evaluate) {
3426
3922
  if (index >= entries.length) {
3427
3923
  yield { ...current };
3428
3924
  return;
@@ -3431,17 +3927,16 @@ function* fillObject(entries, index, current, input, env, tracker, evaluate$1) {
3431
3927
  let keys = [];
3432
3928
  if (entry.key.kind === "KeyIdentifier") keys = [entry.key.name];
3433
3929
  else if (entry.key.kind === "KeyString") keys = [entry.key.value];
3434
- else for (const k of evaluate$1(entry.key.expr, input, env, tracker)) {
3930
+ else for (const k of evaluate(entry.key.expr, input, env, tracker)) {
3435
3931
  if (typeof k !== "string") throw new RuntimeError("Object key must be a string", entry.key.span);
3436
3932
  keys.push(k);
3437
3933
  }
3438
- for (const key of keys) for (const val of evaluate$1(entry.value, input, env, tracker)) {
3934
+ for (const key of keys) for (const val of evaluate(entry.value, input, env, tracker)) {
3439
3935
  current[key] = val;
3440
- yield* fillObject(entries, index + 1, current, input, env, tracker, evaluate$1);
3936
+ yield* fillObject(entries, index + 1, current, input, env, tracker, evaluate);
3441
3937
  delete current[key];
3442
3938
  }
3443
3939
  }
3444
-
3445
3940
  //#endregion
3446
3941
  //#region src/eval/functions.ts
3447
3942
  /**
@@ -3459,7 +3954,7 @@ function* fillObject(entries, index, current, input, env, tracker, evaluate$1) {
3459
3954
  * @param tracker - Limits tracker.
3460
3955
  * @param evaluate - Recursive evaluator.
3461
3956
  */
3462
- const evalCall = function* (node, input, env, tracker, evaluate$1) {
3957
+ const evalCall = function* (node, input, env, tracker, evaluate) {
3463
3958
  for (let i = env.length - 1; i >= 0; i--) {
3464
3959
  const funcs = env[i].funcs.get(node.name);
3465
3960
  if (funcs) {
@@ -3481,7 +3976,7 @@ const evalCall = function* (node, input, env, tracker, evaluate$1) {
3481
3976
  newFrame.funcs.set(argName, argDefs);
3482
3977
  }
3483
3978
  const newStack = [...def.closure, newFrame];
3484
- yield* evaluate$1(def.body, input, newStack, tracker);
3979
+ yield* evaluate(def.body, input, newStack, tracker);
3485
3980
  return;
3486
3981
  }
3487
3982
  }
@@ -3490,7 +3985,7 @@ const evalCall = function* (node, input, env, tracker, evaluate$1) {
3490
3985
  if (!specs) throw new RuntimeError(`Unknown function: ${node.name}`, node.span);
3491
3986
  const builtin = specs.find((s) => s.arity === node.args.length);
3492
3987
  if (!builtin) throw new RuntimeError(`Function ${node.name} does not accept ${node.args.length} arguments`, node.span);
3493
- yield* builtin.apply(input, node.args, env, tracker, evaluate$1, node.span);
3988
+ yield* builtin.apply(input, node.args, env, tracker, evaluate, node.span);
3494
3989
  };
3495
3990
  /**
3496
3991
  * Defines a new function in the environment.
@@ -3504,7 +3999,7 @@ const evalCall = function* (node, input, env, tracker, evaluate$1) {
3504
3999
  * @param tracker - Limits tracker.
3505
4000
  * @param evaluate - Recursive evaluator.
3506
4001
  */
3507
- const evalDef = function* (node, input, env, tracker, evaluate$1) {
4002
+ const evalDef = function* (node, input, env, tracker, evaluate) {
3508
4003
  const newFrame = {
3509
4004
  vars: /* @__PURE__ */ new Map(),
3510
4005
  funcs: /* @__PURE__ */ new Map()
@@ -3519,9 +4014,8 @@ const evalDef = function* (node, input, env, tracker, evaluate$1) {
3519
4014
  newFrame.funcs.set(node.name, currentDefs);
3520
4015
  const newStack = [...env, newFrame];
3521
4016
  funDef.closure = newStack;
3522
- yield* evaluate$1(node.next, input, newStack, tracker);
4017
+ yield* evaluate(node.next, input, newStack, tracker);
3523
4018
  };
3524
-
3525
4019
  //#endregion
3526
4020
  //#region src/eval/control_flow.ts
3527
4021
  /**
@@ -3533,17 +4027,17 @@ const evalDef = function* (node, input, env, tracker, evaluate$1) {
3533
4027
  * @param tracker - Limits tracker.
3534
4028
  * @param evaluate - Recursive evaluator.
3535
4029
  */
3536
- const evalIf = function* (node, input, env, tracker, evaluate$1) {
3537
- yield* evalIfBranch(node, 0, input, env, tracker, evaluate$1);
4030
+ const evalIf = function* (node, input, env, tracker, evaluate) {
4031
+ yield* evalIfBranch(node, 0, input, env, tracker, evaluate);
3538
4032
  };
3539
- function* evalIfBranch(node, branchIndex, input, env, tracker, evaluate$1) {
4033
+ function* evalIfBranch(node, branchIndex, input, env, tracker, evaluate) {
3540
4034
  if (branchIndex >= node.branches.length) {
3541
- yield* evaluate$1(node.else, input, env, tracker);
4035
+ yield* evaluate(node.else, input, env, tracker);
3542
4036
  return;
3543
4037
  }
3544
4038
  const branch = node.branches[branchIndex];
3545
- for (const cond of evaluate$1(branch.cond, input, env, tracker)) if (isTruthy(cond)) yield* evaluate$1(branch.then, input, env, tracker);
3546
- else yield* evalIfBranch(node, branchIndex + 1, input, env, tracker, evaluate$1);
4039
+ for (const cond of evaluate(branch.cond, input, env, tracker)) if (isTruthy(cond)) yield* evaluate(branch.then, input, env, tracker);
4040
+ else yield* evalIfBranch(node, branchIndex + 1, input, env, tracker, evaluate);
3547
4041
  }
3548
4042
  /**
3549
4043
  * Evaluates a `try-catch` expression.
@@ -3554,12 +4048,12 @@ function* evalIfBranch(node, branchIndex, input, env, tracker, evaluate$1) {
3554
4048
  * @param tracker - Limits tracker.
3555
4049
  * @param evaluate - Recursive evaluator.
3556
4050
  */
3557
- const evalTry = function* (node, input, env, tracker, evaluate$1) {
4051
+ const evalTry = function* (node, input, env, tracker, evaluate) {
3558
4052
  try {
3559
- yield* evaluate$1(node.body, input, env, tracker);
4053
+ yield* evaluate(node.body, input, env, tracker);
3560
4054
  } catch (err) {
3561
4055
  if (err instanceof RuntimeError) {
3562
- if (node.handler) yield* evaluate$1(node.handler, err.message, env, tracker);
4056
+ if (node.handler) yield* evaluate(node.handler, err.message, env, tracker);
3563
4057
  } else throw err;
3564
4058
  }
3565
4059
  };
@@ -3572,9 +4066,9 @@ const evalTry = function* (node, input, env, tracker, evaluate$1) {
3572
4066
  * @param tracker - Limits tracker.
3573
4067
  * @param evaluate - Recursive evaluator.
3574
4068
  */
3575
- const evalLabel = function* (node, input, env, tracker, evaluate$1) {
4069
+ const evalLabel = function* (node, input, env, tracker, evaluate) {
3576
4070
  try {
3577
- yield* evaluate$1(node.body, input, env, tracker);
4071
+ yield* evaluate(node.body, input, env, tracker);
3578
4072
  } catch (e) {
3579
4073
  if (e instanceof BreakSignal) {
3580
4074
  if (e.label === node.label) return;
@@ -3582,7 +4076,6 @@ const evalLabel = function* (node, input, env, tracker, evaluate$1) {
3582
4076
  throw e;
3583
4077
  }
3584
4078
  };
3585
-
3586
4079
  //#endregion
3587
4080
  //#region src/eval/dispatch.ts
3588
4081
  /**
@@ -3703,8 +4196,10 @@ function* evaluate(node, input, env, tracker) {
3703
4196
  case "As": {
3704
4197
  const values = Array.from(evaluate(node.bind, input, env, tracker));
3705
4198
  for (const val of values) {
4199
+ const vars = /* @__PURE__ */ new Map();
4200
+ bindPattern(node.pattern, val, vars);
3706
4201
  const newFrame = {
3707
- vars: new Map([[node.name, val]]),
4202
+ vars,
3708
4203
  funcs: /* @__PURE__ */ new Map()
3709
4204
  };
3710
4205
  const newEnv = [...env, newFrame];
@@ -3723,7 +4218,301 @@ function* evaluate(node, input, env, tracker) {
3723
4218
  tracker.exit();
3724
4219
  }
3725
4220
  }
3726
-
4221
+ //#endregion
4222
+ //#region src/compat.ts
4223
+ const semanticWarnings = {
4224
+ unique: "jq sorts unique results; jq-ts preserves first-seen order for determinism.",
4225
+ unique_by: "jq sorts unique_by results by key; jq-ts preserves first-seen order.",
4226
+ to_entries: "jq preserves object insertion order; jq-ts sorts object keys deterministically.",
4227
+ with_entries: "jq preserves object insertion order; jq-ts processes object keys in sorted order.",
4228
+ tostring: "jq stringifies objects in input key order; jq-ts uses stable sorted-key stringification.",
4229
+ tojson: "jq tojson preserves input object order; jq-ts uses stable sorted-key stringification.",
4230
+ infinite: "jq serializes infinite as a finite JSON number; jq-ts returns JavaScript Infinity internally.",
4231
+ normal: "jq documents isnormal; jq-ts exposes normal with approximate JavaScript number semantics.",
4232
+ subnormal: "jq documents subnormal classification; jq-ts currently approximates this as false."
4233
+ };
4234
+ const specialVariableWarnings = {
4235
+ ENV: "jq $ENV is an environment snapshot; jq-ts does not populate it unless the caller injects an ENV variable.",
4236
+ __loc__: "jq $__loc__ reports source location metadata; jq-ts does not populate it unless the caller injects a __loc__ variable.",
4237
+ JQ_BUILD_CONFIGURATION: "jq $JQ_BUILD_CONFIGURATION reports jq build metadata; jq-ts does not populate it unless the caller injects a JQ_BUILD_CONFIGURATION variable.",
4238
+ ARGS: "jq $ARGS is populated from CLI arguments; jq-ts does not populate it unless the caller injects an ARGS variable."
4239
+ };
4240
+ const syntaxWarningsByKind = { Slice: "jq slice bounds have jq-specific numeric coercion; jq-ts uses JavaScript slice semantics." };
4241
+ /**
4242
+ * Checks whether a jq expression can be parsed and statically validated by jq-ts.
4243
+ *
4244
+ * This is a syntax/subset check only. It does not prove that runtime behavior
4245
+ * matches the jq binary for every possible input.
4246
+ */
4247
+ const checkCompatibility = (source) => {
4248
+ try {
4249
+ validate(parse(source));
4250
+ return {
4251
+ compatible: true,
4252
+ findings: []
4253
+ };
4254
+ } catch (err) {
4255
+ const finding = toFinding(err);
4256
+ if (finding) return {
4257
+ compatible: false,
4258
+ findings: [finding]
4259
+ };
4260
+ throw err;
4261
+ }
4262
+ };
4263
+ /**
4264
+ * Checks jq-ts compatibility and reports known semantic differences from jq.
4265
+ */
4266
+ const analyzeCompatibility = (source) => {
4267
+ const check = checkCompatibility(source);
4268
+ if (!check.compatible) return {
4269
+ ...check,
4270
+ warnings: []
4271
+ };
4272
+ const warnings = collectWarnings(parse(source));
4273
+ return {
4274
+ compatible: true,
4275
+ findings: warnings,
4276
+ warnings
4277
+ };
4278
+ };
4279
+ /**
4280
+ * Compares jq-ts execution against a caller-provided jq runner or jq result.
4281
+ *
4282
+ * The function is safe to export from the isolate-safe library because it does
4283
+ * not spawn the jq binary itself. Tests and development tools can pass a runner
4284
+ * that shells out to jq.
4285
+ */
4286
+ const compareWithJq = (source, input, jq, options = {}) => {
4287
+ const analysis = analyzeCompatibility(source);
4288
+ const jqTs = runJqTs(source, input, options);
4289
+ const jqResult = typeof jq === "function" ? runExternalJq(jq, source, input) : jq;
4290
+ const findings = [...analysis.findings];
4291
+ if (!jqTs.ok) findings.push({
4292
+ severity: "error",
4293
+ stage: jqTs.stage ?? "runtime",
4294
+ category: "runtime-error",
4295
+ message: jqTs.error
4296
+ });
4297
+ if (!jqResult.ok) findings.push({
4298
+ severity: "error",
4299
+ stage: "compare",
4300
+ category: "jq-error",
4301
+ message: jqResult.error
4302
+ });
4303
+ const equivalent = jqTs.ok && jqResult.ok ? outputStreamsEqual(jqTs.outputs, jqResult.outputs) : null;
4304
+ if (equivalent === false) findings.push({
4305
+ severity: "error",
4306
+ stage: "compare",
4307
+ category: "output-mismatch",
4308
+ message: "jq-ts output stream does not match jq output stream."
4309
+ });
4310
+ return {
4311
+ compatible: analysis.compatible && jqTs.ok,
4312
+ equivalent,
4313
+ analysis,
4314
+ jqTs,
4315
+ jq: jqResult,
4316
+ findings
4317
+ };
4318
+ };
4319
+ const runJqTs = (source, input, options) => {
4320
+ try {
4321
+ const ast = parse(source);
4322
+ validate(ast);
4323
+ return {
4324
+ ok: true,
4325
+ outputs: runAst(ast, input, options)
4326
+ };
4327
+ } catch (err) {
4328
+ const jqTsError = asJqTsError(err);
4329
+ return {
4330
+ ok: false,
4331
+ error: err instanceof Error ? err.message : String(err),
4332
+ stage: jqTsError?.kind
4333
+ };
4334
+ }
4335
+ };
4336
+ const runExternalJq = (runner, source, input) => {
4337
+ try {
4338
+ const result = runner(source, input);
4339
+ if (Array.isArray(result)) return {
4340
+ ok: true,
4341
+ outputs: result
4342
+ };
4343
+ return result;
4344
+ } catch (err) {
4345
+ return {
4346
+ ok: false,
4347
+ error: err instanceof Error ? err.message : String(err),
4348
+ stage: "compare"
4349
+ };
4350
+ }
4351
+ };
4352
+ const outputStreamsEqual = (left, right) => left.length === right.length && left.every((value, index) => valueEquals(value, right[index]));
4353
+ const toFinding = (err) => {
4354
+ const jqTsError = asJqTsError(err);
4355
+ if (!jqTsError) return null;
4356
+ return {
4357
+ severity: "error",
4358
+ stage: jqTsError.kind,
4359
+ category: classifyError(jqTsError),
4360
+ message: jqTsError.message,
4361
+ span: jqTsError.span
4362
+ };
4363
+ };
4364
+ const asJqTsError = (err) => {
4365
+ if (err instanceof LexError || err instanceof ParseError || err instanceof ValidationError || err instanceof RuntimeError) return err;
4366
+ return null;
4367
+ };
4368
+ const classifyError = (err) => {
4369
+ if (err.kind === "parse" || err.kind === "lex") return "unsupported-syntax";
4370
+ if (err.kind === "runtime") return "runtime-error";
4371
+ if (err.message.startsWith("Unknown function:")) return isIntentionalExclusion(err.message) ? "intentional-exclusion" : "unsupported-builtin";
4372
+ if (err.message.includes("expects") && err.message.includes("arguments")) return "arity-mismatch";
4373
+ return "unsupported-syntax";
4374
+ };
4375
+ const isIntentionalExclusion = (message) => [
4376
+ "now",
4377
+ "input",
4378
+ "inputs",
4379
+ "env"
4380
+ ].some((name) => message === `Unknown function: ${name}`);
4381
+ const collectWarnings = (node) => {
4382
+ const warnings = [];
4383
+ visit(node, (current) => {
4384
+ const syntaxWarning = syntaxWarningsByKind[current.kind];
4385
+ if (syntaxWarning) warnings.push({
4386
+ severity: "warning",
4387
+ stage: "validate",
4388
+ category: "input-dependent",
4389
+ message: syntaxWarning,
4390
+ span: current.span
4391
+ });
4392
+ if (current.kind === "Call") {
4393
+ const warning = semanticWarnings[current.name];
4394
+ if (warning) warnings.push({
4395
+ severity: "warning",
4396
+ stage: "validate",
4397
+ category: "semantic-deviation",
4398
+ message: warning,
4399
+ span: current.span
4400
+ });
4401
+ }
4402
+ if (current.kind === "Var") {
4403
+ const warning = specialVariableWarnings[current.name];
4404
+ if (warning) warnings.push({
4405
+ severity: "warning",
4406
+ stage: "validate",
4407
+ category: current.name === "ENV" ? "intentional-exclusion" : "semantic-deviation",
4408
+ message: warning,
4409
+ span: current.span
4410
+ });
4411
+ }
4412
+ });
4413
+ return dedupeFindings(warnings);
4414
+ };
4415
+ const dedupeFindings = (findings) => {
4416
+ const seen = /* @__PURE__ */ new Set();
4417
+ const result = [];
4418
+ for (const finding of findings) {
4419
+ const key = `${finding.category}:${finding.message}:${finding.span?.start ?? ""}:${finding.span?.end ?? ""}`;
4420
+ if (seen.has(key)) continue;
4421
+ seen.add(key);
4422
+ result.push(finding);
4423
+ }
4424
+ return result;
4425
+ };
4426
+ const visit = (node, callback) => {
4427
+ callback(node);
4428
+ switch (node.kind) {
4429
+ case "Identity":
4430
+ case "Literal":
4431
+ case "Var":
4432
+ case "Recurse":
4433
+ case "Break": return;
4434
+ case "FieldAccess":
4435
+ visit(node.target, callback);
4436
+ return;
4437
+ case "IndexAccess":
4438
+ visit(node.target, callback);
4439
+ visit(node.index, callback);
4440
+ return;
4441
+ case "Iterate":
4442
+ visit(node.target, callback);
4443
+ return;
4444
+ case "Slice":
4445
+ visit(node.target, callback);
4446
+ if (node.start) visit(node.start, callback);
4447
+ if (node.end) visit(node.end, callback);
4448
+ return;
4449
+ case "Array":
4450
+ node.items.forEach((item) => visit(item, callback));
4451
+ return;
4452
+ case "Object":
4453
+ node.entries.forEach((entry) => visitObjectEntry(entry, callback));
4454
+ return;
4455
+ case "Pipe":
4456
+ case "Comma":
4457
+ case "Alt":
4458
+ case "Binary":
4459
+ case "Bool":
4460
+ visit(node.left, callback);
4461
+ visit(node.right, callback);
4462
+ return;
4463
+ case "Unary":
4464
+ visit(node.expr, callback);
4465
+ return;
4466
+ case "If":
4467
+ node.branches.forEach((branch) => {
4468
+ visit(branch.cond, callback);
4469
+ visit(branch.then, callback);
4470
+ });
4471
+ visit(node.else, callback);
4472
+ return;
4473
+ case "As":
4474
+ visit(node.bind, callback);
4475
+ visit(node.body, callback);
4476
+ return;
4477
+ case "Call":
4478
+ node.args.forEach((arg) => visit(arg, callback));
4479
+ return;
4480
+ case "Reduce":
4481
+ visit(node.source, callback);
4482
+ visit(node.init, callback);
4483
+ visit(node.update, callback);
4484
+ return;
4485
+ case "Foreach":
4486
+ visit(node.source, callback);
4487
+ visit(node.init, callback);
4488
+ visit(node.update, callback);
4489
+ if (node.extract) visit(node.extract, callback);
4490
+ return;
4491
+ case "Try":
4492
+ visit(node.body, callback);
4493
+ if (node.handler) visit(node.handler, callback);
4494
+ return;
4495
+ case "Assignment":
4496
+ visit(node.left, callback);
4497
+ visit(node.right, callback);
4498
+ return;
4499
+ case "Def":
4500
+ visit(node.body, callback);
4501
+ visit(node.next, callback);
4502
+ return;
4503
+ case "Label":
4504
+ visit(node.body, callback);
4505
+ return;
4506
+ default: return node;
4507
+ }
4508
+ };
4509
+ const visitObjectEntry = (entry, callback) => {
4510
+ visitObjectKey(entry.key, callback);
4511
+ visit(entry.value, callback);
4512
+ };
4513
+ const visitObjectKey = (key, callback) => {
4514
+ if (key.kind === "KeyExpr") visit(key.expr, callback);
4515
+ };
3727
4516
  //#endregion
3728
4517
  //#region src/index.ts
3729
4518
  /**
@@ -3743,15 +4532,17 @@ const run = (source, input, options = {}) => {
3743
4532
  validate(ast);
3744
4533
  return runAst(ast, input, options);
3745
4534
  };
3746
-
3747
4535
  //#endregion
3748
4536
  exports.LexError = LexError;
3749
4537
  exports.LimitTracker = LimitTracker;
3750
4538
  exports.ParseError = ParseError;
3751
4539
  exports.RuntimeError = RuntimeError;
3752
4540
  exports.ValidationError = ValidationError;
4541
+ exports.analyzeCompatibility = analyzeCompatibility;
4542
+ exports.checkCompatibility = checkCompatibility;
4543
+ exports.compareWithJq = compareWithJq;
3753
4544
  exports.parse = parse;
3754
4545
  exports.resolveLimits = resolveLimits;
3755
4546
  exports.run = run;
3756
4547
  exports.runAst = runAst;
3757
- exports.validate = validate;
4548
+ exports.validate = validate;