@mojir/dvala 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +10 -14
  2. package/dist/cli/cli.js +1550 -1252
  3. package/package.json +2 -1
package/dist/cli/cli.js CHANGED
@@ -68,6 +68,17 @@ var DvalaError = class DvalaError extends Error {
68
68
  getCodeMarker() {
69
69
  return this.sourceCodeInfo && getCodeMarker(this.sourceCodeInfo);
70
70
  }
71
+ toJSON() {
72
+ return {
73
+ name: this.name,
74
+ message: this.message,
75
+ shortMessage: this.shortMessage,
76
+ line: this.sourceCodeInfo?.position.line,
77
+ column: this.sourceCodeInfo?.position.column,
78
+ code: this.sourceCodeInfo?.code,
79
+ filePath: this.sourceCodeInfo?.filePath
80
+ };
81
+ }
71
82
  };
72
83
  var UserDefinedError = class UserDefinedError extends DvalaError {
73
84
  userMessage;
@@ -466,7 +477,7 @@ function findAllOccurrences(input, pattern) {
466
477
  }
467
478
  //#endregion
468
479
  //#region package.json
469
- var version = "0.0.13";
480
+ var version = "0.0.15";
470
481
  //#endregion
471
482
  //#region src/typeGuards/string.ts
472
483
  function isString(value, options = {}) {
@@ -5571,7 +5582,7 @@ If all expressions evaluate to truthy values, the value of the last expression i
5571
5582
  }
5572
5583
  return value;
5573
5584
  },
5574
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
5585
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
5575
5586
  };
5576
5587
  const condSpecialExpression = {
5577
5588
  arity: {},
@@ -5614,7 +5625,7 @@ cond
5614
5625
  end ?? "TRUE"`
5615
5626
  ]
5616
5627
  },
5617
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].flat(), contextStack, builtin, evaluateNode)
5628
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1].flat(), contextStack, builtin)
5618
5629
  };
5619
5630
  //#endregion
5620
5631
  //#region src/parser/types.ts
@@ -5627,79 +5638,6 @@ const bindingTargetTypes = {
5627
5638
  wildcard: 16
5628
5639
  };
5629
5640
  //#endregion
5630
- //#region src/utils/maybePromise.ts
5631
- /**
5632
- * Chain a value that might be a Promise. If the value is sync, calls fn synchronously.
5633
- * If it's a Promise, chains with .then().
5634
- */
5635
- function chain(value, fn) {
5636
- if (value instanceof Promise) return value.then(fn);
5637
- return fn(value);
5638
- }
5639
- /**
5640
- * Like Array.map but handles MaybePromise callbacks sequentially.
5641
- * In the sync case, runs as a simple loop. Switches to async only when needed.
5642
- */
5643
- function mapSequential(arr, fn) {
5644
- const results = [];
5645
- for (let i = 0; i < arr.length; i++) {
5646
- const result = fn(arr[i], i);
5647
- if (result instanceof Promise) return chainRemainingMap(result, results, arr, fn, i);
5648
- results.push(result);
5649
- }
5650
- return results;
5651
- }
5652
- async function chainRemainingMap(currentPromise, results, arr, fn, startIndex) {
5653
- results.push(await currentPromise);
5654
- for (let i = startIndex + 1; i < arr.length; i++) results.push(await fn(arr[i], i));
5655
- return results;
5656
- }
5657
- /**
5658
- * Like Array.reduce but handles MaybePromise callbacks sequentially.
5659
- * In the sync case, runs as a simple loop. Switches to async only when needed.
5660
- */
5661
- function reduceSequential(arr, fn, initial) {
5662
- let result = initial;
5663
- for (let i = 0; i < arr.length; i++) {
5664
- const next = fn(result, arr[i], i);
5665
- if (next instanceof Promise) return chainRemainingReduce(next, arr, fn, i);
5666
- result = next;
5667
- }
5668
- return result;
5669
- }
5670
- async function chainRemainingReduce(currentPromise, arr, fn, startIndex) {
5671
- let result = await currentPromise;
5672
- for (let i = startIndex + 1; i < arr.length; i++) result = await fn(result, arr[i], i);
5673
- return result;
5674
- }
5675
- /**
5676
- * Like Array.forEach but handles MaybePromise callbacks sequentially.
5677
- * In the sync case, runs as a simple loop. Switches to async only when needed.
5678
- */
5679
- function forEachSequential(arr, fn) {
5680
- for (let i = 0; i < arr.length; i++) {
5681
- const result = fn(arr[i], i);
5682
- if (result instanceof Promise) return chainRemainingForEach(result, arr, fn, i);
5683
- }
5684
- }
5685
- async function chainRemainingForEach(currentPromise, arr, fn, startIndex) {
5686
- await currentPromise;
5687
- for (let i = startIndex + 1; i < arr.length; i++) await fn(arr[i], i);
5688
- }
5689
- /**
5690
- * Try/catch that handles MaybePromise values correctly.
5691
- * If tryFn returns a Promise, catches both sync throws and Promise rejections.
5692
- */
5693
- function tryCatch(tryFn, catchFn) {
5694
- try {
5695
- const result = tryFn();
5696
- if (result instanceof Promise) return result.catch(catchFn);
5697
- return result;
5698
- } catch (error) {
5699
- return catchFn(error);
5700
- }
5701
- }
5702
- //#endregion
5703
5641
  //#region src/builtin/bindingNode.ts
5704
5642
  function walkDefaults(bindingTarget, onDefault) {
5705
5643
  if (bindingTarget[0] === bindingTargetTypes.object) Object.values(bindingTarget[1][0]).forEach((element) => {
@@ -5714,70 +5652,6 @@ function walkDefaults(bindingTarget, onDefault) {
5714
5652
  walkDefaults(element, onDefault);
5715
5653
  }
5716
5654
  }
5717
- function evaluateBindingNodeValues(target, value, evaluate) {
5718
- const sourceCodeInfo = target[2];
5719
- const record = {};
5720
- return chain(createRecord(target, value, evaluate, sourceCodeInfo, record), () => record);
5721
- }
5722
- function createRecord(bindingTarget, value, evaluate, sourceCodeInfo, record) {
5723
- if (bindingTarget[0] === bindingTargetTypes.object) {
5724
- assertUnknownRecord(value, sourceCodeInfo);
5725
- const capturedKeys = /* @__PURE__ */ new Set();
5726
- let restElement;
5727
- return chain(forEachSequential(Object.entries(bindingTarget[1][0]), ([key, element]) => {
5728
- if (element[0] === bindingTargetTypes.rest) {
5729
- restElement = element;
5730
- return;
5731
- }
5732
- capturedKeys.add(key);
5733
- const existingVal = value[key];
5734
- return chain(existingVal !== void 0 ? existingVal : element[1][1] ? evaluate(element[1][1]) : null, (resolvedVal) => {
5735
- const val = resolvedVal ?? null;
5736
- assertAny(val, sourceCodeInfo);
5737
- return createRecord(element, val, evaluate, sourceCodeInfo, record);
5738
- });
5739
- }), () => {
5740
- if (restElement) {
5741
- const restValues = Object.entries(value).filter(([key]) => !capturedKeys.has(key)).reduce((acc, [key, val]) => {
5742
- acc[key] = asAny(val);
5743
- return acc;
5744
- }, {});
5745
- record[restElement[1][0]] = restValues;
5746
- }
5747
- });
5748
- } else if (bindingTarget[0] === bindingTargetTypes.array) {
5749
- let restIndex = null;
5750
- assertArray(value, sourceCodeInfo);
5751
- const elements = [];
5752
- for (let index = 0; index < bindingTarget[1][0].length; index += 1) {
5753
- const element = bindingTarget[1][0][index] ?? null;
5754
- if (element === null) continue;
5755
- if (element[0] === bindingTargetTypes.rest) {
5756
- restIndex = index;
5757
- break;
5758
- }
5759
- elements.push({
5760
- element,
5761
- index
5762
- });
5763
- }
5764
- return chain(forEachSequential(elements, ({ element, index }) => {
5765
- const existingVal = value[index];
5766
- return chain(existingVal !== void 0 ? existingVal : element[1][1] ? evaluate(element[1][1]) : null, (resolvedVal) => {
5767
- const val = resolvedVal ?? null;
5768
- assertAny(val, sourceCodeInfo);
5769
- return createRecord(element, val, evaluate, sourceCodeInfo, record);
5770
- });
5771
- }), () => {
5772
- if (restIndex !== null) {
5773
- const restValues = value.slice(restIndex);
5774
- const restElement = bindingTarget[1][0][restIndex];
5775
- record[restElement[1][0]] = restValues;
5776
- }
5777
- });
5778
- } else if (bindingTarget[0] === bindingTargetTypes.rest) record[bindingTarget[1][0]] = asAny(value);
5779
- else record[bindingTarget[1][0][1]] = asAny(value);
5780
- }
5781
5655
  function getAllBindingTargetNames(bindingTarget) {
5782
5656
  const names = {};
5783
5657
  getNamesFromBindingTarget(bindingTarget, names);
@@ -5795,98 +5669,6 @@ function getNamesFromBindingTarget(target, names) {
5795
5669
  names[target[1][0][1]] = true;
5796
5670
  }
5797
5671
  }
5798
- /**
5799
- * Non-throwing pattern matching. Returns bindings on match, null on mismatch.
5800
- * Used by `switch` pattern matching.
5801
- */
5802
- function tryMatch(target, value, evaluate) {
5803
- const record = {};
5804
- return chain(tryMatchRecord(target, value, evaluate, record), (matched) => {
5805
- if (!matched) return null;
5806
- return record;
5807
- });
5808
- }
5809
- function tryMatchRecord(bindingTarget, value, evaluate, record) {
5810
- if (bindingTarget[0] === bindingTargetTypes.wildcard) return true;
5811
- else if (bindingTarget[0] === bindingTargetTypes.literal) {
5812
- const literalNode = bindingTarget[1][0];
5813
- return chain(evaluate(literalNode), (literalValue) => {
5814
- return deepEqual$1(value, literalValue);
5815
- });
5816
- } else if (bindingTarget[0] === bindingTargetTypes.symbol) {
5817
- const symbolNode = bindingTarget[1][0];
5818
- const defaultNode = bindingTarget[1][1];
5819
- if (value === void 0 || value === null) {
5820
- if (defaultNode) return chain(evaluate(defaultNode), (defaultValue) => {
5821
- record[symbolNode[1]] = asAny(defaultValue);
5822
- return true;
5823
- });
5824
- record[symbolNode[1]] = value ?? null;
5825
- } else record[symbolNode[1]] = asAny(value);
5826
- return true;
5827
- } else if (bindingTarget[0] === bindingTargetTypes.object) {
5828
- if (!isUnknownRecord(value)) return false;
5829
- const capturedKeys = /* @__PURE__ */ new Set();
5830
- let restElement;
5831
- const entries = Object.entries(bindingTarget[1][0]);
5832
- let result = true;
5833
- for (const [key, element] of entries) result = chain(result, (matched) => {
5834
- if (!matched) return false;
5835
- if (element[0] === bindingTargetTypes.rest) {
5836
- restElement = element;
5837
- return true;
5838
- }
5839
- capturedKeys.add(key);
5840
- const existingVal = value[key];
5841
- if (existingVal === void 0 && element[0] === bindingTargetTypes.literal) return chain(evaluate(element[1][0]), (literalValue) => {
5842
- return deepEqual$1(void 0, literalValue);
5843
- });
5844
- return chain(existingVal !== void 0 ? existingVal : element[1] && element[1][1] ? evaluate(element[1][1]) : null, (resolvedVal) => {
5845
- return tryMatchRecord(element, resolvedVal ?? null, evaluate, record);
5846
- });
5847
- });
5848
- return chain(result, (matched) => {
5849
- if (!matched) return false;
5850
- if (restElement) {
5851
- const restValues = Object.entries(value).filter(([key]) => !capturedKeys.has(key)).reduce((acc, [key, val]) => {
5852
- acc[key] = asAny(val);
5853
- return acc;
5854
- }, {});
5855
- record[restElement[1][0]] = restValues;
5856
- }
5857
- return true;
5858
- });
5859
- } else {
5860
- const arrayTarget = bindingTarget;
5861
- if (!Array.isArray(value)) return false;
5862
- const elements = arrayTarget[1][0];
5863
- let restIndex = null;
5864
- for (let i = 0; i < elements.length; i += 1) {
5865
- const element = elements[i];
5866
- if (element !== null && element[0] === bindingTargetTypes.rest) {
5867
- restIndex = i;
5868
- break;
5869
- }
5870
- }
5871
- if (restIndex === null && value.length !== elements.length) return false;
5872
- if (restIndex !== null && value.length < restIndex) return false;
5873
- let result = true;
5874
- for (let i = 0; i < elements.length; i += 1) {
5875
- const element = elements[i];
5876
- if (element === null) continue;
5877
- if (element[0] === bindingTargetTypes.rest) {
5878
- record[element[1][0]] = value.slice(i);
5879
- break;
5880
- }
5881
- const el = element;
5882
- result = chain(result, (matched) => {
5883
- if (!matched) return false;
5884
- return tryMatchRecord(el, asAny(value[i]), evaluate, record);
5885
- });
5886
- }
5887
- return result;
5888
- }
5889
- }
5890
5672
  const matchSpecialExpression = {
5891
5673
  arity: {},
5892
5674
  docs: {
@@ -5946,15 +5728,15 @@ match { role: "admin", name: "Alice" }
5946
5728
  end`
5947
5729
  ]
5948
5730
  },
5949
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5731
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
5950
5732
  const result = /* @__PURE__ */ new Set();
5951
- getUndefinedSymbols([node[1][1]], contextStack, builtin, evaluateNode).forEach((s) => result.add(s));
5733
+ getUndefinedSymbols([node[1][1]], contextStack, builtin).forEach((s) => result.add(s));
5952
5734
  for (const [pattern, body, guard] of node[1][2]) {
5953
5735
  const newContext = {};
5954
5736
  Object.assign(newContext, getAllBindingTargetNames(pattern));
5955
5737
  const caseContextStack = contextStack.create(newContext);
5956
- if (guard) getUndefinedSymbols([guard], caseContextStack, builtin, evaluateNode).forEach((s) => result.add(s));
5957
- getUndefinedSymbols([body], caseContextStack, builtin, evaluateNode).forEach((s) => result.add(s));
5738
+ if (guard) getUndefinedSymbols([guard], caseContextStack, builtin).forEach((s) => result.add(s));
5739
+ getUndefinedSymbols([body], caseContextStack, builtin).forEach((s) => result.add(s));
5958
5740
  }
5959
5741
  return result;
5960
5742
  }
@@ -5975,7 +5757,7 @@ Built-in symbols are always considered defined. For user-defined symbols, checks
5975
5757
  "defined?(+)"
5976
5758
  ]
5977
5759
  },
5978
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols([node[1][1]], contextStack, builtin, evaluateNode)
5760
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols([node[1][1]], contextStack, builtin)
5979
5761
  };
5980
5762
  const doSpecialExpression = {
5981
5763
  arity: {},
@@ -6012,14 +5794,14 @@ with
6012
5794
  case effect(dvala.io.println) then ([msg]) -> null
6013
5795
  end`]
6014
5796
  },
6015
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
6016
- const bodyResult = getUndefinedSymbols(node[1][1], contextStack.create({}), builtin, evaluateNode);
5797
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
5798
+ const bodyResult = getUndefinedSymbols(node[1][1], contextStack.create({}), builtin);
6017
5799
  const withHandlers = node[1][2];
6018
5800
  if (!withHandlers || withHandlers.length === 0) return bodyResult;
6019
5801
  let withResult = /* @__PURE__ */ new Set();
6020
5802
  for (const [effectExpr, handlerFn] of withHandlers) {
6021
- const effectResult = getUndefinedSymbols([effectExpr], contextStack, builtin, evaluateNode);
6022
- const handlerResult = getUndefinedSymbols([handlerFn], contextStack, builtin, evaluateNode);
5803
+ const effectResult = getUndefinedSymbols([effectExpr], contextStack, builtin);
5804
+ const handlerResult = getUndefinedSymbols([handlerFn], contextStack, builtin);
6023
5805
  withResult = joinSets(withResult, effectResult, handlerResult);
6024
5806
  }
6025
5807
  return joinSets(bodyResult, withResult);
@@ -6029,22 +5811,22 @@ end`]
6029
5811
  //#region src/builtin/specialExpressions/functions.ts
6030
5812
  const lambdaSpecialExpression = {
6031
5813
  arity: {},
6032
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5814
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6033
5815
  const fn = node[1][1];
6034
- return getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin, evaluateNode);
5816
+ return getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin);
6035
5817
  }
6036
5818
  };
6037
- function getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin, evaluateNode) {
5819
+ function getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin) {
6038
5820
  const result = /* @__PURE__ */ new Set();
6039
5821
  const newContext = { self: { value: null } };
6040
5822
  fn[0].forEach((arg) => {
6041
5823
  Object.assign(newContext, getAllBindingTargetNames(arg));
6042
5824
  walkDefaults(arg, (defaultNode) => {
6043
- addToSet(result, getUndefinedSymbols([defaultNode], contextStack, builtin, evaluateNode));
5825
+ addToSet(result, getUndefinedSymbols([defaultNode], contextStack, builtin));
6044
5826
  });
6045
5827
  });
6046
5828
  const newContextStack = contextStack.create(newContext);
6047
- addToSet(result, getUndefinedSymbols(fn[1], newContextStack, builtin, evaluateNode));
5829
+ addToSet(result, getUndefinedSymbols(fn[1], newContextStack, builtin));
6048
5830
  return result;
6049
5831
  }
6050
5832
  const ifSpecialExpression = {
@@ -6085,7 +5867,7 @@ end`,
6085
5867
  "if false then \"TRUE\" end"
6086
5868
  ]
6087
5869
  },
6088
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].filter((n) => !!n), contextStack, builtin, evaluateNode)
5870
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1].filter((n) => !!n), contextStack, builtin)
6089
5871
  };
6090
5872
  const unlessSpecialExpression = {
6091
5873
  arity: {},
@@ -6122,7 +5904,7 @@ end`,
6122
5904
  "unless false then \"TRUE\" end"
6123
5905
  ]
6124
5906
  },
6125
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].filter((n) => !!n), contextStack, builtin, evaluateNode)
5907
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1].filter((n) => !!n), contextStack, builtin)
6126
5908
  };
6127
5909
  const letSpecialExpression = {
6128
5910
  arity: toFixedArity(0),
@@ -6145,13 +5927,13 @@ let a = 1 + 2 + 3 + 4;
6145
5927
  let b = -> $ * ( $ + 1 );
6146
5928
  b(a)`]
6147
5929
  },
6148
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5930
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6149
5931
  const bindingNode = node[1][1];
6150
5932
  const target = bindingNode[1][0];
6151
5933
  const value = bindingNode[1][1];
6152
- const bindingResult = getUndefinedSymbols([value], contextStack, builtin, evaluateNode);
5934
+ const bindingResult = getUndefinedSymbols([value], contextStack, builtin);
6153
5935
  walkDefaults(target, (defaultNode) => {
6154
- addToSet(bindingResult, getUndefinedSymbols([defaultNode], contextStack, builtin, evaluateNode));
5936
+ addToSet(bindingResult, getUndefinedSymbols([defaultNode], contextStack, builtin));
6155
5937
  });
6156
5938
  contextStack.addValues(getAllBindingTargetNames(target), target[2]);
6157
5939
  return bindingResult;
@@ -6188,7 +5970,7 @@ end`, `loop (n = 5, acc = 1) -> do
6188
5970
  end
6189
5971
  end`]
6190
5972
  },
6191
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
5973
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6192
5974
  const bindingNodes = node[1][1];
6193
5975
  const newContext = bindingNodes.reduce((context, bindingNode) => {
6194
5976
  const names = getAllBindingTargetNames(bindingNode[1][0]);
@@ -6197,30 +5979,30 @@ end`]
6197
5979
  });
6198
5980
  return context;
6199
5981
  }, {});
6200
- return joinSets(getUndefinedSymbols(bindingNodes.map((bindingNode) => bindingNode[1][1]), contextStack, builtin, evaluateNode), getUndefinedSymbols([node[1][2]], contextStack.create(newContext), builtin, evaluateNode));
5982
+ return joinSets(getUndefinedSymbols(bindingNodes.map((bindingNode) => bindingNode[1][1]), contextStack, builtin), getUndefinedSymbols([node[1][2]], contextStack.create(newContext), builtin));
6201
5983
  }
6202
5984
  };
6203
5985
  //#endregion
6204
5986
  //#region src/builtin/specialExpressions/loops.ts
6205
- function analyze(loopNode, contextStack, getUndefinedSymbols, builtin, evaluateNode) {
5987
+ function analyze(loopNode, contextStack, getUndefinedSymbols, builtin) {
6206
5988
  const result = /* @__PURE__ */ new Set();
6207
5989
  const newContext = {};
6208
5990
  const [, loopBindings, body] = loopNode[1];
6209
5991
  loopBindings.forEach((loopBindingNode) => {
6210
5992
  const [bindingNode, letBindings, whenNode, whileNode] = loopBindingNode;
6211
5993
  const [target, value] = bindingNode[1];
6212
- getUndefinedSymbols([value], contextStack.create(newContext), builtin, evaluateNode).forEach((symbol) => result.add(symbol));
5994
+ getUndefinedSymbols([value], contextStack.create(newContext), builtin).forEach((symbol) => result.add(symbol));
6213
5995
  Object.assign(newContext, getAllBindingTargetNames(target));
6214
5996
  /* v8 ignore next */
6215
5997
  if (letBindings) letBindings.forEach((letBindingNode) => {
6216
5998
  const [letTarget, letValue] = letBindingNode[1];
6217
- getUndefinedSymbols([letValue], contextStack.create(newContext), builtin, evaluateNode).forEach((symbol) => result.add(symbol));
5999
+ getUndefinedSymbols([letValue], contextStack.create(newContext), builtin).forEach((symbol) => result.add(symbol));
6218
6000
  Object.assign(newContext, getAllBindingTargetNames(letTarget));
6219
6001
  });
6220
- if (whenNode) getUndefinedSymbols([whenNode], contextStack.create(newContext), builtin, evaluateNode).forEach((symbol) => result.add(symbol));
6221
- if (whileNode) getUndefinedSymbols([whileNode], contextStack.create(newContext), builtin, evaluateNode).forEach((symbol) => result.add(symbol));
6002
+ if (whenNode) getUndefinedSymbols([whenNode], contextStack.create(newContext), builtin).forEach((symbol) => result.add(symbol));
6003
+ if (whileNode) getUndefinedSymbols([whileNode], contextStack.create(newContext), builtin).forEach((symbol) => result.add(symbol));
6222
6004
  });
6223
- getUndefinedSymbols([body], contextStack.create(newContext), builtin, evaluateNode).forEach((symbol) => result.add(symbol));
6005
+ getUndefinedSymbols([body], contextStack.create(newContext), builtin).forEach((symbol) => result.add(symbol));
6224
6006
  return result;
6225
6007
  }
6226
6008
  const forSpecialExpression = {
@@ -6279,7 +6061,7 @@ for (
6279
6061
  ) -> ii + j
6280
6062
  `]
6281
6063
  },
6282
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => analyze(node, contextStack, getUndefinedSymbols, builtin, evaluateNode)
6064
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => analyze(node, contextStack, getUndefinedSymbols, builtin)
6283
6065
  };
6284
6066
  const doseqSpecialExpression = {
6285
6067
  arity: toFixedArity(1),
@@ -6329,7 +6111,7 @@ const doseqSpecialExpression = {
6329
6111
  doseq (i in [1, 2, 3]) -> perform(effect(dvala.io.println), i * 2)
6330
6112
  `]
6331
6113
  },
6332
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => analyze(node, contextStack, getUndefinedSymbols, builtin, evaluateNode)
6114
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => analyze(node, contextStack, getUndefinedSymbols, builtin)
6333
6115
  };
6334
6116
  const orSpecialExpression = {
6335
6117
  arity: {},
@@ -6372,7 +6154,7 @@ const orSpecialExpression = {
6372
6154
  }
6373
6155
  return value;
6374
6156
  },
6375
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
6157
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
6376
6158
  };
6377
6159
  const qqSpecialExpression = {
6378
6160
  arity: { min: 1 },
@@ -6420,7 +6202,7 @@ Also works with undefined symbols — if a symbol is undefined, it is treated as
6420
6202
  }
6421
6203
  return null;
6422
6204
  },
6423
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
6205
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
6424
6206
  };
6425
6207
  const recurSpecialExpression = {
6426
6208
  arity: {},
@@ -6459,7 +6241,7 @@ end`
6459
6241
  evaluateAsNormalExpression: (params) => {
6460
6242
  throw new RecurSignal(params);
6461
6243
  },
6462
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
6244
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
6463
6245
  };
6464
6246
  const arraySpecialExpression = {
6465
6247
  arity: {},
@@ -6491,7 +6273,7 @@ const arraySpecialExpression = {
6491
6273
  for (const param of params) result.push(asAny(param, sourceCodeInfo));
6492
6274
  return result;
6493
6275
  },
6494
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
6276
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
6495
6277
  };
6496
6278
  const effectSpecialExpression = {
6497
6279
  arity: {},
@@ -6550,7 +6332,7 @@ let default = {
6550
6332
  }
6551
6333
  return result;
6552
6334
  },
6553
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1], contextStack, builtin, evaluateNode)
6335
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => getUndefinedSymbols(node[1][1], contextStack, builtin)
6554
6336
  };
6555
6337
  const importSpecialExpression = {
6556
6338
  arity: toFixedArity(1),
@@ -6580,8 +6362,8 @@ const parallelSpecialExpression = {
6580
6362
  description: "Evaluates all branch expressions concurrently and returns an array of results in order. Each branch runs as an independent trampoline invocation. If any branch suspends, the entire `parallel` suspends with a composite blob. On resume, branches are resumed one at a time. Only available in async mode (`run()`). Requires at least one branch.",
6581
6363
  examples: []
6582
6364
  },
6583
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
6584
- return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin, evaluateNode)));
6365
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6366
+ return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin)));
6585
6367
  }
6586
6368
  };
6587
6369
  const performSpecialExpression = {
@@ -6612,9 +6394,9 @@ end
6612
6394
  `],
6613
6395
  seeAlso: ["effect?"]
6614
6396
  },
6615
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
6397
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6616
6398
  const [, effectExpr, argExprs] = node[1];
6617
- return joinSets(getUndefinedSymbols([effectExpr], contextStack, builtin, evaluateNode), getUndefinedSymbols(argExprs, contextStack, builtin, evaluateNode));
6399
+ return joinSets(getUndefinedSymbols([effectExpr], contextStack, builtin), getUndefinedSymbols(argExprs, contextStack, builtin));
6618
6400
  }
6619
6401
  };
6620
6402
  const raceSpecialExpression = {
@@ -6630,8 +6412,8 @@ const raceSpecialExpression = {
6630
6412
  description: "Races all branch expressions concurrently. The first branch to complete wins — its value becomes the result. Losing branches are cancelled via AbortSignal. Errored branches are silently dropped. If all branches error, throws an aggregate error. If no branch completes but some suspend, the race suspends. On resume, the host provides the winner value directly. Only available in async mode (`run()`). Requires at least one branch.",
6631
6413
  examples: []
6632
6414
  },
6633
- getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
6634
- return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin, evaluateNode)));
6415
+ getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
6416
+ return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin)));
6635
6417
  }
6636
6418
  };
6637
6419
  //#endregion
@@ -6697,6 +6479,9 @@ function isFunctionDocs(docs) {
6697
6479
  return "args" in docs && "variants" in docs;
6698
6480
  }
6699
6481
  //#endregion
6482
+ //#region src/builtin/modules/assertion/assertion.dvala
6483
+ var assertion_default = "{\n assert-fails: (fn, ...args) -> do\n let message = first(args);\n assert(function?(fn), \"First argument must be a function\");\n if not(null?(message)) then assert(string?(message), \"Second argument must be a string\") end;\n let failed-sentinel = effect(dvala.assertion.failed);\n let result = do fn() with case effect(dvala.error) then ([msg]) -> failed-sentinel end;\n if effect?(result) && result == failed-sentinel then\n null\n else\n assert(false, message ?? \"Expected function to fail\")\n end\n end,\n\n assert-fails-with: (fn, expected-error, ...args) -> do\n let message = first(args);\n assert(function?(fn), \"First argument must be a function\");\n assert(string?(expected-error), \"Second argument must be a string\");\n if not(null?(message)) then assert(string?(message), \"Third argument must be a string\") end;\n let failed-sentinel = effect(dvala.assertion.failed);\n let result = do fn() with case effect(dvala.error) then ([msg]) -> [failed-sentinel, msg] end;\n if array?(result) && first(result) == failed-sentinel then do\n let actual-error = second(result);\n if actual-error == expected-error then\n null\n else\n assert(false, message ?? (\"Expected function to fail with \\\"\" ++ expected-error ++ \"\\\" but got \\\"\" ++ actual-error ++ \"\\\"\"))\n end\n end\n else\n assert(false, message ?? (\"Expected function to fail with \\\"\" ++ expected-error ++ \"\\\"\"))\n end\n end,\n\n assert-succeeds: (fn, ...args) -> do\n let message = first(args);\n assert(function?(fn), \"First argument must be a function\");\n if not(null?(message)) then assert(string?(message), \"Second argument must be a string\") end;\n let failed-sentinel = effect(dvala.assertion.failed);\n let result = do fn() with case effect(dvala.error) then ([msg]) -> failed-sentinel end;\n if effect?(result) && result == failed-sentinel then\n assert(false, message ?? \"Expected function to succeed\")\n else\n null\n end\n end\n}\n";
6484
+ //#endregion
6700
6485
  //#region src/builtin/modules/assertion/docs.ts
6701
6486
  const moduleDocs$5 = {
6702
6487
  "assert!=": {
@@ -6974,22 +6759,22 @@ const moduleDocs$5 = {
6974
6759
  seeAlso: ["assertion.assert-truthy", "assertion.assert-falsy"],
6975
6760
  hideOperatorForm: true
6976
6761
  },
6977
- "assert-throws": {
6762
+ "assert-fails": {
6978
6763
  category: "assertion",
6979
- description: "If $fun does not throw, it throws `AssertionError`.",
6764
+ description: "If $fun does not fail (perform `dvala.error`), it throws `AssertionError`.",
6980
6765
  returns: { type: "null" },
6981
6766
  args: {
6982
6767
  fun: { type: "function" },
6983
6768
  message: { type: "string" }
6984
6769
  },
6985
6770
  variants: [{ argumentNames: ["fun"] }, { argumentNames: ["fun", "message"] }],
6986
- examples: ["let { assert-throws } = import(assertion);\nassert-throws(-> perform(effect(dvala.error), \"Error\"))", "let { assert-throws } = import(assertion);\ndo assert-throws(-> identity(\"Error\")) with case effect(dvala.error) then ([msg]) -> msg end"],
6987
- seeAlso: ["assertion.assert-throws-error", "assertion.assert-not-throws"],
6771
+ examples: ["let { assert-fails } = import(assertion);\nassert-fails(-> perform(effect(dvala.error), \"Error\"))", "let { assert-fails } = import(assertion);\ndo assert-fails(-> identity(\"Error\")) with case effect(dvala.error) then ([msg]) -> msg end"],
6772
+ seeAlso: ["assertion.assert-fails-with", "assertion.assert-succeeds"],
6988
6773
  hideOperatorForm: true
6989
6774
  },
6990
- "assert-throws-error": {
6775
+ "assert-fails-with": {
6991
6776
  category: "assertion",
6992
- description: "If $fun does not throw $error-message, it throws `AssertionError`.",
6777
+ description: "If $fun does not fail with $error-message, it throws `AssertionError`.",
6993
6778
  returns: { type: "null" },
6994
6779
  args: {
6995
6780
  "fun": { type: "function" },
@@ -7001,21 +6786,21 @@ const moduleDocs$5 = {
7001
6786
  "error-message",
7002
6787
  "message"
7003
6788
  ] }],
7004
- examples: ["let { assert-throws-error } = import(assertion);\ndo assert-throws-error(-> perform(effect(dvala.error), \"Error\"), \"Error\") with case effect(dvala.error) then ([msg]) -> msg end", "let { assert-throws-error } = import(assertion);\ndo assert-throws-error(-> identity(\"Error\"), \"Error\") with case effect(dvala.error) then ([msg]) -> msg end"],
7005
- seeAlso: ["assertion.assert-throws", "assertion.assert-not-throws"],
6789
+ examples: ["let { assert-fails-with } = import(assertion);\ndo assert-fails-with(-> perform(effect(dvala.error), \"Error\"), \"Error\") with case effect(dvala.error) then ([msg]) -> msg end", "let { assert-fails-with } = import(assertion);\ndo assert-fails-with(-> identity(\"Error\"), \"Error\") with case effect(dvala.error) then ([msg]) -> msg end"],
6790
+ seeAlso: ["assertion.assert-fails", "assertion.assert-succeeds"],
7006
6791
  hideOperatorForm: true
7007
6792
  },
7008
- "assert-not-throws": {
6793
+ "assert-succeeds": {
7009
6794
  category: "assertion",
7010
- description: "If $fun throws, it throws `AssertionError`.",
6795
+ description: "If $fun fails (performs `dvala.error`), it throws `AssertionError`.",
7011
6796
  returns: { type: "null" },
7012
6797
  args: {
7013
6798
  fun: { type: "function" },
7014
6799
  message: { type: "string" }
7015
6800
  },
7016
6801
  variants: [{ argumentNames: ["fun"] }, { argumentNames: ["fun", "message"] }],
7017
- examples: ["let { assert-not-throws } = import(assertion);\ndo assert-not-throws(-> identity(\"Error\")) with case effect(dvala.error) then ([msg]) -> msg end", "let { assert-not-throws } = import(assertion);\ndo assert-not-throws(-> perform(effect(dvala.error), \"Error\")) with case effect(dvala.error) then ([msg]) -> msg end"],
7018
- seeAlso: ["assertion.assert-throws", "assertion.assert-throws-error"],
6802
+ examples: ["let { assert-succeeds } = import(assertion);\ndo assert-succeeds(-> identity(\"OK\")) with case effect(dvala.error) then ([msg]) -> msg end", "let { assert-succeeds } = import(assertion);\ndo assert-succeeds(-> perform(effect(dvala.error), \"Error\")) with case effect(dvala.error) then ([msg]) -> msg end"],
6803
+ seeAlso: ["assertion.assert-fails", "assertion.assert-fails-with"],
7019
6804
  hideOperatorForm: true
7020
6805
  },
7021
6806
  "assert-array": {
@@ -7404,57 +7189,22 @@ const assertNormalExpression = {
7404
7189
  max: 2
7405
7190
  }
7406
7191
  },
7407
- "assert-throws": {
7408
- evaluate: ([func, message], sourceCodeInfo, contextStack, { executeFunction }) => {
7409
- if (message !== void 0) {
7410
- assertString(message, sourceCodeInfo);
7411
- message = ` ${message}`;
7412
- }
7413
- message ??= "";
7414
- assertFunctionLike(func, sourceCodeInfo);
7415
- return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => {
7416
- throw new AssertionError(`Expected function to throw.${message}`, sourceCodeInfo);
7417
- }), () => null);
7418
- },
7192
+ "assert-fails": {
7193
+ evaluate: () => null,
7419
7194
  arity: {
7420
7195
  min: 1,
7421
7196
  max: 2
7422
7197
  }
7423
7198
  },
7424
- "assert-throws-error": {
7425
- evaluate: ([func, throwMessage, message], sourceCodeInfo, contextStack, { executeFunction }) => {
7426
- if (message !== void 0) {
7427
- assertString(message, sourceCodeInfo);
7428
- message = ` ${message}`;
7429
- }
7430
- message ??= "";
7431
- assertString(throwMessage, sourceCodeInfo);
7432
- assertFunctionLike(func, sourceCodeInfo);
7433
- return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => {
7434
- throw new AssertionError(`Expected function to throw "${throwMessage}".${message}`, sourceCodeInfo);
7435
- }), (error) => {
7436
- const errorMessage = error.shortMessage;
7437
- if (errorMessage !== throwMessage) throw new AssertionError(`Expected function to throw "${throwMessage}", but thrown "${errorMessage}".${message}`, sourceCodeInfo);
7438
- return null;
7439
- });
7440
- },
7199
+ "assert-fails-with": {
7200
+ evaluate: () => null,
7441
7201
  arity: {
7442
7202
  min: 2,
7443
7203
  max: 3
7444
7204
  }
7445
7205
  },
7446
- "assert-not-throws": {
7447
- evaluate: ([func, message], sourceCodeInfo, contextStack, { executeFunction }) => {
7448
- if (message !== void 0) {
7449
- assertString(message, sourceCodeInfo);
7450
- message = ` ${message}`;
7451
- }
7452
- message ??= "";
7453
- assertFunctionLike(func, sourceCodeInfo);
7454
- return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => null), () => {
7455
- throw new AssertionError(`Expected function not to throw.${message}`, sourceCodeInfo);
7456
- });
7457
- },
7206
+ "assert-succeeds": {
7207
+ evaluate: () => null,
7458
7208
  arity: {
7459
7209
  min: 1,
7460
7210
  max: 2
@@ -7662,7 +7412,7 @@ if (assertNormalExpression[key]) assertNormalExpression[key].docs = docs;
7662
7412
  const assertModule = {
7663
7413
  name: "assertion",
7664
7414
  functions: assertNormalExpression,
7665
- source: "{}",
7415
+ source: assertion_default,
7666
7416
  docs: moduleDocs$5
7667
7417
  };
7668
7418
  //#endregion
@@ -17203,6 +16953,9 @@ const moduleDocs$1 = {
17203
16953
  }
17204
16954
  };
17205
16955
  //#endregion
16956
+ //#region src/builtin/modules/number-theory/number-theory.dvala
16957
+ var number_theory_default = "do\n // Helper predicates\n let is-prime = (n) ->\n if n < 2 then false\n else if n == 2 then true\n else if n % 2 == 0 then false\n else loop (i = 3) ->\n if i * i > n then true\n else if n % i == 0 then false\n else recur(i + 2) end\n end\n end\n end\n end;\n\n let is-perfect-square = (n) ->\n if n < 0 then false\n else do\n let s = floor(sqrt(n));\n s * s == n\n end end;\n\n let is-perfect-cube = (n) -> do\n let c = round(sign(n) * (abs(n) ^ (1 / 3)));\n c * c * c == n\n end;\n\n let sum-proper-divisors = (n) ->\n if n <= 1 then 0\n else loop (i = 2, acc = 1) ->\n if i * i > n then acc\n else if n % i == 0 then\n if i * i == n then recur(i + 1, acc + i)\n else recur(i + 1, acc + i + n / i) end\n else recur(i + 1, acc) end\n end end;\n\n let is-abundant = (n) -> n > 0 && sum-proper-divisors(n) > n;\n let is-deficient = (n) -> n > 0 && sum-proper-divisors(n) < n;\n let is-composite = (n) -> n > 1 && not(is-prime(n));\n\n let is-happy = (n) -> do\n let sum-of-squared-digits = (x) ->\n loop (num = x, acc = 0) ->\n if num == 0 then acc\n else do\n let d = num % 10;\n recur(floor(num / 10), acc + d * d)\n end end;\n loop (slow = n, fast = sum-of-squared-digits(n)) ->\n if fast == 1 then true\n else if slow == fast then false\n else recur(sum-of-squared-digits(slow), sum-of-squared-digits(sum-of-squared-digits(fast))) end\n end\n end;\n\n let count-bits = (n) ->\n loop (x = n, acc = 0) ->\n if x == 0 then acc\n else recur(floor(x / 2), acc + x % 2) end;\n\n let is-perfect-power = (n) ->\n if n == 1 then true\n else if n < 2 then false\n else loop (k = 2) ->\n if 2 ^ k > n then false\n else do\n let b = round(n ^ (1 / k));\n if b ^ k == n then true\n else recur(k + 1) end\n end\n end end end;\n\n let binom = (n, k) ->\n if k == 0 || k == n then 1\n else loop (i = 0, k2 = min(k, n - k), acc = 1) ->\n if i >= k2 then acc\n else recur(i + 1, k2, acc * (n - i) / (i + 1)) end\n end;\n\n let bell-numbers = [1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, 4213597, 27644437, 190899322, 1382958545, 10480142147, 82864869804, 682076806159, 5832742205057, 51724158235372, 474869816156751, 4506715738447323];\n\n let catalan-numbers = [1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440, 9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420, 24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, 18367353072152, 69533550916004, 263747951750360, 1002242216651368, 3814986502092304];\n\n let mersenne-numbers = [3, 7, 31, 127, 2047, 8191, 131071, 524287, 2147483647];\n\n let perfect-numbers = [6, 28, 496, 8128, 33550336, 8589869056, 137438691328];\n\n let sylvester-numbers = [2, 6, 42, 1806, 3263442, 10650056950806];\n\n let lucky-numbers = [1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, 87, 93, 99, 105, 111, 115, 127, 129, 133, 135, 141, 151, 159, 163, 169, 171, 189, 193, 195, 201, 205, 211, 219, 223, 231, 235, 237, 241, 259, 261, 267, 273, 283, 285, 289, 297, 303, 307, 319, 321, 327, 331, 339, 349, 357, 361, 367, 385, 391, 393, 399, 409, 415, 421, 427, 429, 433, 451, 463, 475, 477, 483, 487, 489, 495, 511, 517, 519, 529, 535, 537, 541, 553, 559, 577, 579, 583, 591, 601, 613, 615, 619, 621, 631, 639, 643, 645, 651, 655, 673, 679, 685, 693, 699, 717, 723, 727, 729, 735, 739, 741, 745, 769, 777, 781, 787, 801, 805, 819, 823, 831, 841, 855, 867, 873, 883, 885, 895, 897, 903, 925, 927, 931, 933, 937, 957, 961, 975, 979, 981, 991, 993, 997, 1009, 1011, 1021, 1023, 1029, 1039, 1041, 1053, 1057, 1087, 1093, 1095, 1101, 1105, 1107, 1117, 1123, 1147, 1155, 1167, 1179, 1183, 1189, 1197, 1201, 1203, 1209, 1219, 1231, 1233, 1245, 1249, 1251, 1261, 1263, 1275, 1281, 1285, 1291, 1303, 1309, 1323, 1329, 1339, 1357, 1365, 1369, 1387, 1389, 1395, 1401, 1417, 1419, 1435, 1441, 1455, 1459, 1471, 1473, 1485, 1491, 1495, 1497, 1501, 1503, 1519, 1533, 1543, 1545, 1563, 1567, 1575, 1579, 1585, 1587, 1597, 1599, 1611, 1639, 1641, 1645, 1659, 1663, 1675, 1693, 1701, 1705, 1711, 1723, 1731, 1737, 1749, 1765, 1767, 1771, 1773, 1777, 1797, 1801, 1809, 1819, 1827, 1831, 1833, 1839, 1857, 1869, 1879, 1893, 1899, 1915, 1921, 1923, 1933, 1941, 1945, 1959, 1963, 1965, 1977, 1983, 1987, 1995, 2001, 2019, 2023, 2031, 2053, 2059, 2065, 2067, 2079, 2083, 2085, 2095, 2113, 2115, 2121, 2125, 2127, 2133, 2163, 2173, 2187, 2209, 2211, 2215, 2217, 2221, 2239, 2251, 2253, 2257, 2271, 2277, 2281, 2283, 2301, 2311, 2317, 2323, 2335, 2343, 2355, 2365, 2379, 2395, 2403, 2407, 2409, 2415, 2419, 2427, 2439, 2445, 2461, 2467, 2473, 2479, 2491, 2493, 2505, 2511, 2523, 2527, 2545, 2557, 2563, 2571, 2575, 2587, 2589, 2593, 2599, 2607, 2625, 2635, 2647, 2649, 2653, 2661, 2667, 2671, 2689, 2697, 2715, 2725, 2755, 2763, 2773, 2781, 2785, 2787, 2797, 2815, 2817, 2821, 2823, 2827, 2835, 2841, 2845, 2851, 2877, 2887, 2899, 2901, 2905, 2913, 2923, 2943, 2953, 2961, 2971, 2973, 2977, 2983, 3003, 3007, 3027, 3031, 3037, 3039, 3049, 3055, 3073, 3075, 3091, 3097, 3099, 3109, 3111, 3121, 3123, 3133, 3153, 3163, 3171, 3175, 3183, 3187, 3199, 3213, 3223, 3229, 3235, 3243, 3259, 3261, 3289, 3297, 3301, 3307, 3313, 3325, 3339, 3351, 3355, 3363, 3381, 3403, 3405, 3409, 3411, 3427, 3433, 3439, 3451, 3453, 3465, 3477, 3481, 3487, 3489, 3495, 3499, 3507, 3559, 3565, 3571, 3579, 3595, 3597, 3603, 3607, 3613, 3621, 3625, 3633, 3655, 3661, 3663, 3669, 3675, 3685, 3687, 3697, 3709, 3717, 3721, 3727, 3747, 3753, 3763, 3771, 3781, 3789, 3793, 3795, 3811, 3843, 3847, 3849, 3865, 3873, 3879, 3889, 3891, 3897, 3909, 3915, 3931, 3943, 3951, 3955, 3969, 3975, 3981, 3991, 3999, 4003, 4015, 4023, 4033, 4035, 4041, 4045, 4063, 4069, 4081, 4095, 4105, 4107, 4129, 4131, 4161, 4165, 4173, 4179, 4189, 4195, 4201, 4203, 4207, 4227, 4237, 4251, 4255, 4257, 4263, 4269, 4285, 4287, 4315, 4321, 4329, 4335, 4363, 4377, 4383, 4389, 4399, 4413, 4431, 4441, 4443, 4455, 4461, 4465, 4483, 4485, 4495, 4509, 4519, 4521, 4539, 4551, 4561, 4567, 4569, 4573, 4587, 4609, 4611, 4621, 4623, 4629, 4645, 4647, 4653, 4663, 4671, 4675, 4695, 4699, 4713, 4717, 4725, 4741, 4761, 4767, 4773, 4797, 4801, 4809, 4813, 4819, 4833, 4837, 4839, 4843, 4851, 4863, 4867, 4881, 4887, 4893, 4929, 4951, 4963, 4965, 4969, 4977, 4987, 4989, 4993, 4999, 5001, 5007, 5019, 5029, 5041, 5043, 5049, 5053, 5089, 5103, 5127, 5137, 5139, 5149, 5151, 5157, 5169, 5179, 5181, 5191, 5211, 5217, 5229, 5233, 5235, 5253, 5259, 5277, 5283, 5293, 5295, 5299, 5325, 5335, 5341, 5343, 5371, 5377, 5379, 5385, 5409, 5419, 5427, 5433, 5449, 5455, 5463, 5473, 5487, 5491, 5503, 5515, 5527, 5547, 5551, 5559, 5569, 5577, 5587, 5589, 5593, 5599, 5613, 5617, 5637, 5641, 5649, 5655, 5661, 5671, 5673, 5679, 5691, 5701, 5707, 5713, 5719, 5737, 5755, 5763, 5767, 5769, 5803, 5809, 5817, 5827, 5833, 5839, 5851, 5869, 5883, 5889, 5893, 5901, 5905, 5911, 5913, 5923, 5959, 5965, 5967, 5971, 5973, 5977, 5991, 5997, 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093, 6111, 6115, 6123, 6141, 6147, 6159, 6163, 6175, 6177, 6195, 6211, 6229, 6237, 6243, 6249, 6253, 6271, 6273, 6279, 6301, 6309, 6331, 6345, 6351, 6355, 6363, 6367, 6369, 6373, 6379, 6385, 6399, 6411, 6415, 6427, 6433, 6435, 6447, 6463, 6471, 6475, 6477, 6501, 6505, 6523, 6531, 6535, 6541, 6553, 6559, 6567, 6573, 6601, 6621, 6625, 6631, 6661, 6663, 6667, 6669, 6679, 6687, 6693, 6715, 6723, 6733, 6741, 6745, 6747, 6753, 6757, 6763, 6765, 6783, 6787, 6789, 6841, 6849, 6867, 6871, 6883, 6891, 6909, 6915, 6921, 6931, 6933, 6937, 6951, 6981, 6985, 6999, 7003, 7009, 7035, 7041, 7045, 7047, 7069, 7077, 7081, 7087, 7101, 7111, 7129, 7135, 7153, 7167, 7171, 7173, 7183, 7191, 7195, 7197, 7207, 7215, 7231, 7233, 7237, 7245, 7249, 7279, 7293, 7299, 7311, 7321, 7333, 7339, 7341, 7345, 7357, 7359, 7371, 7377, 7395, 7401, 7405, 7419, 7435, 7437, 7443, 7447, 7459, 7471, 7489, 7501, 7503, 7507, 7531, 7533, 7549, 7551, 7563, 7567, 7575, 7585, 7591, 7593, 7603, 7609, 7629, 7633, 7639, 7645, 7677, 7687, 7689, 7701, 7711, 7717, 7737, 7755, 7779, 7791, 7795, 7801, 7803, 7813, 7827, 7833, 7837, 7855, 7881, 7885, 7897, 7899, 7909, 7917, 7921, 7929, 7939, 7947, 7951, 7963, 7969, 7971, 8001, 8005, 8007, 8013, 8037, 8047, 8071, 8073, 8085, 8089, 8107, 8109, 8127, 8131, 8139, 8151, 8161, 8169, 8173, 8175, 8191, 8193, 8221, 8223, 8227, 8233, 8253, 8257, 8263, 8269, 8283, 8289, 8299, 8325, 8331, 8347, 8359, 8365, 8367, 8379, 8409, 8413, 8421, 8445, 8449, 8467, 8473, 8475, 8479, 8487, 8493, 8515, 8535, 8539, 8551, 8553, 8575, 8577, 8583, 8589, 8601, 8605, 8611, 8617, 8635, 8637, 8641, 8647, 8655, 8661, 8673, 8683, 8719, 8757, 8769, 8773, 8787, 8793, 8805, 8809, 8827, 8829, 8833, 8835, 8841, 8869, 8871, 8895, 8913, 8931, 8937, 8947, 8955, 8961, 8977, 8979, 8989, 8995, 8997, 9009, 9031, 9033, 9061, 9063, 9073, 9075, 9081, 9085, 9115, 9117, 9121, 9123, 9135, 9139, 9145, 9151, 9177, 9181, 9211, 9213, 9223, 9231, 9235, 9249, 9253, 9267, 9273, 9277, 9285, 9291, 9303, 9315, 9331, 9339, 9349, 9373, 9387, 9399, 9403, 9409, 9421, 9423, 9429, 9441, 9451, 9457, 9471, 9475, 9481, 9483, 9487, 9501, 9535, 9537, 9543, 9547, 9549, 9555, 9561, 9567, 9613, 9621, 9625, 9631, 9643, 9649, 9661, 9663, 9675, 9687, 9691, 9703, 9727, 9733, 9751, 9753, 9775, 9787, 9789, 9795, 9801, 9807, 9811, 9813, 9837, 9841, 9883, 9895, 9915, 9927, 9937, 9957, 9961, 9979, 9985, 9987, 9997, 9999, 10003, 10009, 10017, 10041, 10051, 10059, 10069, 10071, 10083, 10087, 10089, 10095, 10111, 10117, 10125, 10131, 10143, 10147, 10149, 10153, 10173, 10191, 10195, 10197, 10221, 10239, 10255, 10261, 10275, 10279, 10291, 10311, 10315, 10317, 10321, 10341, 10363, 10365, 10387, 10399, 10411, 10417, 10431, 10441, 10443, 10459, 10461, 10471, 10501, 10507, 10509, 10525, 10531, 10533, 10555, 10563, 10569, 10575, 10585, 10587, 10597, 10599, 10605, 10609, 10635, 10651, 10653, 10659, 10671, 10683, 10723, 10725, 10731, 10747, 10753, 10755, 10759, 10773, 10785, 10789, 10797, 10809, 10843, 10849, 10873, 10881, 10891, 10903, 10909, 10911, 10921, 10923, 10945, 10953, 10965, 10975, 10977, 11005, 11011, 11017, 11047, 11055, 11059, 11073, 11077, 11089, 11091, 11097, 11113, 11137, 11157, 11163, 11173, 11181, 11193, 11197, 11205, 11217, 11223, 11227, 11239, 11245, 11247, 11259, 11263, 11269, 11283, 11289, 11301, 11323, 11341, 11343, 11371, 11373, 11377, 11389, 11391, 11395, 11407, 11419, 11425, 11427, 11437, 11439, 11475, 11479, 11487, 11491, 11521, 11529, 11535, 11539, 11541, 11577, 11581, 11583, 11599, 11617, 11623, 11629, 11641, 11643, 11659, 11667, 11677, 11679, 11707, 11721, 11725, 11731, 11769, 11781, 11797, 11803, 11811, 11815, 11823, 11827, 11833, 11835, 11845, 11847, 11853, 11865, 11877, 11887, 11911, 11923, 11929, 11943, 11953, 11959, 11961, 11991, 11995, 12007, 12015, 12025, 12049, 12057, 12063, 12069, 12079, 12097, 12103, 12117, 12121, 12133, 12139, 12141, 12151, 12159, 12163, 12165, 12193, 12201, 12207, 12223, 12237, 12243, 12265, 12267, 12285, 12295, 12301, 12307, 12315, 12319, 12321, 12333, 12337, 12357, 12363, 12373, 12379, 12391, 12399, 12411, 12417, 12427, 12435, 12457, 12481, 12487, 12495, 12499, 12519, 12543, 12547, 12553, 12567, 12579, 12589, 12607, 12609, 12621, 12631, 12645, 12649, 12651, 12673, 12679, 12699, 12709, 12711, 12729, 12735, 12741, 12759, 12763, 12777, 12781, 12799, 12801, 12813, 12819, 12861, 12867, 12877, 12885, 12903, 12907, 12925, 12937, 12951, 12957, 12961, 12969, 12991, 12999, 13009, 13011, 13021, 13027, 13029, 13053, 13057, 13063, 13077, 13083, 13113, 13117, 13119, 13125, 13129, 13135, 13141, 13167, 13177, 13179, 13203, 13209, 13215, 13219, 13243, 13245, 13267, 13273, 13279, 13281, 13285, 13293, 13309, 13317, 13323, 13327, 13335, 13345, 13347, 13359, 13363, 13371, 13387, 13419, 13441, 13443, 13465, 13473, 13485, 13489, 13513, 13515, 13519, 13527, 13531, 13533, 13537, 13551, 13567, 13575, 13581, 13587, 13599, 13609, 13633, 13657, 13677, 13681, 13693, 13695, 13707, 13723, 13725, 13737, 13741, 13743, 13759, 13801, 13803, 13821, 13831, 13833, 13849, 13851, 13861, 13873, 13893, 13897, 13929, 13947, 13953, 13957, 13995, 14007, 14017, 14031, 14035, 14037, 14041, 14049, 14053, 14059, 14073, 14079, 14091, 14095, 14113, 14115, 14119, 14137, 14163, 14179, 14181, 14185, 14199, 14205, 14209, 14211, 14217, 14229, 14245, 14247, 14253, 14281, 14287, 14293, 14307, 14313, 14317, 14331, 14347, 14349, 14353, 14367, 14395, 14407, 14419, 14427, 14437, 14439, 14443, 14449, 14457, 14461, 14473, 14491, 14493, 14505, 14521, 14523, 14539, 14541, 14565, 14587, 14595, 14599, 14601, 14607, 14625, 14661, 14667, 14689, 14691, 14713, 14715, 14721, 14731, 14749, 14751, 14755, 14775, 14779, 14785, 14793, 14797, 14817, 14841, 14875, 14881, 14883, 14899, 14905, 14919, 14923, 14931, 14935, 14943, 14947, 14973, 14977, 14997, 15003, 15007, 15009, 15025, 15031, 15049, 15057, 15063, 15069, 15073, 15081, 15103, 15109, 15121, 15129, 15133, 15141, 15165, 15169, 15175, 15183, 15187, 15189, 15193, 15205, 15213, 15217, 15229, 15231, 15235, 15237, 15247, 15255, 15259, 15261, 15271, 15291, 15301, 15313, 15333, 15355, 15379, 15381, 15385, 15397, 15417, 15445, 15457, 15469, 15471, 15481, 15487, 15489, 15511, 15519, 15523, 15531, 15543, 15547, 15567, 15573, 15577, 15585, 15597, 15609, 15645, 15655, 15661, 15673, 15675, 15693, 15697, 15717, 15735, 15763, 15771, 15783, 15793, 15805, 15817, 15819, 15835, 15843, 15847, 15855, 15879, 15883, 15891, 15901, 15907, 15919, 15927, 15939, 15955, 15969, 15975, 15981, 15993, 16003, 16009, 16023, 16045, 16047, 16053, 16057, 16077, 16081, 16095, 16101, 16135, 16153, 16191, 16195, 16197, 16203, 16213, 16227, 16237, 16245, 16255, 16267, 16275, 16279, 16287, 16297, 16309, 16329, 16333, 16341, 16353, 16359, 16365, 16381, 16387, 16389, 16393, 16395, 16413, 16417, 16429, 16431, 16447, 16449, 16467, 16473, 16479, 16491, 16507, 16521, 16539, 16557, 16573, 16591, 16611, 16615, 16617, 16621, 16635, 16639, 16657, 16665, 16677, 16701, 16707, 16725, 16747, 16765, 16771, 16773, 16791, 16795, 16825, 16827, 16845, 16863, 16867, 16893, 16915, 16917, 16921, 16933, 16939, 16947, 16953, 16957, 16959, 16969, 16971, 16981, 16995, 17001, 17011, 17017, 17019, 17035, 17047, 17053, 17061, 17083, 17085, 17103, 17115, 17119, 17125, 17127, 17151, 17157, 17173, 17181, 17209, 17211, 17215, 17221, 17223, 17229, 17251, 17253, 17283, 17287, 17305, 17313, 17329, 17335, 17341, 17355, 17359, 17367, 17389, 17391, 17401, 17409, 17431, 17433, 17455, 17463, 17467, 17473, 17485, 17497, 17517, 17527, 17535, 17545, 17547, 17563, 17565, 17581, 17589, 17619, 17625, 17671, 17677, 17689, 17695, 17703, 17713, 17725, 17733, 17737, 17749, 17767, 17769, 17775, 17781, 17787, 17797, 17811, 17829, 17851, 17875, 17883, 17893, 17913, 17925, 17935, 17943, 17947, 17965, 17977, 17991, 17997, 18001, 18007, 18019, 18025, 18043, 18049, 18055, 18067, 18085, 18087, 18123, 18127, 18145, 18147, 18151, 18153, 18169, 18175, 18181, 18187, 18189, 18195, 18207, 18211, 18237, 18253, 18261, 18279, 18283, 18285, 18295, 18303, 18315, 18333, 18375, 18381, 18397, 18399, 18403, 18409, 18441, 18445, 18451, 18459, 18465, 18469, 18475, 18493, 18495, 18501, 18513, 18523, 18535, 18543, 18589, 18591, 18597, 18615, 18619, 18621, 18633, 18639, 18655, 18661, 18681, 18693, 18715, 18717, 18723, 18745, 18747, 18757, 18759, 18765, 18775, 18777, 18783, 18787, 18817, 18819, 18825, 18837, 18849, 18853, 18871, 18873, 18879, 18915, 18937, 18943, 18951, 18967, 18969, 18975, 18979, 18987, 19009, 19015, 19017, 19033, 19051, 19081, 19113, 19119, 19125, 19131, 19153, 19155, 19159, 19161, 19173, 19195, 19197, 19207, 19225, 19237, 19261, 19263, 19269, 19285, 19309, 19323, 19327, 19329, 19333, 19341, 19347, 19351, 19357, 19363, 19365, 19371, 19389, 19395, 19405, 19411, 19417, 19435, 19455, 19467, 19477, 19479, 19503, 19521, 19533, 19543, 19551, 19579, 19581, 19603, 19609, 19615, 19627, 19629, 19657, 19659, 19687, 19693, 19705, 19707, 19711, 19719, 19723, 19725, 19731, 19735, 19755, 19767, 19771, 19773, 19783, 19791, 19807, 19825, 19851, 19861, 19869, 19875, 19893, 19917, 19921, 19929, 19939, 19963, 19981, 19993, 20005, 20013, 20017, 20043, 20067, 20071, 20077, 20085, 20089, 20101, 20103, 20121, 20133, 20149, 20151, 20169, 20181, 20185, 20197, 20203, 20215, 20227, 20253, 20257, 20271, 20295, 20307, 20319, 20341, 20349, 20353, 20355, 20359, 20371, 20379, 20385, 20397, 20403, 20425, 20445, 20449, 20455, 20461, 20475, 20485, 20487, 20509, 20511, 20539, 20551, 20563, 20581, 20583, 20587, 20605, 20611, 20613, 20649, 20665, 20679, 20697, 20713, 20731, 20733, 20739, 20757, 20763, 20769, 20773, 20793, 20797, 20805, 20811, 20821, 20823, 20833, 20835, 20839, 20845, 20859, 20875, 20887, 20889, 20899, 20905, 20923, 20937, 20941, 20953, 20959, 20965, 20991, 21013, 21015, 21021, 21027, 21043, 21049, 21051, 21055, 21073, 21075, 21111, 21115, 21129, 21139, 21147, 21153, 21169, 21175, 21177, 21189, 21193, 21199, 21205, 21211, 21223, 21231, 21253, 21255, 21307, 21309, 21315, 21327, 21331, 21337, 21345, 21373, 21381, 21405, 21409, 21411, 21421, 21433, 21445, 21451, 21453, 21469, 21471, 21475, 21499, 21505, 21529, 21531, 21537, 21549, 21567, 21571, 21591, 21597, 21609, 21613, 21615, 21621, 21655, 21663, 21687, 21693, 21703, 21709, 21717, 21721, 21735, 21739, 21751, 21757, 21759, 21771, 21787, 21819, 21841, 21847, 21867, 21885, 21891, 21897, 21913, 21915, 21925, 21927, 21931, 21933, 21957, 21967, 21987, 21993, 22009, 22017, 22035, 22039, 22075, 22087, 22093, 22095, 22099, 22113, 22119, 22125, 22147, 22155, 22165, 22167, 22177, 22185, 22197, 22225, 22227, 22231, 22269, 22281, 22305, 22327, 22333, 22339, 22369, 22371, 22377, 22381, 22399, 22401, 22411, 22417, 22431, 22437, 22461, 22471, 22473, 22479, 22503, 22507, 22521, 22525, 22527, 22533, 22555, 22569, 22585, 22587, 22591, 22597, 22603, 22617, 22627, 22629, 22651, 22683, 22687, 22689, 22701, 22711, 22743, 22779, 22789, 22791, 22795, 22807, 22827, 22839, 22843, 22851, 22855, 22869, 22879, 22881, 22885, 22893, 22911, 22921, 22941, 22947, 22953, 22957, 22965, 22969, 22975, 22981, 22987, 22999, 23007, 23031, 23037, 23041, 23061, 23067, 23083, 23089, 23095, 23101, 23109, 23137, 23145, 23163, 23169, 23173, 23191, 23193, 23199, 23205, 23269, 23271, 23293, 23295, 23311, 23323, 23341, 23343, 23353, 23355, 23361, 23365, 23373, 23377, 23397, 23419, 23421, 23427, 23445, 23449, 23451, 23457, 23469, 23479, 23499, 23515, 23523, 23529, 23533, 23551, 23563, 23565, 23569, 23571, 23577, 23607, 23613, 23649, 23671, 23677, 23689, 23701, 23709, 23721, 23767, 23775, 23781, 23799, 23805, 23815, 23829, 23835, 23851, 23857, 23881, 23889, 23893, 23913, 23919, 23925, 23929, 23943, 23953, 23955, 23961, 23965, 23971, 23973, 23991, 24013, 24015, 24025, 24033, 24037, 24069, 24073, 24117, 24121, 24129, 24133, 24145, 24151, 24181, 24183, 24213, 24217, 24237, 24247, 24255, 24261, 24277, 24285, 24289, 24301, 24309, 24321, 24327, 24331, 24333, 24343, 24363, 24381, 24387, 24397, 24403, 24405, 24423, 24429, 24447, 24451, 24481, 24499, 24523, 24531, 24571, 24573, 24585, 24591, 24603, 24619, 24633, 24637, 24639, 24643, 24645, 24649, 24663, 24669, 24709, 24711, 24727, 24729, 24733, 24739, 24741, 24759, 24763, 24771, 24783, 24789, 24805, 24811, 24829, 24831, 24843, 24855, 24865, 24873, 24877, 24895, 24907, 24909, 24933, 24951, 24957, 24963, 24985, 24991, 25015, 25017, 25021, 25033, 25057, 25063, 25095, 25099, 25107, 25117, 25119, 25129, 25147, 25153, 25159, 25167, 25171, 25185, 25189, 25201, 25213, 25215, 25225, 25237, 25255, 25263, 25285, 25287, 25293, 25309, 25317, 25335, 25341, 25347, 25377, 25389, 25413, 25425, 25431, 25441, 25455, 25461, 25477, 25483, 25489, 25497, 25503, 25525, 25549, 25561, 25567, 25569, 25581, 25591, 25593, 25611, 25621, 25623, 25645, 25647, 25657, 25671, 25677, 25687, 25737, 25753, 25759, 25771, 25773, 25803, 25815, 25819, 25821, 25833, 25837, 25845, 25855, 25861, 25875, 25893, 25909, 25917, 25923, 25929, 25939, 25959, 25963, 25971, 25977, 25987, 26005, 26007, 26011, 26025, 26035, 26041, 26071, 26085, 26103, 26107, 26115, 26119, 26149, 26155, 26167, 26169, 26179, 26209, 26215, 26217, 26221, 26229, 26251, 26263, 26281, 26293, 26295, 26301, 26313, 26319, 26343, 26347, 26359, 26365, 26385, 26397, 26409, 26413, 26431, 26445, 26467, 26505, 26523, 26529, 26533, 26547, 26553, 26565, 26595, 26599, 26617, 26629, 26641, 26649, 26655, 26659, 26665, 26683, 26695, 26697, 26703, 26719, 26721, 26727, 26733, 26749, 26755, 26757, 26781, 26797, 26805, 26841, 26845, 26847, 26881, 26883, 26893, 26905, 26907, 26913, 26923, 26925, 26935, 26943, 26997, 27001, 27007, 27009, 27013, 27027, 27031, 27033, 27037, 27039, 27061, 27063, 27075, 27079, 27091, 27093, 27097, 27105, 27141, 27157, 27189, 27195, 27199, 27201, 27205, 27207, 27217, 27237, 27265, 27271, 27283, 27301, 27309, 27315, 27321, 27325, 27331, 27333, 27349, 27357, 27363, 27387, 27393, 27409, 27415, 27417, 27427, 27435, 27453, 27457, 27469, 27475, 27477, 27483, 27489, 27493, 27501, 27511, 27531, 27541, 27561, 27585, 27595, 27597, 27603, 27639, 27663, 27667, 27691, 27693, 27705, 27711, 27741, 27751, 27757, 27765, 27783, 27793, 27805, 27807, 27813, 27829, 27831, 27847, 27855, 27859, 27871, 27879, 27913, 27915, 27951, 27961, 27963, 27975, 28021, 28023, 28027, 28039, 28069, 28071, 28083, 28087, 28089, 28101, 28105, 28119, 28123, 28129, 28131, 28141, 28161, 28167, 28191, 28195, 28203, 28233, 28239, 28245, 28293, 28311, 28321, 28329, 28339, 28351, 28359, 28365, 28375, 28393, 28405, 28417, 28429, 28435, 28437, 28459, 28467, 28483, 28509, 28513, 28525, 28563, 28569, 28581, 28593, 28605, 28633, 28639, 28677, 28689, 28701, 28707, 28735, 28759, 28765, 28771, 28791, 28797, 28801, 28803, 28815, 28825, 28827, 28837, 28843, 28855, 28857, 28867, 28869, 28887, 28891, 28905, 28921, 28923, 28933, 28951, 28963, 28969, 28987, 28989, 28993, 28995, 29005, 29025, 29031, 29035, 29049, 29055, 29065, 29089, 29091, 29095, 29113, 29121, 29127, 29137, 29143, 29149, 29157, 29175, 29185, 29193, 29203, 29205, 29239, 29253, 29281, 29283, 29287, 29295, 29311, 29317, 29319, 29329, 29341, 29349, 29371, 29391, 29413, 29437, 29451, 29457, 29467, 29473, 29485, 29487, 29493, 29497, 29515, 29517, 29521, 29533, 29535, 29563, 29577, 29589, 29595, 29599, 29611, 29613, 29623, 29625, 29653, 29659, 29661, 29665, 29677, 29689, 29697, 29709, 29715, 29721, 29751, 29757, 29779, 29781, 29787, 29791, 29805, 29815, 29829, 29845, 29847, 29851, 29865, 29877, 29893, 29905, 29913, 29925, 29949, 29959, 29971, 29973, 29989, 29995, 30013, 30021, 30061, 30067, 30073, 30075, 30087, 30103, 30115, 30121, 30159, 30163, 30181, 30207, 30225, 30229, 30231, 30241, 30243, 30253, 30261, 30265, 30273, 30289, 30291, 30303, 30313, 30327, 30337, 30367, 30369, 30373, 30387, 30397, 30409, 30411, 30429, 30439, 30465, 30471, 30475, 30477, 30495, 30499, 30505, 30523, 30529, 30537, 30541, 30543, 30547, 30559, 30565, 30567, 30589, 30601, 30643, 30651, 30681, 30687, 30727, 30747, 30753, 30765, 30775, 30777, 30789, 30793, 30807, 30817, 30837, 30849, 30861, 30871, 30873, 30877, 30885, 30901, 30915, 30919, 30943, 30945, 30949, 30969, 30997, 30999, 31003, 31021, 31029, 31033, 31039, 31051, 31069, 31071, 31081, 31093, 31095, 31107, 31135, 31137, 31143, 31147, 31189, 31191, 31207, 31221, 31231, 31237, 31239, 31249, 31251, 31255, 31261, 31263, 31293, 31303, 31311, 31315, 31335, 31341, 31363, 31381, 31383, 31387, 31389, 31395, 31405, 31411, 31425, 31429];\n\n let partition-numbers = [1, 2, 3, 5, 7, 11, 15, 22, 30, 42, 56, 77, 101, 135, 176, 231, 297, 385, 490, 627, 792, 1002, 1255, 1575, 1958, 2436, 3010, 3718, 4565, 5604, 6842, 8349, 10143, 12310, 14883, 17977, 21637, 26015, 31185, 37338, 44583, 53174, 63261, 75175, 89134, 105558, 124754, 147273, 173525, 204226, 239943, 281589, 329931, 386155, 451276, 526823, 614154, 715220, 831820, 966467, 1121505, 1300156, 1505499, 1741630, 2012558, 2323520, 2679689, 3087735, 3554345, 4087968, 4697205, 5392783, 6185689, 7089500, 8118264, 9289091, 10619863, 12132164, 13848650, 15796476, 18004327, 20506255, 23338469, 26543660, 30167357, 34262962, 38887673, 44108109, 49995925, 56634173, 64112359, 72533807, 82010177, 92669720, 104651419, 118114304, 133230930, 150198136, 169229875, 190569292, 214481126, 241265379, 271248950, 304801365, 342325709, 384276336, 431149389, 483502844, 541946240, 607163746, 679903203, 761002156, 851376628, 952050665, 1064144451, 1188908248, 1327710076, 1482074143, 1653668665, 1844349560, 2056148051, 2291320912, 2552338241, 2841940500, 3163127352, 3519222692, 3913864295, 4351078600, 4835271870, 5371315400, 5964539504, 6620830889, 7346629512, 8149040695, 9035836076, 10015581680, 11097645016, 12292341831, 13610949895, 15065878135, 16670689208, 18440293320, 20390982757, 22540654445, 24908858009, 27517052599, 30388671978, 33549419497, 37027355200, 40853235313, 45060624582, 49686288421, 54770336324, 60356673280, 66493182097, 73232243759, 80630964769, 88751778802, 97662728555, 107438159466, 118159068427, 129913904637, 142798995930, 156919475295, 172389800255, 189334822579, 207890420102, 228204732751, 250438925115, 274768617130, 301384802048, 330495499613, 362326859895, 397125074750, 435157697830, 476715857290, 522115831195, 571701605655, 625846753120, 684957390936, 749474411781, 819876908323, 896684817527, 980462880430, 1071823774337, 1171432692373, 1280011042268, 1398341745571, 1527273599625, 1667727404093, 1820701100652, 1987276856363, 2168627105469, 2366022741845, 2580840212973, 2814570987591, 3068829878530, 3345365983698, 3646072432125, 3972999029388, 4328363658647, 4714566886083, 5134205287973, 5590088317495, 6085253859260, 6622987708040, 7206841706490, 7840656226137, 8528581302375, 9275102575355, 10085065885767, 10963707205259, 11916681236278, 12950095925895, 14070545699287, 15285151248481, 16601598107914, 18028182516671, 19573856161145, 21248279009367, 23061871173849, 25025873760111, 27152408925615, 29454549941750, 31946390696157, 34643126322519, 37561133582570, 40718063627362, 44132934884255, 47826239745920, 51820051838712, 56138148670947, 60806135438329, 65851585970275, 71304185514919, 77195892663512, 83561103925871, 90436839668817, 97862933703585, 105882246722733, 114540884553038, 123888443077259, 133978259344888, 144867692496445, 156618412527946, 169296722391554, 182973889854026, 197726516681672, 213636919820625, 230793554364681, 249291451168559, 269232701252579, 290726957916112, 313891991306665, 338854264248680, 365749566870782, 394723676655357, 425933084409356, 459545750448675, 495741934760846, 534715062908609, 576672674947168, 621837416509615, 670448123060170, 722760953690372, 779050629562167, 839611730366814, 904760108316360, 974834369944625, 1050197489931117, 1131238503938606, 1218374349844333, 1312051800816215, 1412749565173450, 1520980492851175, 1637293969337171, 1762278433057269, 1896564103591584, 2040825852575075, 2195786311682516, 2362219145337711, 2540952590045698, 2732873183547535, 2938929793929555, 3160137867148997, 3397584011986773, 3652430836071053, 3925922161489422, 4219388528587095, 4534253126900886, 4872038056472084, 5234371069753672, 5622992691950605, 6039763882095515, 6486674127079088, 6965850144195831, 7479565078510584, 8030248384943040, 8620496275465025];\n\n {\n // =========================================================================\n // FINITE SEQUENCES — generate inline\n // =========================================================================\n\n fibonacci-take-while: (fn) -> do\n loop (result = [], a = 0, b = 1, i = 0) ->\n if fn(a, i) then recur(push(result, a), b, a + b, i + 1)\n else result end\n end,\n\n tribonacci-take-while: (fn) -> do\n loop (result = [], a = 0, b = 1, c = 1, i = 0) ->\n if fn(a, i) then recur(push(result, a), b, c, a + b + c, i + 1)\n else result end\n end,\n\n lucas-take-while: (fn) -> do\n loop (result = [], a = 2, b = 1, i = 0) ->\n if fn(a, i) then recur(push(result, a), b, a + b, i + 1)\n else result end\n end,\n\n pell-take-while: (fn) -> do\n loop (result = [], a = 1, b = 2, i = 0) ->\n if fn(a, i) then recur(push(result, a), b, 2 * b + a, i + 1)\n else result end\n end,\n\n padovan-take-while: (fn) -> do\n loop (result = [], a = 1, b = 1, c = 1, i = 0) ->\n if fn(a, i) then recur(push(result, a), b, c, a + b, i + 1)\n else result end\n end,\n\n factorial-take-while: (fn) -> do\n loop (result = [], fact = 1, i = 0) ->\n if fn(fact, i) then recur(push(result, fact), fact * (i + 1), i + 1)\n else result end\n end,\n\n\n\n // =========================================================================\n // PREDICATE SEQUENCES — use inline predicates\n // =========================================================================\n\n prime-take-while: (fn) -> do\n loop (result = [], n = 2) ->\n if is-prime(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n composite-take-while: (fn) -> do\n loop (result = [], n = 4) ->\n if is-composite(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n abundant-take-while: (fn) -> do\n loop (result = [], n = 12) ->\n if is-abundant(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n deficient-take-while: (fn) -> do\n loop (result = [], n = 1) ->\n if is-deficient(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n perfect-square-take-while: (fn) -> do\n loop (result = [], i = 1) -> do\n let val = i * i;\n if fn(val, i - 1) then recur(push(result, val), i + 1)\n else result end\n end\n end,\n\n perfect-cube-take-while: (fn) -> do\n loop (result = [], i = 1) -> do\n let val = i * i * i;\n if fn(val, i - 1) then recur(push(result, val), i + 1)\n else result end\n end\n end,\n\n happy-take-while: (fn) -> do\n loop (result = [], n = 1) ->\n if is-happy(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n // =========================================================================\n // PARAMETERIZED SEQUENCES\n // =========================================================================\n\n arithmetic-take-while: (start, step, fn) -> do\n loop (result = [], i = 0) -> do\n let val = start + i * step;\n if fn(val, i) then recur(push(result, val), i + 1)\n else result end\n end\n end,\n\n geometric-take-while: (start, ratio, fn) -> do\n loop (result = [], i = 0) -> do\n let val = start * (ratio ^ i);\n if fn(val, i) then recur(push(result, val), i + 1)\n else result end\n end\n end,\n\n polygonal-take-while: (sides, fn) -> do\n loop (result = [], n = 1) -> do\n let val = (sides - 2) * n * (n - 1) / 2 + n;\n if fn(val, n - 1) then recur(push(result, val), n + 1)\n else result end\n end\n end,\n\n look-and-say-take-while: (fn) -> do\n let next-term = (s) -> do\n loop (result = \"\", i = 0) ->\n if i >= count(s) then result\n else do\n let ch = nth(s, i);\n let cnt = loop (c = 1, j = i + 1) ->\n if j < count(s) && nth(s, j) == ch then recur(c + 1, j + 1)\n else c end;\n recur(++(result, str(cnt), ch), i + cnt)\n end\n end\n end;\n loop (result = [], term = \"1\", idx = 0) ->\n if fn(term, idx) then recur(push(result, term), next-term(term), idx + 1)\n else result end\n end,\n\n // =========================================================================\n // FINITE SEQUENCES — iterate precomputed arrays\n // =========================================================================\n\n bell-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(bell-numbers) then result\n else if fn(nth(bell-numbers, i), i) then recur(push(result, nth(bell-numbers, i)), i + 1)\n else result end\n end\n end,\n\n catalan-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(catalan-numbers) then result\n else if fn(nth(catalan-numbers, i), i) then recur(push(result, nth(catalan-numbers, i)), i + 1)\n else result end\n end\n end,\n\n mersenne-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(mersenne-numbers) then result\n else if fn(nth(mersenne-numbers, i), i) then recur(push(result, nth(mersenne-numbers, i)), i + 1)\n else result end\n end\n end,\n\n partition-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(partition-numbers) then result\n else if fn(nth(partition-numbers, i), i) then recur(push(result, nth(partition-numbers, i)), i + 1)\n else result end\n end\n end,\n\n perfect-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(perfect-numbers) then result\n else if fn(nth(perfect-numbers, i), i) then recur(push(result, nth(perfect-numbers, i)), i + 1)\n else result end\n end\n end,\n\n sylvester-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(sylvester-numbers) then result\n else if fn(nth(sylvester-numbers, i), i) then recur(push(result, nth(sylvester-numbers, i)), i + 1)\n else result end\n end\n end,\n\n // =========================================================================\n // DYNAMIC SEQUENCES — generate on-the-fly\n // =========================================================================\n\n bernoulli-take-while: (fn) -> do\n // b-arr accumulates all Bernoulli numbers computed so far; B(0)=1 is always included\n loop (b-arr = [1], n = 1) -> do\n let bn = if n > 1 && n % 2 == 1 then 0\n else do\n let s = loop (k = 0, acc = 0) ->\n if k >= n then acc\n else recur(k + 1, acc + binom(n + 1, k) * nth(b-arr, k)) end;\n (0 - s) / (n + 1)\n end end;\n if fn(bn, n) then recur(push(b-arr, bn), n + 1)\n else b-arr end\n end\n end,\n\n golomb-take-while: (fn) -> do\n // g-arr is 0-indexed: g-arr[i] = g(i+1). g(1)=1, g(n)=1+g(n-g(g(n-1)))\n if not(fn(1, 0)) then []\n else do\n loop (g-arr = [1], n = 2) -> do\n let gn1 = nth(g-arr, n - 2);\n let ggn1 = nth(g-arr, gn1 - 1);\n let gval = 1 + nth(g-arr, n - 1 - ggn1);\n if fn(gval, n - 1) then recur(push(g-arr, gval), n + 1)\n else g-arr end\n end\n end\n end\n end,\n\n lucky-take-while: (fn) -> do\n loop (result = [], i = 0) ->\n if i >= count(lucky-numbers) then result\n else if fn(nth(lucky-numbers, i), i) then recur(push(result, nth(lucky-numbers, i)), i + 1)\n else result end\n end\n end,\n\n perfect-power-take-while: (fn) -> do\n loop (result = [], n = 1) ->\n if is-perfect-power(n) then\n if fn(n, count(result)) then recur(push(result, n), n + 1)\n else result end\n else recur(result, n + 1) end\n end,\n\n recaman-take-while: (fn) -> do\n let in-arr = (arr, val) ->\n loop (i = 0) ->\n if i >= count(arr) then false\n else if nth(arr, i) == val then true\n else recur(i + 1) end\n end;\n if not(fn(0, 0)) then []\n else do\n loop (result = [0], n = 1) -> do\n let prev = nth(result, n - 1);\n let backward = prev - n;\n let nxt = if backward > 0 && not(in-arr(result, backward)) then backward\n else prev + n end;\n if fn(nxt, n) then recur(push(result, nxt), n + 1)\n else result end\n end\n end\n end\n end,\n\n thue-morse-take-while: (fn) -> do\n loop (result = [], i = 0) -> do\n let val = count-bits(i) % 2;\n if fn(val, i) then recur(push(result, val), i + 1)\n else result end\n end\n end\n }\nend\n";
16958
+ //#endregion
17206
16959
  //#region src/builtin/modules/number-theory/binomialCefficient.ts
17207
16960
  function binomialCoefficient(n, k) {
17208
16961
  if (k === 0 || k === n) return 1;
@@ -17921,19 +17674,7 @@ const abundantSequence = {
17921
17674
  }
17922
17675
  return abundants;
17923
17676
  },
17924
- "abundant?": (n) => isAbundant(n),
17925
- "abundant-take-while": (takeWhile) => {
17926
- const abundants = [];
17927
- function loop(i) {
17928
- if (!isAbundant(i)) return loop(i + 1);
17929
- return chain(takeWhile(i, abundants.length), (keep) => {
17930
- if (!keep) return abundants;
17931
- abundants.push(i);
17932
- return loop(i + 1);
17933
- });
17934
- }
17935
- return loop(2);
17936
- }
17677
+ "abundant?": (n) => isAbundant(n)
17937
17678
  };
17938
17679
  //#endregion
17939
17680
  //#region src/builtin/modules/number-theory/sequences/arithmetic.ts
@@ -17966,23 +17707,8 @@ const arithmeticNormalExpressions = {
17966
17707
  arity: toFixedArity(3)
17967
17708
  },
17968
17709
  "arithmetic-take-while": {
17969
- evaluate: ([start, step, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
17970
- assertNumber(start, sourceCodeInfo, { finite: true });
17971
- assertNumber(step, sourceCodeInfo, { finite: true });
17972
- assertFunctionLike(fn, sourceCodeInfo);
17973
- const s = start;
17974
- const d = step;
17975
- const f = fn;
17976
- const arithmetic = [];
17977
- function loop(i) {
17978
- const value = s + i * d;
17979
- return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
17980
- if (!keep) return arithmetic;
17981
- arithmetic.push(value);
17982
- return loop(i + 1);
17983
- });
17984
- }
17985
- return loop(0);
17710
+ evaluate: () => {
17711
+ throw new Error("unreachable: overridden by dvalaImpl");
17986
17712
  },
17987
17713
  arity: toFixedArity(3)
17988
17714
  },
@@ -18045,25 +17771,6 @@ function getBernoulliSeq(length) {
18045
17771
  }
18046
17772
  return bernoulli;
18047
17773
  }
18048
- /**
18049
- * Generates Bernoulli numbers as long as the predicate function returns true
18050
- * @param predicate - Function that takes a Bernoulli number and its index and returns true if generation should continue
18051
- * @returns Array of Bernoulli numbers generated until predicate returns false
18052
- */
18053
- function generateBernoulli(predicate) {
18054
- const bernoulli = [1];
18055
- function loop(n) {
18056
- let sum = 0;
18057
- for (let k = 0; k < n; k++) sum += binomialCoefficient(n + 1, k) * bernoulli[k];
18058
- const newValue = n > 1 && n % 2 === 1 ? 0 : -sum / (n + 1);
18059
- return chain(predicate(newValue, n), (keep) => {
18060
- if (!keep) return bernoulli;
18061
- bernoulli.push(newValue);
18062
- return loop(n + 1);
18063
- });
18064
- }
18065
- return loop(1);
18066
- }
18067
17774
  const bernoulliNormalExpressions = {
18068
17775
  "bernoulli-seq": {
18069
17776
  evaluate: ([length], sourceCodeInfo) => {
@@ -18086,10 +17793,8 @@ const bernoulliNormalExpressions = {
18086
17793
  arity: toFixedArity(1)
18087
17794
  },
18088
17795
  "bernoulli-take-while": {
18089
- evaluate: ([fn], sourceCodeInfo, contextStack, { executeFunction }) => {
18090
- assertFunctionLike(fn, sourceCodeInfo);
18091
- const f = fn;
18092
- return generateBernoulli((value, index) => chain(executeFunction(f, [value, index], contextStack), (val) => !!val));
17796
+ evaluate: () => {
17797
+ throw new Error("unreachable: overridden by dvalaImpl");
18093
17798
  },
18094
17799
  arity: toFixedArity(1)
18095
17800
  }
@@ -18141,7 +17846,8 @@ const collatzSequence = {
18141
17846
  }
18142
17847
  return collatz;
18143
17848
  },
18144
- "noNth": true
17849
+ "noNth": true,
17850
+ "noTakeWhile": true
18145
17851
  };
18146
17852
  //#endregion
18147
17853
  //#region src/builtin/modules/number-theory/sequences/prime.ts
@@ -18162,19 +17868,7 @@ const primeSequence = {
18162
17868
  }
18163
17869
  return primes;
18164
17870
  },
18165
- "prime?": (n) => isPrime(n),
18166
- "prime-take-while": (takeWhile) => {
18167
- const primes = [];
18168
- function loop(i) {
18169
- if (!isPrime(i)) return loop(i + 1);
18170
- return chain(takeWhile(i, primes.length), (keep) => {
18171
- if (!keep) return primes;
18172
- primes.push(i);
18173
- return loop(i + 1);
18174
- });
18175
- }
18176
- return loop(2);
18177
- }
17871
+ "prime?": (n) => isPrime(n)
18178
17872
  };
18179
17873
  //#endregion
18180
17874
  //#region src/builtin/modules/number-theory/sequences/composite.ts
@@ -18192,19 +17886,7 @@ const compositeSequence = {
18192
17886
  }
18193
17887
  return composites;
18194
17888
  },
18195
- "composite?": (n) => isComposite(n),
18196
- "composite-take-while": (takeWhile) => {
18197
- const composites = [];
18198
- function loop(i) {
18199
- if (!isComposite(i)) return loop(i + 1);
18200
- return chain(takeWhile(i, composites.length), (keep) => {
18201
- if (!keep) return composites;
18202
- composites.push(i);
18203
- return loop(i + 1);
18204
- });
18205
- }
18206
- return loop(4);
18207
- }
17889
+ "composite?": (n) => isComposite(n)
18208
17890
  };
18209
17891
  //#endregion
18210
17892
  //#region src/builtin/modules/number-theory/sequences/deficient.ts
@@ -18221,19 +17903,7 @@ const deficientSequence = {
18221
17903
  }
18222
17904
  return deficients;
18223
17905
  },
18224
- "deficient?": (n) => isDeficient(n),
18225
- "deficient-take-while": (takeWhile) => {
18226
- const deficients = [];
18227
- function loop(i) {
18228
- if (!isDeficient(i)) return loop(i + 1);
18229
- return chain(takeWhile(i, deficients.length), (keep) => {
18230
- if (!keep) return deficients;
18231
- deficients.push(i);
18232
- return loop(i + 1);
18233
- });
18234
- }
18235
- return loop(1);
18236
- }
17906
+ "deficient?": (n) => isDeficient(n)
18237
17907
  };
18238
17908
  //#endregion
18239
17909
  //#region src/builtin/modules/number-theory/sequences/fibonacci.ts
@@ -18360,23 +18030,8 @@ const geometricNormalExpressions = {
18360
18030
  arity: toFixedArity(3)
18361
18031
  },
18362
18032
  "geometric-take-while": {
18363
- evaluate: ([start, ratio, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
18364
- assertNumber(start, sourceCodeInfo, { finite: true });
18365
- assertNumber(ratio, sourceCodeInfo, { finite: true });
18366
- assertFunctionLike(fn, sourceCodeInfo);
18367
- const s = start;
18368
- const r = ratio;
18369
- const f = fn;
18370
- const geometric = [];
18371
- function loop(i) {
18372
- const value = s * r ** i;
18373
- return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
18374
- if (!keep) return geometric;
18375
- geometric.push(value);
18376
- return loop(i + 1);
18377
- });
18378
- }
18379
- return loop(0);
18033
+ evaluate: () => {
18034
+ throw new Error("unreachable: overridden by dvalaImpl");
18380
18035
  },
18381
18036
  arity: toFixedArity(3)
18382
18037
  },
@@ -18409,25 +18064,9 @@ function getGolombSeq(n) {
18409
18064
  for (let i = 2; i <= n; i += 1) golomb.push(1 + golomb[i - golomb[golomb[i - 1]]]);
18410
18065
  return golomb.slice(1);
18411
18066
  }
18412
- function generateGolombSeq(pred) {
18413
- const golomb = [0, 1];
18414
- return chain(pred(1, 0), (keepFirst) => {
18415
- if (!keepFirst) return [];
18416
- function loop(i) {
18417
- const golombNumber = 1 + golomb[i - golomb[golomb[i - 1]]];
18418
- return chain(pred(golombNumber, i - 1), (keep) => {
18419
- if (!keep) return golomb.slice(1);
18420
- golomb.push(golombNumber);
18421
- return loop(i + 1);
18422
- });
18423
- }
18424
- return loop(2);
18425
- });
18426
- }
18427
18067
  const golombSequence = {
18428
18068
  "golomb-seq": (length) => getGolombSeq(length),
18429
- "golomb?": () => true,
18430
- "golomb-take-while": (takeWhile) => generateGolombSeq(takeWhile)
18069
+ "golomb?": () => true
18431
18070
  };
18432
18071
  //#endregion
18433
18072
  //#region src/builtin/modules/number-theory/sequences/happy.ts
@@ -18463,19 +18102,7 @@ const happySequence = {
18463
18102
  }
18464
18103
  return happyNumbers;
18465
18104
  },
18466
- "happy?": (n) => isHappyNumber(n),
18467
- "happy-take-while": (takeWhile) => {
18468
- const happyNumbers = [];
18469
- function loop(i) {
18470
- if (!isHappyNumber(i)) return loop(i + 1);
18471
- return chain(takeWhile(i, happyNumbers.length), (keep) => {
18472
- if (!keep) return happyNumbers;
18473
- happyNumbers.push(i);
18474
- return loop(i + 1);
18475
- });
18476
- }
18477
- return loop(1);
18478
- }
18105
+ "happy?": (n) => isHappyNumber(n)
18479
18106
  };
18480
18107
  //#endregion
18481
18108
  //#region src/builtin/modules/number-theory/sequences/juggler.ts
@@ -18489,7 +18116,8 @@ const jugglerSequence = {
18489
18116
  }
18490
18117
  return juggler;
18491
18118
  },
18492
- "noNth": true
18119
+ "noNth": true,
18120
+ "noTakeWhile": true
18493
18121
  };
18494
18122
  //#endregion
18495
18123
  //#region src/builtin/modules/number-theory/sequences/lookAndSay.ts
@@ -18535,22 +18163,6 @@ const lookAndSaySequence = {
18535
18163
  for (let i = 1; i < length; i += 1) lookAndSay[i] = lookAndSay[i - 1].replace(/(\d)\1*/g, (match) => `${match.length}${match[0]}`);
18536
18164
  return lookAndSay;
18537
18165
  },
18538
- "look-and-say-take-while": (takeWhile) => {
18539
- const lookAndSay = [];
18540
- return chain(takeWhile("1", 0), (keepFirst) => {
18541
- if (!keepFirst) return lookAndSay;
18542
- lookAndSay.push("1");
18543
- function loop(i) {
18544
- const next = lookAndSay[i - 1].replace(/(\d)\1*/g, (match) => `${match.length}${match[0]}`);
18545
- return chain(takeWhile(next, i), (keep) => {
18546
- if (!keep) return lookAndSay;
18547
- lookAndSay.push(next);
18548
- return loop(i + 1);
18549
- });
18550
- }
18551
- return loop(1);
18552
- });
18553
- },
18554
18166
  "look-and-say?": (n) => isLookAndSay(n)
18555
18167
  };
18556
18168
  //#endregion
@@ -18635,6 +18247,16 @@ const lucasNumbers = [
18635
18247
  7639424778862807
18636
18248
  ];
18637
18249
  //#endregion
18250
+ //#region src/utils/maybePromise.ts
18251
+ /**
18252
+ * Chain a value that might be a Promise. If the value is sync, calls fn synchronously.
18253
+ * If it's a Promise, chains with .then().
18254
+ */
18255
+ function chain(value, fn) {
18256
+ if (value instanceof Promise) return value.then(fn);
18257
+ return fn(value);
18258
+ }
18259
+ //#endregion
18638
18260
  //#region src/builtin/modules/number-theory/sequences/lucky.ts
18639
18261
  /**
18640
18262
  * Generates lucky numbers while the predicate function returns true.
@@ -18711,8 +18333,7 @@ function getLuckyNumbers(count) {
18711
18333
  }
18712
18334
  const luckySequence = {
18713
18335
  "lucky-seq": (length) => getLuckyNumbers(length),
18714
- "lucky?": (n) => generateLuckyNumbers((l) => l <= n).includes(n),
18715
- "lucky-take-while": (takeWhile) => generateLuckyNumbers(takeWhile)
18336
+ "lucky?": (n) => generateLuckyNumbers((l) => l <= n).includes(n)
18716
18337
  };
18717
18338
  //#endregion
18718
18339
  //#region src/builtin/modules/number-theory/sequences/mersenne.ts
@@ -18815,37 +18436,7 @@ const padovanSequence = {
18815
18436
  for (let i = 3; i < length; i += 1) padovan[i] = padovan[i - 2] + padovan[i - 3];
18816
18437
  return padovan.slice(0, length);
18817
18438
  },
18818
- "padovan?": (n) => isPadovan(n),
18819
- "padovan-take-while": (takeWhile) => {
18820
- const padovan = [];
18821
- return chain(takeWhile(1, 0), (keep0) => {
18822
- if (!keep0) return padovan;
18823
- padovan.push(1);
18824
- return chain(takeWhile(1, 1), (keep1) => {
18825
- if (!keep1) return padovan;
18826
- padovan.push(1);
18827
- return chain(takeWhile(1, 2), (keep2) => {
18828
- if (!keep2) return padovan;
18829
- padovan.push(1);
18830
- let a = 1;
18831
- let b = 1;
18832
- let c = 1;
18833
- function loop(i) {
18834
- const temp = a + b;
18835
- a = b;
18836
- b = c;
18837
- c = temp;
18838
- return chain(takeWhile(c, i), (keep) => {
18839
- if (!keep) return padovan;
18840
- padovan.push(c);
18841
- return loop(i + 1);
18842
- });
18843
- }
18844
- return loop(4);
18845
- });
18846
- });
18847
- });
18848
- }
18439
+ "padovan?": (n) => isPadovan(n)
18849
18440
  };
18850
18441
  //#endregion
18851
18442
  //#region src/builtin/modules/number-theory/sequences/pell.ts
@@ -18912,19 +18503,7 @@ const perfectCubeSequence = {
18912
18503
  for (let i = 1; i <= length; i++) perfectcubes.push(i ** 3);
18913
18504
  return perfectcubes;
18914
18505
  },
18915
- "perfect-cube?": (n) => n > 0 && Number.isInteger(Math.cbrt(n)),
18916
- "perfect-cube-take-while": (takeWhile) => {
18917
- const perfectcubes = [];
18918
- function loop(i) {
18919
- const value = i ** 3;
18920
- return chain(takeWhile(value, i), (keep) => {
18921
- if (!keep) return perfectcubes;
18922
- perfectcubes.push(value);
18923
- return loop(i + 1);
18924
- });
18925
- }
18926
- return loop(1);
18927
- }
18506
+ "perfect-cube?": (n) => n > 0 && Number.isInteger(Math.cbrt(n))
18928
18507
  };
18929
18508
  //#endregion
18930
18509
  //#region src/builtin/modules/number-theory/sequences/perfectPower.ts
@@ -18954,19 +18533,7 @@ const perfectPowerSequence = {
18954
18533
  for (let i = 1; perfectPowers.length < length; i++) if (perfectPower(i)) perfectPowers.push(i);
18955
18534
  return perfectPowers;
18956
18535
  },
18957
- "perfect-power?": (n) => perfectPower(n) !== null,
18958
- "perfect-power-take-while": (takeWhile) => {
18959
- const perfectPowers = [];
18960
- function loop(i) {
18961
- if (!perfectPower(i)) return loop(i + 1);
18962
- return chain(takeWhile(i, perfectPowers.length), (keep) => {
18963
- if (!keep) return perfectPowers;
18964
- perfectPowers.push(i);
18965
- return loop(i + 1);
18966
- });
18967
- }
18968
- return loop(1);
18969
- }
18536
+ "perfect-power?": (n) => perfectPower(n) !== null
18970
18537
  };
18971
18538
  //#endregion
18972
18539
  //#region src/builtin/modules/number-theory/sequences/perfectSquare.ts
@@ -18976,19 +18543,7 @@ const perfectSquareSequence = {
18976
18543
  for (let i = 1; i <= length; i++) perfectSquares.push(i ** 2);
18977
18544
  return perfectSquares;
18978
18545
  },
18979
- "perfect-square?": (n) => n > 0 && Number.isInteger(Math.sqrt(n)),
18980
- "perfect-square-take-while": (takeWhile) => {
18981
- const perfectSquares = [];
18982
- function loop(i) {
18983
- const value = i ** 2;
18984
- return chain(takeWhile(value, i), (keep) => {
18985
- if (!keep) return perfectSquares;
18986
- perfectSquares.push(value);
18987
- return loop(i + 1);
18988
- });
18989
- }
18990
- return loop(1);
18991
- }
18546
+ "perfect-square?": (n) => n > 0 && Number.isInteger(Math.sqrt(n))
18992
18547
  };
18993
18548
  //#endregion
18994
18549
  //#region src/builtin/modules/number-theory/sequences/poligonal.ts
@@ -19010,24 +18565,8 @@ const poligonalNormalExpressions = {
19010
18565
  arity: toFixedArity(2)
19011
18566
  },
19012
18567
  "polygonal-take-while": {
19013
- evaluate: ([sides, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
19014
- assertNumber(sides, sourceCodeInfo, {
19015
- integer: true,
19016
- gte: 3
19017
- });
19018
- assertFunctionLike(fn, sourceCodeInfo);
19019
- const s = sides;
19020
- const f = fn;
19021
- const polygonal = [];
19022
- function loop(i) {
19023
- const value = (i * i * (s - 2) - i * (s - 4)) / 2;
19024
- return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
19025
- if (!keep) return polygonal;
19026
- polygonal.push(value);
19027
- return loop(i + 1);
19028
- });
19029
- }
19030
- return loop(1);
18568
+ evaluate: () => {
18569
+ throw new Error("unreachable: overridden by dvalaImpl");
19031
18570
  },
19032
18571
  arity: toFixedArity(2)
19033
18572
  },
@@ -19088,25 +18627,6 @@ function generateRecamanSequence(n) {
19088
18627
  }
19089
18628
  const recamanSequence = {
19090
18629
  "recaman-seq": (length) => generateRecamanSequence(length),
19091
- "recaman-take-while": (takeWhile) => {
19092
- const sequence = [];
19093
- const seen = new Set([0]);
19094
- return chain(takeWhile(0, 0), (keepFirst) => {
19095
- if (!keepFirst) return sequence;
19096
- sequence.push(0);
19097
- function loop(i) {
19098
- let next = sequence[i - 1] - i;
19099
- if (next <= 0 || seen.has(next)) next = sequence[i - 1] + i;
19100
- return chain(takeWhile(next, i), (keep) => {
19101
- if (!keep) return sequence;
19102
- sequence.push(next);
19103
- seen.add(next);
19104
- return loop(i + 1);
19105
- });
19106
- }
19107
- return loop(1);
19108
- });
19109
- },
19110
18630
  "recaman?": () => true
19111
18631
  };
19112
18632
  //#endregion
@@ -19127,18 +18647,6 @@ const thueMorseSequence = {
19127
18647
  for (let i = 0; i < length; i += 1) thueMorse[i] = countSetBits(i) % 2;
19128
18648
  return thueMorse;
19129
18649
  },
19130
- "thue-morse-take-while": (takeWhile) => {
19131
- const thueMorse = [];
19132
- function loop(i) {
19133
- const value = countSetBits(i) % 2;
19134
- return chain(takeWhile(value, i), (keep) => {
19135
- if (!keep) return thueMorse;
19136
- thueMorse.push(value);
19137
- return loop(i + 1);
19138
- });
19139
- }
19140
- return loop(0);
19141
- },
19142
18650
  "thue-morse?": (n) => n === 1 || n === 0
19143
18651
  };
19144
18652
  function countSetBits(num) {
@@ -19260,16 +18768,7 @@ function addNormalExpressions$1(normalExpressions) {
19260
18768
  function getFiniteNumberSequence(name, sequence) {
19261
18769
  return {
19262
18770
  [`${name}-seq`]: createSeqNormalExpression((length) => sequence.slice(0, length), sequence.length),
19263
- [`${name}-take-while`]: createTakeWhileNormalExpression((takeWhile) => {
19264
- function loop(i) {
19265
- if (i >= sequence.length) return sequence.slice(0, i);
19266
- return chain(takeWhile(sequence[i], i), (keep) => {
19267
- if (!keep) return sequence.slice(0, i);
19268
- return loop(i + 1);
19269
- });
19270
- }
19271
- return loop(0);
19272
- }, sequence.length),
18771
+ [`${name}-take-while`]: createTakeWhileNormalExpression(sequence.length),
19273
18772
  [`${name}-nth`]: createNthNormalExpression(() => sequence, sequence.length),
19274
18773
  [`${name}?`]: createNumberPredNormalExpression((n) => sequence.includes(n))
19275
18774
  };
@@ -19281,8 +18780,8 @@ function addSequence(sequence) {
19281
18780
  if (key.endsWith("seq")) {
19282
18781
  sequenceNormalExpressions[key] = createSeqNormalExpression(value, sequence.maxLength);
19283
18782
  if (!sequence.noNth) sequenceNormalExpressions[key.replace(/seq$/, "nth")] = createNthNormalExpression(value, sequence.maxLength);
19284
- } else if (key.endsWith("take-while")) sequenceNormalExpressions[key] = createTakeWhileNormalExpression(value, sequence.maxLength);
19285
- else if (key.endsWith("?")) if (sequence.string) sequenceNormalExpressions[key] = createStringPredNormalExpression(value);
18783
+ if (!sequence.noTakeWhile) sequenceNormalExpressions[key.replace(/seq$/, "take-while")] = createTakeWhileNormalExpression(sequence.maxLength);
18784
+ } else if (key.endsWith("?")) if (sequence.string) sequenceNormalExpressions[key] = createStringPredNormalExpression(value);
19286
18785
  else sequenceNormalExpressions[key] = createNumberPredNormalExpression(value);
19287
18786
  }
19288
18787
  }
@@ -19305,18 +18804,10 @@ function createSeqNormalExpression(seqFunction, maxLength) {
19305
18804
  arity: typeof maxLength === "number" ? { max: 1 } : toFixedArity(1)
19306
18805
  };
19307
18806
  }
19308
- function createTakeWhileNormalExpression(takeWhileFunction, maxLength) {
18807
+ function createTakeWhileNormalExpression(maxLength) {
19309
18808
  return {
19310
- evaluate: (params, sourceCodeInfo, contextStack, { executeFunction }) => {
19311
- const fn = params[0];
19312
- assertFunctionLike(fn, sourceCodeInfo);
19313
- return chain(takeWhileFunction((value, index) => chain(executeFunction(fn, [value, index], contextStack), (val) => !!val), sourceCodeInfo), (resolved) => {
19314
- if (typeof resolved[0] === "number") {
19315
- /* v8 ignore next 3 */
19316
- if (resolved.some((n) => n > Number.MAX_SAFE_INTEGER)) throw new DvalaError("Result exceeds maximum safe integer", sourceCodeInfo);
19317
- }
19318
- return resolved;
19319
- });
18809
+ evaluate: () => {
18810
+ throw new Error("unreachable: overridden by dvalaImpl");
19320
18811
  },
19321
18812
  arity: typeof maxLength === "number" ? { max: 1 } : toFixedArity(1)
19322
18813
  };
@@ -19732,7 +19223,7 @@ if (combinatoricalNormalExpression[key]) combinatoricalNormalExpression[key].doc
19732
19223
  const numberTheoryModule = {
19733
19224
  name: "number-theory",
19734
19225
  functions: combinatoricalNormalExpression,
19735
- source: "{}",
19226
+ source: number_theory_default,
19736
19227
  docs: moduleDocs$1
19737
19228
  };
19738
19229
  //#endregion
@@ -24880,7 +24371,7 @@ function printlnHandler(args, k) {
24880
24371
  k
24881
24372
  };
24882
24373
  }
24883
- function generateUUID() {
24374
+ function generateUUID$1() {
24884
24375
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
24885
24376
  const random = Math.random() * 16 | 0;
24886
24377
  return (char === "x" ? random : random & 3 | 8).toString(16);
@@ -25056,7 +24547,7 @@ const standardEffects = {
25056
24547
  handler: (_args, k) => {
25057
24548
  return {
25058
24549
  type: "Value",
25059
- value: generateUUID(),
24550
+ value: generateUUID$1(),
25060
24551
  k
25061
24552
  };
25062
24553
  },
@@ -26605,57 +26096,416 @@ function createContextStack(params = {}, modules, pure) {
26605
26096
  return params.globalModuleScope ? contextStack : contextStack.create({});
26606
26097
  }
26607
26098
  //#endregion
26608
- //#region src/getUndefinedSymbols/index.ts
26609
- const getUndefinedSymbols$1 = (ast, contextStack, builtin, evaluateNode) => {
26610
- const nodes = Array.isArray(ast) ? ast : [[NodeTypes.SpecialExpression, [
26611
- specialExpressionTypes.block,
26612
- ast.body,
26613
- void 0
26614
- ]]];
26615
- const unresolvedSymbols = /* @__PURE__ */ new Set();
26616
- for (const subNode of nodes) findUnresolvedSymbolsInNode(subNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26617
- return unresolvedSymbols;
26618
- };
26619
- function findUnresolvedSymbolsInNode(node, contextStack, builtin, evaluateNode) {
26620
- const nodeType = node[0];
26621
- switch (nodeType) {
26622
- case NodeTypes.UserDefinedSymbol: {
26623
- const symbolNode = node;
26624
- if (contextStack.lookUp(symbolNode) === null) return new Set([symbolNode[1]]);
26625
- return null;
26626
- }
26627
- case NodeTypes.NormalBuiltinSymbol:
26628
- case NodeTypes.SpecialBuiltinSymbol:
26629
- case NodeTypes.String:
26630
- case NodeTypes.Number:
26631
- case NodeTypes.ReservedSymbol:
26632
- case NodeTypes.Binding: return null;
26633
- case NodeTypes.NormalExpression: {
26634
- const normalExpressionNode = node;
26635
- const unresolvedSymbols = /* @__PURE__ */ new Set();
26636
- if (isNormalExpressionNodeWithName(normalExpressionNode)) {
26637
- const [, [symbolNode]] = normalExpressionNode;
26638
- if (isUserDefinedSymbolNode(symbolNode)) {
26639
- if (contextStack.lookUp(symbolNode) === null) unresolvedSymbols.add(symbolNode[1]);
26640
- }
26641
- } else {
26642
- const [, [expressionNode]] = normalExpressionNode;
26643
- findUnresolvedSymbolsInNode(expressionNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26644
- }
26645
- for (const subNode of normalExpressionNode[1][1]) findUnresolvedSymbolsInNode(subNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26646
- return unresolvedSymbols;
26099
+ //#region src/builtin/bindingSlot.ts
26100
+ /**
26101
+ * Validate that the root value matches the expected binding target structure.
26102
+ *
26103
+ * For array destructuring (`let [a, b] = value`), value must be an array.
26104
+ * For object destructuring (`let {a, b} = value`), value must be an object.
26105
+ * For symbol binding (`let x = value`), no validation needed.
26106
+ */
26107
+ function validateBindingRootType(target, value, sourceCodeInfo) {
26108
+ switch (target[0]) {
26109
+ case bindingTargetTypes.array:
26110
+ assertArray(value, sourceCodeInfo);
26111
+ break;
26112
+ case bindingTargetTypes.object:
26113
+ assertUnknownRecord(value, sourceCodeInfo);
26114
+ break;
26115
+ }
26116
+ }
26117
+ /**
26118
+ * Flatten a binding pattern into a linear list of slots.
26119
+ *
26120
+ * Example: `{a = 1, b: {c = 2}}`
26121
+ * Produces: [
26122
+ * { name: 'a', path: [{type: 'key', key: 'a'}], defaultNode: <1> },
26123
+ * { name: 'c', path: [{type: 'key', key: 'b'}, {type: 'key', key: 'c'}], defaultNode: <2> }
26124
+ * ]
26125
+ */
26126
+ function flattenBindingPattern(target) {
26127
+ const slots = [];
26128
+ flattenTarget(target, [], slots);
26129
+ return slots;
26130
+ }
26131
+ function flattenTarget(target, path, slots) {
26132
+ const sourceCodeInfo = target[2];
26133
+ switch (target[0]) {
26134
+ case bindingTargetTypes.symbol: {
26135
+ const symbolNode = target[1][0];
26136
+ const defaultNode = target[1][1];
26137
+ slots.push({
26138
+ name: symbolNode[1],
26139
+ path: [...path],
26140
+ defaultNode,
26141
+ sourceCodeInfo
26142
+ });
26143
+ break;
26647
26144
  }
26648
- case NodeTypes.SpecialExpression: {
26649
- const specialExpressionNode = node;
26650
- const specialExpressionType = specialExpressionNode[1][0];
26651
- const castedGetUndefinedSymbols = builtin.specialExpressions[specialExpressionType].getUndefinedSymbols;
26652
- return castedGetUndefinedSymbols(specialExpressionNode, contextStack, {
26653
- getUndefinedSymbols: getUndefinedSymbols$1,
26654
- builtin,
26655
- evaluateNode
26145
+ case bindingTargetTypes.rest: {
26146
+ const name = target[1][0];
26147
+ const defaultNode = target[1][1];
26148
+ slots.push({
26149
+ name,
26150
+ path: [...path],
26151
+ defaultNode,
26152
+ isRest: true,
26153
+ sourceCodeInfo
26656
26154
  });
26155
+ break;
26657
26156
  }
26658
- case NodeTypes.Spread: return findUnresolvedSymbolsInNode(node[1], contextStack, builtin, evaluateNode);
26157
+ case bindingTargetTypes.object: {
26158
+ const entries = target[1][0];
26159
+ const capturedKeys = /* @__PURE__ */ new Set();
26160
+ for (const [key, element] of Object.entries(entries)) {
26161
+ if (element[0] === bindingTargetTypes.rest) continue;
26162
+ capturedKeys.add(key);
26163
+ const newPath = [...path, {
26164
+ type: "key",
26165
+ key
26166
+ }];
26167
+ const hasDefault = element[1][1] !== void 0;
26168
+ const isCompound = element[0] === bindingTargetTypes.object || element[0] === bindingTargetTypes.array;
26169
+ if (hasDefault && isCompound) slots.push({
26170
+ name: `_intermediate_${slots.length}`,
26171
+ path: newPath,
26172
+ defaultNode: element[1][1],
26173
+ nestedTarget: element,
26174
+ sourceCodeInfo: element[2]
26175
+ });
26176
+ else flattenTarget(element, newPath, slots);
26177
+ }
26178
+ for (const [_key, element] of Object.entries(entries)) if (element[0] === bindingTargetTypes.rest) {
26179
+ const name = element[1][0];
26180
+ slots.push({
26181
+ name,
26182
+ path: [...path],
26183
+ isRest: true,
26184
+ restKeys: capturedKeys,
26185
+ sourceCodeInfo: element[2]
26186
+ });
26187
+ break;
26188
+ }
26189
+ break;
26190
+ }
26191
+ case bindingTargetTypes.array: {
26192
+ const elements = target[1][0];
26193
+ for (let i = 0; i < elements.length; i++) {
26194
+ const element = elements[i];
26195
+ if (element === null || element === void 0) continue;
26196
+ if (element[0] === bindingTargetTypes.rest) {
26197
+ const name = element[1][0];
26198
+ slots.push({
26199
+ name,
26200
+ path: [...path],
26201
+ isRest: true,
26202
+ restIndex: i,
26203
+ sourceCodeInfo: element[2]
26204
+ });
26205
+ break;
26206
+ }
26207
+ const newPath = [...path, {
26208
+ type: "index",
26209
+ index: i
26210
+ }];
26211
+ const hasDefault = element[1][1] !== void 0;
26212
+ const isCompound = element[0] === bindingTargetTypes.object || element[0] === bindingTargetTypes.array;
26213
+ if (hasDefault && isCompound) slots.push({
26214
+ name: `_intermediate_${slots.length}`,
26215
+ path: newPath,
26216
+ defaultNode: element[1][1],
26217
+ nestedTarget: element,
26218
+ sourceCodeInfo: element[2]
26219
+ });
26220
+ else flattenTarget(element, newPath, slots);
26221
+ }
26222
+ break;
26223
+ }
26224
+ case bindingTargetTypes.literal:
26225
+ case bindingTargetTypes.wildcard: break;
26226
+ }
26227
+ }
26228
+ /**
26229
+ * Extract a value from a nested structure by following a path.
26230
+ *
26231
+ * Returns undefined if the path cannot be followed (missing key/index).
26232
+ */
26233
+ function extractValueByPath(rootValue, path, sourceCodeInfo) {
26234
+ let current = rootValue;
26235
+ for (const step of path) {
26236
+ if (current === null || current === void 0) return;
26237
+ if (step.type === "key") {
26238
+ assertUnknownRecord(current, sourceCodeInfo);
26239
+ current = current[step.key];
26240
+ } else {
26241
+ assertArray(current, sourceCodeInfo);
26242
+ current = current[step.index];
26243
+ }
26244
+ }
26245
+ return current;
26246
+ }
26247
+ /**
26248
+ * Extract rest values for an object rest binding.
26249
+ * Returns an object with all keys except those in restKeys.
26250
+ */
26251
+ function extractObjectRest(value, restKeys, sourceCodeInfo) {
26252
+ assertUnknownRecord(value, sourceCodeInfo);
26253
+ const result = {};
26254
+ for (const [key, val] of Object.entries(value)) if (!restKeys.has(key)) result[key] = asAny(val);
26255
+ return result;
26256
+ }
26257
+ /**
26258
+ * Extract rest values for an array rest binding.
26259
+ * Returns elements from restIndex onwards.
26260
+ */
26261
+ function extractArrayRest(value, restIndex, sourceCodeInfo) {
26262
+ assertArray(value, sourceCodeInfo);
26263
+ return value.slice(restIndex);
26264
+ }
26265
+ //#endregion
26266
+ //#region src/builtin/matchSlot.ts
26267
+ /**
26268
+ * Flatten a binding pattern into a linear list of match slots.
26269
+ * Returns slots in order they should be processed.
26270
+ *
26271
+ * Type checks come first (to fail fast on type mismatch).
26272
+ * Then binding/literal slots in depth-first order.
26273
+ */
26274
+ function flattenMatchPattern(target) {
26275
+ const slots = [];
26276
+ flattenMatchTarget(target, [], slots);
26277
+ return slots;
26278
+ }
26279
+ function flattenMatchTarget(target, path, slots) {
26280
+ switch (target[0]) {
26281
+ case bindingTargetTypes.wildcard:
26282
+ slots.push({
26283
+ kind: "wildcard",
26284
+ path: [...path]
26285
+ });
26286
+ break;
26287
+ case bindingTargetTypes.literal: {
26288
+ const literalNode = target[1][0];
26289
+ slots.push({
26290
+ kind: "literal",
26291
+ path: [...path],
26292
+ literalNode,
26293
+ sourceCodeInfo: target[2]
26294
+ });
26295
+ break;
26296
+ }
26297
+ case bindingTargetTypes.symbol: {
26298
+ const name = target[1][0][1];
26299
+ const defaultNode = target[1][1];
26300
+ slots.push({
26301
+ kind: "bind",
26302
+ name,
26303
+ path: [...path],
26304
+ defaultNode,
26305
+ sourceCodeInfo: target[2]
26306
+ });
26307
+ break;
26308
+ }
26309
+ case bindingTargetTypes.rest: {
26310
+ const name = target[1][0];
26311
+ const defaultNode = target[1][1];
26312
+ slots.push({
26313
+ kind: "rest",
26314
+ name,
26315
+ path: [...path],
26316
+ defaultNode,
26317
+ sourceCodeInfo: target[2]
26318
+ });
26319
+ break;
26320
+ }
26321
+ case bindingTargetTypes.object: {
26322
+ if (path.length > 0) slots.push({
26323
+ kind: "typeCheck",
26324
+ path: [...path],
26325
+ requiredType: "object",
26326
+ sourceCodeInfo: target[2]
26327
+ });
26328
+ const entries = target[1][0];
26329
+ const capturedKeys = /* @__PURE__ */ new Set();
26330
+ let restElement;
26331
+ for (const [key, element] of Object.entries(entries)) {
26332
+ if (element[0] === bindingTargetTypes.rest) {
26333
+ restElement = element;
26334
+ continue;
26335
+ }
26336
+ capturedKeys.add(key);
26337
+ flattenMatchTarget(element, [...path, {
26338
+ type: "key",
26339
+ key
26340
+ }], slots);
26341
+ }
26342
+ if (restElement) slots.push({
26343
+ kind: "rest",
26344
+ name: restElement[1][0],
26345
+ path: [...path],
26346
+ restKeys: capturedKeys,
26347
+ sourceCodeInfo: restElement[2]
26348
+ });
26349
+ break;
26350
+ }
26351
+ case bindingTargetTypes.array: {
26352
+ if (path.length > 0) slots.push({
26353
+ kind: "typeCheck",
26354
+ path: [...path],
26355
+ requiredType: "array",
26356
+ sourceCodeInfo: target[2]
26357
+ });
26358
+ const elements = target[1][0];
26359
+ for (let i = 0; i < elements.length; i++) {
26360
+ const element = elements[i];
26361
+ if (element === null || element === void 0) continue;
26362
+ if (element[0] === bindingTargetTypes.rest) {
26363
+ slots.push({
26364
+ kind: "rest",
26365
+ name: element[1][0],
26366
+ path: [...path],
26367
+ restIndex: i,
26368
+ sourceCodeInfo: element[2]
26369
+ });
26370
+ break;
26371
+ }
26372
+ flattenMatchTarget(element, [...path, {
26373
+ type: "index",
26374
+ index: i
26375
+ }], slots);
26376
+ }
26377
+ break;
26378
+ }
26379
+ }
26380
+ }
26381
+ /**
26382
+ * Extract a value from a nested structure by following a path.
26383
+ * Returns undefined if path cannot be followed.
26384
+ */
26385
+ function extractMatchValueByPath(rootValue, path) {
26386
+ let current = rootValue;
26387
+ for (const step of path) {
26388
+ if (current === null || current === void 0) return;
26389
+ if (step.type === "key") {
26390
+ if (!isUnknownRecord(current)) return void 0;
26391
+ current = current[step.key];
26392
+ } else {
26393
+ if (!Array.isArray(current)) return void 0;
26394
+ current = current[step.index];
26395
+ }
26396
+ }
26397
+ return current;
26398
+ }
26399
+ /**
26400
+ * Check if value matches required type at path.
26401
+ */
26402
+ function checkTypeAtPath(rootValue, path, requiredType) {
26403
+ const value = path.length > 0 ? extractMatchValueByPath(rootValue, path) : rootValue;
26404
+ if (value === null || value === void 0) return false;
26405
+ if (requiredType === "object") return isUnknownRecord(value);
26406
+ else return Array.isArray(value);
26407
+ }
26408
+ /**
26409
+ * Extract rest values for object rest.
26410
+ */
26411
+ function extractMatchObjectRest(value, path, restKeys) {
26412
+ const obj = path.length > 0 ? extractMatchValueByPath(value, path) : value;
26413
+ if (!isUnknownRecord(obj)) return {};
26414
+ const result = {};
26415
+ for (const [key, val] of Object.entries(obj)) if (!restKeys.has(key)) result[key] = asAny(val);
26416
+ return result;
26417
+ }
26418
+ /**
26419
+ * Extract rest values for array rest.
26420
+ */
26421
+ function extractMatchArrayRest(value, path, restIndex) {
26422
+ const arr = path.length > 0 ? extractMatchValueByPath(value, path) : value;
26423
+ if (!Array.isArray(arr)) return [];
26424
+ return arr.slice(restIndex).map((v) => asAny(v));
26425
+ }
26426
+ /**
26427
+ * Check array length constraints at pattern root.
26428
+ * For patterns like [a, b, c] - exact match required.
26429
+ * For patterns like [a, b, ...rest] - minimum match required.
26430
+ */
26431
+ function checkArrayLengthConstraint(target, value) {
26432
+ if (target[0] !== bindingTargetTypes.array) return true;
26433
+ if (!Array.isArray(value)) return false;
26434
+ const elements = target[1][0];
26435
+ let hasRest = false;
26436
+ let nonRestCount = 0;
26437
+ for (const element of elements) {
26438
+ if (element === null) {
26439
+ nonRestCount++;
26440
+ continue;
26441
+ }
26442
+ if (element[0] === bindingTargetTypes.rest) {
26443
+ hasRest = true;
26444
+ break;
26445
+ }
26446
+ nonRestCount++;
26447
+ }
26448
+ if (hasRest) return value.length >= nonRestCount;
26449
+ else return value.length === nonRestCount;
26450
+ }
26451
+ /**
26452
+ * Check object exists at pattern root.
26453
+ */
26454
+ function checkObjectTypeConstraint(target, value) {
26455
+ if (target[0] !== bindingTargetTypes.object) return true;
26456
+ return isUnknownRecord(value);
26457
+ }
26458
+ //#endregion
26459
+ //#region src/getUndefinedSymbols/index.ts
26460
+ const getUndefinedSymbols$1 = (ast, contextStack, builtin) => {
26461
+ const nodes = Array.isArray(ast) ? ast : [[NodeTypes.SpecialExpression, [
26462
+ specialExpressionTypes.block,
26463
+ ast.body,
26464
+ void 0
26465
+ ]]];
26466
+ const unresolvedSymbols = /* @__PURE__ */ new Set();
26467
+ for (const subNode of nodes) findUnresolvedSymbolsInNode(subNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26468
+ return unresolvedSymbols;
26469
+ };
26470
+ function findUnresolvedSymbolsInNode(node, contextStack, builtin) {
26471
+ const nodeType = node[0];
26472
+ switch (nodeType) {
26473
+ case NodeTypes.UserDefinedSymbol: {
26474
+ const symbolNode = node;
26475
+ if (contextStack.lookUp(symbolNode) === null) return new Set([symbolNode[1]]);
26476
+ return null;
26477
+ }
26478
+ case NodeTypes.NormalBuiltinSymbol:
26479
+ case NodeTypes.SpecialBuiltinSymbol:
26480
+ case NodeTypes.String:
26481
+ case NodeTypes.Number:
26482
+ case NodeTypes.ReservedSymbol:
26483
+ case NodeTypes.Binding: return null;
26484
+ case NodeTypes.NormalExpression: {
26485
+ const normalExpressionNode = node;
26486
+ const unresolvedSymbols = /* @__PURE__ */ new Set();
26487
+ if (isNormalExpressionNodeWithName(normalExpressionNode)) {
26488
+ const [, [symbolNode]] = normalExpressionNode;
26489
+ if (isUserDefinedSymbolNode(symbolNode)) {
26490
+ if (contextStack.lookUp(symbolNode) === null) unresolvedSymbols.add(symbolNode[1]);
26491
+ }
26492
+ } else {
26493
+ const [, [expressionNode]] = normalExpressionNode;
26494
+ findUnresolvedSymbolsInNode(expressionNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26495
+ }
26496
+ for (const subNode of normalExpressionNode[1][1]) findUnresolvedSymbolsInNode(subNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26497
+ return unresolvedSymbols;
26498
+ }
26499
+ case NodeTypes.SpecialExpression: {
26500
+ const specialExpressionNode = node;
26501
+ const specialExpressionType = specialExpressionNode[1][0];
26502
+ const castedGetUndefinedSymbols = builtin.specialExpressions[specialExpressionType].getUndefinedSymbols;
26503
+ return castedGetUndefinedSymbols(specialExpressionNode, contextStack, {
26504
+ getUndefinedSymbols: getUndefinedSymbols$1,
26505
+ builtin
26506
+ });
26507
+ }
26508
+ case NodeTypes.Spread: return findUnresolvedSymbolsInNode(node[1], contextStack, builtin);
26659
26509
  default: throw new DvalaError(`Unhandled node type: ${nodeType}`, node[2]);
26660
26510
  }
26661
26511
  }
@@ -27793,7 +27643,7 @@ const SUSPENDED_MESSAGE = "Program suspended";
27793
27643
  * Generate a UUID for identifying a run() or resume() call.
27794
27644
  * Uses crypto.randomUUID() when available, falls back to a simple generator.
27795
27645
  */
27796
- function generateRunId() {
27646
+ function generateUUID() {
27797
27647
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
27798
27648
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27799
27649
  const r = Math.random() * 16 | 0;
@@ -27801,6 +27651,15 @@ function generateRunId() {
27801
27651
  });
27802
27652
  }
27803
27653
  /**
27654
+ * Create a Snapshot with a freshly generated unique `id`.
27655
+ */
27656
+ function createSnapshot(fields) {
27657
+ return {
27658
+ id: generateUUID(),
27659
+ ...fields
27660
+ };
27661
+ }
27662
+ /**
27804
27663
  * Test whether a handler pattern key matches a given effect name.
27805
27664
  *
27806
27665
  * Rules:
@@ -28258,6 +28117,28 @@ function serializeSuspensionBlob(k, snapshots, nextSnapshotIndex, meta) {
28258
28117
  return base;
28259
28118
  }
28260
28119
  /**
28120
+ * Create a terminal snapshot for completed or errored program states.
28121
+ * The continuation is empty (cannot resume), but checkpoints are preserved
28122
+ * for time travel debugging.
28123
+ */
28124
+ function serializeTerminalSnapshot(snapshots, nextSnapshotIndex) {
28125
+ const base = {
28126
+ version: SUSPENSION_VERSION,
28127
+ contextStacks: [],
28128
+ k: []
28129
+ };
28130
+ if (snapshots.length > 0) {
28131
+ base.snapshots = snapshots;
28132
+ const roots = [];
28133
+ for (const snapshot of snapshots) roots.push(snapshot);
28134
+ const { roots: dedupedRoots, pool } = dedupSubTrees(roots, DEFAULT_DEDUP_THRESHOLD);
28135
+ for (let i = 0; i < base.snapshots.length; i++) base.snapshots[i] = dedupedRoots[i];
28136
+ if (Object.keys(pool).length > 0) base.pool = pool;
28137
+ }
28138
+ base.nextSnapshotIndex = nextSnapshotIndex;
28139
+ return base;
28140
+ }
28141
+ /**
28261
28142
  * Deserialize a plain object (as produced by `serializeToObject`) back into
28262
28143
  * a continuation stack and metadata.
28263
28144
  *
@@ -28324,7 +28205,7 @@ function deserializeFromObject(blobData, options) {
28324
28205
  };
28325
28206
  }
28326
28207
  //#endregion
28327
- //#region src/evaluator/trampoline.ts
28208
+ //#region src/evaluator/trampoline-evaluator.ts
28328
28209
  /**
28329
28210
  * Trampoline evaluator — explicit-stack evaluation engine.
28330
28211
  *
@@ -28342,292 +28223,10 @@ function deserializeFromObject(blobData, options) {
28342
28223
  * - `stepNode` is always synchronous and returns `Step`.
28343
28224
  * - `applyFrame` may return `Step | Promise<Step>` when normal expressions
28344
28225
  * or compound function types produce async results.
28345
- * - Normal built-in expressions are called directly with pre-evaluated args
28346
- * (they may still use the old recursive `evaluateNode` internally for
28347
- * higher-order callbacks — suspension through them is deferred).
28348
- * - Binding utilities (`evaluateBindingNodeValues`, `tryMatch`) are called
28349
- * with a recursive `evaluateNode` helper. This is acceptable for Phase 1.
28226
+ * - Normal built-in expressions are called directly with pre-evaluated args.
28227
+ * - All binding and pattern matching use frame-based slot processing.
28350
28228
  * - All state lives in frames (no JS closures) — enabling serialization later.
28351
28229
  */
28352
- function evaluateNodeRecursive(node, contextStack) {
28353
- switch (node[0]) {
28354
- case NodeTypes.Number: return node[1];
28355
- case NodeTypes.String: return node[1];
28356
- case NodeTypes.NormalBuiltinSymbol:
28357
- case NodeTypes.SpecialBuiltinSymbol:
28358
- case NodeTypes.UserDefinedSymbol: return contextStack.evaluateSymbol(node);
28359
- case NodeTypes.ReservedSymbol: return evaluateReservedSymbol(node);
28360
- case NodeTypes.NormalExpression: return chain(evaluateNormalExpressionRecursive(node, contextStack), (resolved) => {
28361
- if (typeof resolved === "number" && Number.isNaN(resolved)) throw new DvalaError("Number is NaN", node[2]);
28362
- return annotate(resolved);
28363
- });
28364
- case NodeTypes.SpecialExpression: {
28365
- const initial = {
28366
- type: "Eval",
28367
- node,
28368
- env: contextStack,
28369
- k: []
28370
- };
28371
- try {
28372
- return annotate(runSyncTrampoline(initial));
28373
- } catch (error) {
28374
- /* v8 ignore next 4 */
28375
- if (error instanceof DvalaError && error.message.includes("Unexpected async operation")) return runAsyncTrampoline({
28376
- type: "Eval",
28377
- node,
28378
- env: contextStack,
28379
- k: []
28380
- }).then((r) => annotate(r));
28381
- throw error;
28382
- }
28383
- }
28384
- default: throw new DvalaError(`${getNodeTypeName(node[0])}-node cannot be evaluated`, node[2]);
28385
- }
28386
- }
28387
- function evaluateParamsRecursive(paramNodes, contextStack) {
28388
- const params = [];
28389
- const placeholders = [];
28390
- return chain(forEachSequential(paramNodes, (paramNode, index) => {
28391
- if (isSpreadNode(paramNode))
28392
- /* v8 ignore start */
28393
- return chain(evaluateNodeRecursive(paramNode[1], contextStack), (spreadValue) => {
28394
- if (Array.isArray(spreadValue)) params.push(...spreadValue);
28395
- else throw new DvalaError(`Spread operator requires an array, got ${valueToString(paramNode)}`, paramNode[2]);
28396
- });
28397
- else if (paramNode[0] === NodeTypes.ReservedSymbol && paramNode[1] === "_") placeholders.push(index);
28398
- else return chain(evaluateNodeRecursive(paramNode, contextStack), (value) => {
28399
- params.push(value);
28400
- });
28401
- }), () => ({
28402
- params,
28403
- placeholders
28404
- }));
28405
- }
28406
- function evaluateNormalExpressionRecursive(node, contextStack) {
28407
- const sourceCodeInfo = node[2];
28408
- return chain(evaluateParamsRecursive(node[1][1], contextStack), ({ params, placeholders }) => {
28409
- if (isNormalExpressionNodeWithName(node)) {
28410
- const nameSymbol = node[1][0];
28411
- if (placeholders.length > 0) return chain(evaluateNodeRecursive(nameSymbol, contextStack), (resolvedFn) => {
28412
- return {
28413
- [FUNCTION_SYMBOL]: true,
28414
- function: asFunctionLike(resolvedFn, sourceCodeInfo),
28415
- functionType: "Partial",
28416
- params,
28417
- placeholders,
28418
- sourceCodeInfo,
28419
- arity: toFixedArity(placeholders.length)
28420
- };
28421
- });
28422
- if (isNormalBuiltinSymbolNode(nameSymbol)) {
28423
- const type = nameSymbol[1];
28424
- const normalExpression = builtin.allNormalExpressions[type];
28425
- if (contextStack.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${normalExpression.name}' in pure mode`, node[2]);
28426
- /* v8 ignore next 3 */
28427
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, node[2]);
28428
- return normalExpression.evaluate(params, node[2], contextStack, { executeFunction: executeFunctionRecursive });
28429
- } else {
28430
- const fn = contextStack.getValue(nameSymbol[1]);
28431
- if (fn !== void 0) return executeFunctionRecursive(asFunctionLike(fn, sourceCodeInfo), params, contextStack, sourceCodeInfo);
28432
- /* v8 ignore next 1 */
28433
- throw new UndefinedSymbolError(nameSymbol[1], node[2]);
28434
- }
28435
- } else {
28436
- const fnNode = node[1][0];
28437
- /* v8 ignore start */
28438
- return chain(evaluateNodeRecursive(fnNode, contextStack), (resolvedFn) => {
28439
- const fn = asFunctionLike(resolvedFn, sourceCodeInfo);
28440
- if (placeholders.length > 0) return {
28441
- [FUNCTION_SYMBOL]: true,
28442
- function: fn,
28443
- functionType: "Partial",
28444
- params,
28445
- placeholders,
28446
- sourceCodeInfo,
28447
- arity: toFixedArity(placeholders.length)
28448
- };
28449
- return executeFunctionRecursive(fn, params, contextStack, sourceCodeInfo);
28450
- });
28451
- }
28452
- });
28453
- }
28454
- function executeFunctionRecursive(fn, params, contextStack, sourceCodeInfo) {
28455
- if (isDvalaFunction(fn)) return executeDvalaFunctionRecursive(fn, params, contextStack, sourceCodeInfo);
28456
- if (Array.isArray(fn)) return evaluateArrayAsFunction(fn, params, sourceCodeInfo);
28457
- if (isObj(fn)) return evaluateObjectAsFunction(fn, params, sourceCodeInfo);
28458
- if (typeof fn === "string") return evaluateStringAsFunction(fn, params, sourceCodeInfo);
28459
- if (isNumber(fn)) return evaluateNumberAsFunction(fn, params, sourceCodeInfo);
28460
- /* v8 ignore next 1 */
28461
- throw new DvalaError("Unexpected function type", sourceCodeInfo);
28462
- }
28463
- /**
28464
- * Execute a DvalaFunction recursively. This is the old-style executor
28465
- * used as a fallback for normal expression callbacks.
28466
- */
28467
- function executeDvalaFunctionRecursive(fn, params, contextStack, sourceCodeInfo) {
28468
- switch (fn.functionType) {
28469
- case "UserDefined": return executeUserDefinedRecursive(fn, params, contextStack, sourceCodeInfo);
28470
- case "Partial": return executePartialRecursive(fn, params, contextStack, sourceCodeInfo);
28471
- case "Comp": return executeCompRecursive(fn, params, contextStack, sourceCodeInfo);
28472
- case "Constantly": return fn.value;
28473
- case "Juxt": return executeJuxtRecursive(fn, params, contextStack, sourceCodeInfo);
28474
- case "Complement": return chain(executeFunctionRecursive(fn.function, params, contextStack, sourceCodeInfo), (result) => !result);
28475
- case "EveryPred": return executeEveryPredRecursive(fn, params, contextStack, sourceCodeInfo);
28476
- case "SomePred": return executeSomePredRecursive(fn, params, contextStack, sourceCodeInfo);
28477
- case "Fnull": return executeFnullRecursive(fn, params, contextStack, sourceCodeInfo);
28478
- case "EffectMatcher": return executeEffectMatcherRecursive(fn, params, sourceCodeInfo);
28479
- case "Builtin": {
28480
- const normalExpression = builtin.allNormalExpressions[fn.normalBuiltinSymbolType];
28481
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, sourceCodeInfo);
28482
- return executeBuiltinRecursive(fn, params, contextStack, sourceCodeInfo);
28483
- }
28484
- case "SpecialBuiltin": return executeSpecialBuiltinRecursive(fn, params, contextStack, sourceCodeInfo);
28485
- case "Module": return executeModuleRecursive(fn, params, contextStack, sourceCodeInfo);
28486
- }
28487
- }
28488
- function executeUserDefinedRecursive(fn, params, contextStack, sourceCodeInfo) {
28489
- function setupAndExecute(currentParams) {
28490
- if (!arityAcceptsMin(fn.arity, currentParams.length)) throw new DvalaError(`Expected ${fn.arity} arguments, got ${currentParams.length}.`, sourceCodeInfo);
28491
- const evaluatedFunction = fn.evaluatedfunction;
28492
- const args = evaluatedFunction[0];
28493
- const nbrOfNonRestArgs = args.filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
28494
- const newContextStack = contextStack.create(fn.evaluatedfunction[2]);
28495
- const newContext = { self: { value: fn } };
28496
- const rest = [];
28497
- let paramSetup = void 0;
28498
- for (let i = 0; i < currentParams.length; i += 1) if (i < nbrOfNonRestArgs) {
28499
- const paramIndex = i;
28500
- paramSetup = chain(paramSetup, () => {
28501
- const param = toAny(currentParams[paramIndex]);
28502
- return chain(evaluateBindingNodeValues(args[paramIndex], param, (node) => evaluateNodeRecursive(node, newContextStack.create(newContext))), (valueRecord) => {
28503
- Object.entries(valueRecord).forEach(([key, value]) => {
28504
- newContext[key] = { value };
28505
- });
28506
- });
28507
- });
28508
- } else rest.push(toAny(currentParams[i]));
28509
- let defaultSetup = void 0;
28510
- for (let i = currentParams.length; i < nbrOfNonRestArgs; i++) {
28511
- const argIndex = i;
28512
- defaultSetup = chain(defaultSetup, () => {
28513
- const arg = args[argIndex];
28514
- return chain(evaluateNodeRecursive(arg[1][1], contextStack.create(newContext)), (defaultValue) => {
28515
- return chain(evaluateBindingNodeValues(arg, defaultValue, (node) => evaluateNodeRecursive(node, contextStack.create(newContext))), (valueRecord) => {
28516
- Object.entries(valueRecord).forEach(([key, value]) => {
28517
- newContext[key] = { value };
28518
- });
28519
- });
28520
- });
28521
- });
28522
- }
28523
- return chain(paramSetup, () => chain(defaultSetup, () => {
28524
- const restArgument = args.find((arg) => arg[0] === bindingTargetTypes.rest);
28525
- return chain(restArgument !== void 0 ? chain(evaluateBindingNodeValues(restArgument, rest, (node) => evaluateNodeRecursive(node, contextStack.create(newContext))), (valueRecord) => {
28526
- Object.entries(valueRecord).forEach(([key, value]) => {
28527
- newContext[key] = { value };
28528
- });
28529
- }) : void 0, () => {
28530
- const newContextStack2 = newContextStack.create(newContext);
28531
- const bodyResult = reduceSequential(evaluatedFunction[1], (_acc, node) => evaluateNodeRecursive(node, newContextStack2), null);
28532
- /* v8 ignore start */
28533
- if (bodyResult instanceof Promise) return bodyResult.catch((error) => {
28534
- if (error instanceof RecurSignal) return setupAndExecute(error.params);
28535
- throw error;
28536
- });
28537
- /* v8 ignore stop */
28538
- return bodyResult;
28539
- });
28540
- }));
28541
- }
28542
- for (;;) try {
28543
- return setupAndExecute(params);
28544
- } catch (error) {
28545
- if (error instanceof RecurSignal) {
28546
- params = error.params;
28547
- continue;
28548
- }
28549
- throw error;
28550
- }
28551
- }
28552
- function executePartialRecursive(fn, params, contextStack, sourceCodeInfo) {
28553
- const actualParams = [...fn.params];
28554
- /* v8 ignore next 3 */
28555
- if (params.length !== fn.placeholders.length) throw new DvalaError(`(partial) expects ${fn.placeholders.length} arguments, got ${params.length}.`, sourceCodeInfo);
28556
- const paramsCopy = [...params];
28557
- for (const placeholderIndex of fn.placeholders) actualParams.splice(placeholderIndex, 0, paramsCopy.shift());
28558
- return executeFunctionRecursive(fn.function, actualParams, contextStack, sourceCodeInfo);
28559
- }
28560
- function executeCompRecursive(fn, params, contextStack, sourceCodeInfo) {
28561
- const { params: f } = fn;
28562
- if (f.length === 0) {
28563
- if (params.length !== 1) throw new DvalaError(`(comp) expects one argument, got ${valueToString(params.length)}.`, sourceCodeInfo);
28564
- return asAny(params[0], sourceCodeInfo);
28565
- }
28566
- let result = params;
28567
- for (let i = f.length - 1; i >= 0; i--) {
28568
- const fun = f[i];
28569
- result = chain(result, (currentParams) => chain(executeFunctionRecursive(asFunctionLike(fun, sourceCodeInfo), currentParams, contextStack, sourceCodeInfo), (r) => [r]));
28570
- }
28571
- return chain(result, (finalArr) => asAny(finalArr[0], sourceCodeInfo));
28572
- }
28573
- function executeJuxtRecursive(fn, params, contextStack, sourceCodeInfo) {
28574
- return mapSequential(fn.params, (fun) => executeFunctionRecursive(asFunctionLike(fun, sourceCodeInfo), params, contextStack, sourceCodeInfo));
28575
- }
28576
- function executeEveryPredRecursive(fn, params, contextStack, sourceCodeInfo) {
28577
- const checks = [];
28578
- for (const f of fn.params) for (const param of params) checks.push(() => executeFunctionRecursive(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
28579
- return reduceSequential(checks, (acc, check) => {
28580
- if (!acc) return false;
28581
- return chain(check(), (result) => !!result);
28582
- }, true);
28583
- }
28584
- function executeSomePredRecursive(fn, params, contextStack, sourceCodeInfo) {
28585
- const checks = [];
28586
- for (const f of fn.params) for (const param of params) checks.push(() => executeFunctionRecursive(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
28587
- return reduceSequential(checks, (acc, check) => {
28588
- if (acc) return true;
28589
- return chain(check(), (result) => !!result);
28590
- }, false);
28591
- }
28592
- function executeFnullRecursive(fn, params, contextStack, sourceCodeInfo) {
28593
- const fnulledParams = params.map((param, index) => param === null ? toAny(fn.params[index]) : param);
28594
- return executeFunctionRecursive(asFunctionLike(fn.function, sourceCodeInfo), fnulledParams, contextStack, sourceCodeInfo);
28595
- }
28596
- function executeEffectMatcherRecursive(fn, params, sourceCodeInfo) {
28597
- assertNumberOfParams({
28598
- min: 1,
28599
- max: 1
28600
- }, params.length, fn.sourceCodeInfo ?? sourceCodeInfo);
28601
- const effectRef = params[0];
28602
- assertEffect(effectRef, sourceCodeInfo);
28603
- const effectName = effectRef.name;
28604
- if (fn.matchType === "string") return effectNameMatchesPattern(effectName, fn.pattern);
28605
- return new RegExp(fn.pattern, fn.flags).test(effectName);
28606
- }
28607
- function executeBuiltinRecursive(fn, params, contextStack, sourceCodeInfo) {
28608
- const normalExpression = asNonUndefined(builtin.allNormalExpressions[fn.normalBuiltinSymbolType], sourceCodeInfo);
28609
- /* v8 ignore next 6 */
28610
- if (contextStack.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${fn.name}' in pure mode`, sourceCodeInfo);
28611
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, sourceCodeInfo);
28612
- return normalExpression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28613
- }
28614
- /* v8 ignore start */
28615
- function executeSpecialBuiltinRecursive(fn, params, contextStack, sourceCodeInfo) {
28616
- const specialExpression = asNonUndefined(builtin.specialExpressions[fn.specialBuiltinSymbolType], sourceCodeInfo);
28617
- if (specialExpression.evaluateAsNormalExpression) return specialExpression.evaluateAsNormalExpression(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28618
- throw new DvalaError(`Special builtin function ${fn.specialBuiltinSymbolType} is not supported as normal expression.`, sourceCodeInfo);
28619
- }
28620
- function executeModuleRecursive(fn, params, contextStack, sourceCodeInfo) {
28621
- const dvalaModule = contextStack.getModule(fn.moduleName);
28622
- if (!dvalaModule) throw new DvalaError(`Module '${fn.moduleName}' not found.`, sourceCodeInfo);
28623
- const expression = dvalaModule.functions[fn.functionName];
28624
- if (!expression) throw new DvalaError(`Function '${fn.functionName}' not found in module '${fn.moduleName}'.`, sourceCodeInfo);
28625
- if (contextStack.pure && expression.pure === false) throw new DvalaError(`Cannot call impure function '${fn.functionName}' in pure mode`, sourceCodeInfo);
28626
- assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
28627
- if (expression.dvalaImpl) return executeUserDefinedRecursive(expression.dvalaImpl, params, contextStack, sourceCodeInfo);
28628
- return expression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28629
- }
28630
- /* v8 ignore stop */
28631
28230
  function evaluateObjectAsFunction(fn, params, sourceCodeInfo) {
28632
28231
  if (params.length !== 1) throw new DvalaError("Object as function requires one string parameter.", sourceCodeInfo);
28633
28232
  const key = params[0];
@@ -28675,7 +28274,7 @@ function evaluateFunction(fn, contextStack) {
28675
28274
  });
28676
28275
  return ctx;
28677
28276
  }, {});
28678
- getUndefinedSymbols$1(fn[1], contextStack.new(context), builtin, evaluateNodeRecursive).forEach((name) => {
28277
+ getUndefinedSymbols$1(fn[1], contextStack.new(context), builtin).forEach((name) => {
28679
28278
  const value = contextStack.getValue(name);
28680
28279
  if (isAny(value)) functionContext[name] = { value };
28681
28280
  });
@@ -28948,26 +28547,34 @@ function stepSpecialExpression(node, env, k) {
28948
28547
  const nodes = node[1][1];
28949
28548
  const withHandlerNodes = node[1][2];
28950
28549
  const newEnv = env.create({});
28951
- let bodyK = k;
28952
- if (withHandlerNodes && withHandlerNodes.length > 0) bodyK = [{
28953
- type: "TryWith",
28954
- handlers: withHandlerNodes.map(([effectExpr, handlerNode]) => ({
28955
- effectRef: evaluateNodeRecursive(effectExpr, env),
28956
- handlerNode
28957
- })),
28958
- env,
28959
- sourceCodeInfo
28960
- }, ...k];
28550
+ if (withHandlerNodes && withHandlerNodes.length > 0) {
28551
+ const effectRefFrame = {
28552
+ type: "EffectRef",
28553
+ handlerNodes: withHandlerNodes,
28554
+ evaluatedHandlers: [],
28555
+ index: 0,
28556
+ bodyNodes: nodes,
28557
+ bodyEnv: newEnv,
28558
+ env,
28559
+ sourceCodeInfo
28560
+ };
28561
+ return {
28562
+ type: "Eval",
28563
+ node: withHandlerNodes[0][0],
28564
+ env,
28565
+ k: [effectRefFrame, ...k]
28566
+ };
28567
+ }
28961
28568
  if (nodes.length === 0) return {
28962
28569
  type: "Value",
28963
28570
  value: null,
28964
- k: bodyK
28571
+ k
28965
28572
  };
28966
28573
  if (nodes.length === 1) return {
28967
28574
  type: "Eval",
28968
28575
  node: nodes[0],
28969
28576
  env: newEnv,
28970
- k: bodyK
28577
+ k
28971
28578
  };
28972
28579
  const frame = {
28973
28580
  type: "Sequence",
@@ -28980,7 +28587,7 @@ function stepSpecialExpression(node, env, k) {
28980
28587
  type: "Eval",
28981
28588
  node: nodes[0],
28982
28589
  env: newEnv,
28983
- k: [frame, ...bodyK]
28590
+ k: [frame, ...k]
28984
28591
  };
28985
28592
  }
28986
28593
  case specialExpressionTypes.let: {
@@ -29335,7 +28942,7 @@ function dispatchCall(frame, k) {
29335
28942
  if (env.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${normalExpression.name}' in pure mode`, sourceCodeInfo);
29336
28943
  /* v8 ignore next 3 */
29337
28944
  if (normalExpression.dvalaImpl) return setupUserDefinedCall(normalExpression.dvalaImpl, params, env, sourceCodeInfo, k);
29338
- return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env, { executeFunction: executeFunctionRecursive }), k);
28945
+ return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env), k);
29339
28946
  }
29340
28947
  const fn = env.getValue(nameSymbol[1]);
29341
28948
  if (fn !== void 0) return dispatchFunction(asFunctionLike(fn, sourceCodeInfo), params, placeholders, env, sourceCodeInfo, k);
@@ -29396,79 +29003,219 @@ function dispatchFunction(fn, params, placeholders, env, sourceCodeInfo, k) {
29396
29003
  }
29397
29004
  /**
29398
29005
  * Dispatch a DvalaFunction. User-defined functions are set up with frames;
29399
- * compound function types (Comp, Juxt, etc.) use the recursive executor.
29006
+ * some compound function types still use the recursive executor for iteration.
29400
29007
  */
29401
29008
  function dispatchDvalaFunction(fn, params, env, sourceCodeInfo, k) {
29402
29009
  switch (fn.functionType) {
29403
29010
  case "UserDefined": return setupUserDefinedCall(fn, params, env, sourceCodeInfo, k);
29404
- case "Partial":
29405
- case "Comp":
29406
- case "Constantly":
29407
- case "Juxt":
29408
- case "Complement":
29409
- case "EveryPred":
29410
- case "SomePred":
29411
- case "Fnull":
29412
- case "EffectMatcher":
29413
- case "SpecialBuiltin": return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
29414
- case "Module": {
29415
- const expression = env.getModule(fn.moduleName)?.functions[fn.functionName];
29416
- if (expression?.dvalaImpl) {
29417
- assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
29418
- return setupUserDefinedCall(expression.dvalaImpl, params, env, sourceCodeInfo, k);
29419
- }
29420
- return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
29011
+ case "Constantly": return {
29012
+ type: "Value",
29013
+ value: fn.value,
29014
+ k
29015
+ };
29016
+ case "EffectMatcher": {
29017
+ assertNumberOfParams({
29018
+ min: 1,
29019
+ max: 1
29020
+ }, params.length, fn.sourceCodeInfo ?? sourceCodeInfo);
29021
+ const effectRef = params[0];
29022
+ assertEffect(effectRef, sourceCodeInfo);
29023
+ const effectName = effectRef.name;
29024
+ if (fn.matchType === "string") return {
29025
+ type: "Value",
29026
+ value: effectNameMatchesPattern(effectName, fn.pattern),
29027
+ k
29028
+ };
29029
+ return {
29030
+ type: "Value",
29031
+ value: new RegExp(fn.pattern, fn.flags).test(effectName),
29032
+ k
29033
+ };
29421
29034
  }
29422
- case "Builtin": {
29035
+ case "Partial": {
29036
+ const actualParams = [...fn.params];
29037
+ if (params.length !== fn.placeholders.length) throw new DvalaError(`(partial) expects ${fn.placeholders.length} arguments, got ${params.length}.`, sourceCodeInfo);
29038
+ const paramsCopy = [...params];
29039
+ for (const placeholderIndex of fn.placeholders) actualParams.splice(placeholderIndex, 0, paramsCopy.shift());
29040
+ return dispatchFunction(fn.function, actualParams, [], env, sourceCodeInfo, k);
29041
+ }
29042
+ case "Fnull": {
29043
+ const fnulledParams = params.map((param, index) => param === null ? toAny(fn.params[index]) : param);
29044
+ return dispatchFunction(fn.function, fnulledParams, [], env, sourceCodeInfo, k);
29045
+ }
29046
+ case "Complement": {
29047
+ const frame = {
29048
+ type: "Complement",
29049
+ sourceCodeInfo
29050
+ };
29051
+ return dispatchFunction(fn.function, params, [], env, sourceCodeInfo, [frame, ...k]);
29052
+ }
29053
+ case "Comp": {
29054
+ const fns = fn.params;
29055
+ if (fns.length === 0) {
29056
+ if (params.length !== 1) throw new DvalaError(`(comp) expects one argument, got ${valueToString(params.length)}.`, sourceCodeInfo);
29057
+ return {
29058
+ type: "Value",
29059
+ value: asAny(params[0], sourceCodeInfo),
29060
+ k
29061
+ };
29062
+ }
29063
+ const startIndex = fns.length - 1;
29064
+ const frame = {
29065
+ type: "Comp",
29066
+ fns,
29067
+ index: startIndex - 1,
29068
+ env,
29069
+ sourceCodeInfo
29070
+ };
29071
+ return dispatchFunction(asFunctionLike(fns[startIndex], sourceCodeInfo), params, [], env, sourceCodeInfo, [frame, ...k]);
29072
+ }
29073
+ case "Juxt": {
29074
+ const fns = fn.params;
29075
+ if (fns.length === 0) return {
29076
+ type: "Value",
29077
+ value: [],
29078
+ k
29079
+ };
29080
+ const frame = {
29081
+ type: "Juxt",
29082
+ fns,
29083
+ params,
29084
+ index: 1,
29085
+ results: [],
29086
+ env,
29087
+ sourceCodeInfo
29088
+ };
29089
+ return dispatchFunction(asFunctionLike(fns[0], sourceCodeInfo), params, [], env, sourceCodeInfo, [frame, ...k]);
29090
+ }
29091
+ case "EveryPred": {
29092
+ const checks = [];
29093
+ for (const f of fn.params) for (const p of params) checks.push({
29094
+ fn: asFunctionLike(f, sourceCodeInfo),
29095
+ param: p
29096
+ });
29097
+ if (checks.length === 0) return {
29098
+ type: "Value",
29099
+ value: true,
29100
+ k
29101
+ };
29102
+ const frame = {
29103
+ type: "EveryPred",
29104
+ checks,
29105
+ index: 1,
29106
+ env,
29107
+ sourceCodeInfo
29108
+ };
29109
+ const firstCheck = checks[0];
29110
+ return dispatchFunction(firstCheck.fn, [firstCheck.param], [], env, sourceCodeInfo, [frame, ...k]);
29111
+ }
29112
+ case "SomePred": {
29113
+ const checks = [];
29114
+ for (const f of fn.params) for (const p of params) checks.push({
29115
+ fn: asFunctionLike(f, sourceCodeInfo),
29116
+ param: p
29117
+ });
29118
+ if (checks.length === 0) return {
29119
+ type: "Value",
29120
+ value: false,
29121
+ k
29122
+ };
29123
+ const frame = {
29124
+ type: "SomePred",
29125
+ checks,
29126
+ index: 1,
29127
+ env,
29128
+ sourceCodeInfo
29129
+ };
29130
+ const firstCheck = checks[0];
29131
+ return dispatchFunction(firstCheck.fn, [firstCheck.param], [], env, sourceCodeInfo, [frame, ...k]);
29132
+ }
29133
+ case "SpecialBuiltin": {
29134
+ const specialExpression = asNonUndefined(builtin.specialExpressions[fn.specialBuiltinSymbolType], sourceCodeInfo);
29135
+ if (specialExpression.evaluateAsNormalExpression) return wrapMaybePromiseAsStep(specialExpression.evaluateAsNormalExpression(params, sourceCodeInfo, env), k);
29136
+ throw new DvalaError(`Special builtin function ${fn.specialBuiltinSymbolType} is not supported as normal expression.`, sourceCodeInfo);
29137
+ }
29138
+ case "Module": {
29139
+ const dvalaModule = env.getModule(fn.moduleName);
29140
+ if (!dvalaModule) throw new DvalaError(`Module '${fn.moduleName}' not found.`, sourceCodeInfo);
29141
+ const expression = dvalaModule.functions[fn.functionName];
29142
+ if (!expression) throw new DvalaError(`Function '${fn.functionName}' not found in module '${fn.moduleName}'.`, sourceCodeInfo);
29143
+ if (env.pure && expression.pure === false) throw new DvalaError(`Cannot call impure function '${fn.functionName}' in pure mode`, sourceCodeInfo);
29144
+ assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
29145
+ if (expression.dvalaImpl) return setupUserDefinedCall(expression.dvalaImpl, params, env, sourceCodeInfo, k);
29146
+ return wrapMaybePromiseAsStep(expression.evaluate(params, sourceCodeInfo, env), k);
29147
+ }
29148
+ case "Builtin": {
29423
29149
  const normalExpression = builtin.allNormalExpressions[fn.normalBuiltinSymbolType];
29150
+ if (env.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${normalExpression.name}' in pure mode`, sourceCodeInfo);
29424
29151
  if (normalExpression.dvalaImpl) return setupUserDefinedCall(normalExpression.dvalaImpl, params, env, sourceCodeInfo, k);
29425
- return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
29152
+ return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env), k);
29426
29153
  }
29427
29154
  }
29428
29155
  }
29429
29156
  /**
29430
29157
  * Set up a user-defined function call: bind params, push FnBodyFrame.
29431
29158
  *
29432
- * For Phase 1, parameter binding (including destructuring defaults) is done
29433
- * synchronously via evaluateBindingNodeValues with the recursive evaluator.
29434
- * This will be converted to use frames in a later phase.
29159
+ * Uses frame-based binding slots for all argument binding, enabling
29160
+ * suspension/serialization at any point during destructuring.
29435
29161
  */
29436
29162
  function setupUserDefinedCall(fn, params, env, sourceCodeInfo, k) {
29437
29163
  if (!arityAcceptsMin(fn.arity, params.length)) throw new DvalaError(`Expected ${fn.arity} arguments, got ${params.length}.`, sourceCodeInfo);
29164
+ const nbrOfNonRestArgs = fn.evaluatedfunction[0].filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
29165
+ return continueArgSlotBinding(fn, params, 0, nbrOfNonRestArgs, { self: { value: fn } }, env, sourceCodeInfo, k);
29166
+ }
29167
+ /**
29168
+ * Continue binding function arguments using slot-based binding.
29169
+ * Handles provided args, defaults, rest, then proceeds to body.
29170
+ */
29171
+ function continueArgSlotBinding(fn, params, argIndex, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k) {
29438
29172
  const evaluatedFunc = fn.evaluatedfunction;
29439
29173
  const args = evaluatedFunc[0];
29440
- const nbrOfNonRestArgs = args.filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
29441
- const newContextStack = env.create(fn.evaluatedfunction[2]);
29442
- const newContext = { self: { value: fn } };
29443
- const rest = [];
29444
- for (let i = 0; i < params.length; i += 1) if (i < nbrOfNonRestArgs) {
29445
- const param = toAny(params[i]);
29446
- const valueRecord = evaluateBindingNodeValues(args[i], param, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29447
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29448
- Object.entries(valueRecord).forEach(([key, value]) => {
29449
- newContext[key] = { value };
29450
- });
29451
- } else rest.push(toAny(params[i]));
29452
- for (let i = params.length; i < nbrOfNonRestArgs; i++) {
29453
- const arg = args[i];
29454
- const defaultValue = evaluateNodeRecursive(arg[1][1], newContextStack.create(newContext));
29455
- if (defaultValue instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29456
- const valueRecord = evaluateBindingNodeValues(arg, defaultValue, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29457
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29458
- Object.entries(valueRecord).forEach(([key, value]) => {
29459
- newContext[key] = { value };
29460
- });
29174
+ const closureContext = evaluatedFunc[2];
29175
+ const bindingEnv = outerEnv.create(closureContext).create(context);
29176
+ if (argIndex < params.length && argIndex < nbrOfNonRestArgs) {
29177
+ const param = toAny(params[argIndex]);
29178
+ const argTarget = args[argIndex];
29179
+ return startBindingSlots(argTarget, param, bindingEnv, sourceCodeInfo, [{
29180
+ type: "FnArgSlotComplete",
29181
+ fn,
29182
+ params,
29183
+ argIndex,
29184
+ nbrOfNonRestArgs,
29185
+ context,
29186
+ outerEnv,
29187
+ sourceCodeInfo
29188
+ }, ...k]);
29461
29189
  }
29190
+ if (argIndex < nbrOfNonRestArgs) return continueBindingArgs(fn, params, argIndex, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k);
29191
+ return handleRestArgAndBody(fn, params, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k);
29192
+ }
29193
+ /**
29194
+ * Handle rest argument binding and proceed to body evaluation.
29195
+ */
29196
+ function handleRestArgAndBody(fn, params, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k) {
29197
+ const evaluatedFunc = fn.evaluatedfunction;
29198
+ const args = evaluatedFunc[0];
29199
+ const closureContext = evaluatedFunc[2];
29200
+ const bindingEnv = outerEnv.create(closureContext).create(context);
29201
+ const rest = params.slice(nbrOfNonRestArgs).map(toAny);
29462
29202
  const restArgument = args.find((arg) => arg[0] === bindingTargetTypes.rest);
29463
- if (restArgument) {
29464
- const valueRecord = evaluateBindingNodeValues(restArgument, rest, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29465
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29466
- Object.entries(valueRecord).forEach(([key, value]) => {
29467
- newContext[key] = { value };
29468
- });
29469
- }
29470
- const bodyNodes = evaluatedFunc[1];
29471
- const bodyEnv = newContextStack.create(newContext);
29203
+ if (restArgument) return startBindingSlots(restArgument, rest, bindingEnv, sourceCodeInfo, [{
29204
+ type: "FnRestArgComplete",
29205
+ fn,
29206
+ context,
29207
+ outerEnv,
29208
+ sourceCodeInfo
29209
+ }, ...k]);
29210
+ return proceedToFnBody(fn, context, outerEnv, sourceCodeInfo, k);
29211
+ }
29212
+ /**
29213
+ * Start evaluating function body.
29214
+ */
29215
+ function proceedToFnBody(fn, context, outerEnv, sourceCodeInfo, k) {
29216
+ const closureContext = fn.evaluatedfunction[2];
29217
+ const bodyEnv = outerEnv.create(closureContext).create(context);
29218
+ const bodyNodes = fn.evaluatedfunction[1];
29472
29219
  if (bodyNodes.length === 0) return {
29473
29220
  type: "Value",
29474
29221
  value: null,
@@ -29479,15 +29226,9 @@ function setupUserDefinedCall(fn, params, env, sourceCodeInfo, k) {
29479
29226
  fn,
29480
29227
  bodyIndex: 1,
29481
29228
  env: bodyEnv,
29482
- outerEnv: env,
29229
+ outerEnv,
29483
29230
  sourceCodeInfo
29484
29231
  };
29485
- if (bodyNodes.length === 1) return {
29486
- type: "Eval",
29487
- node: bodyNodes[0],
29488
- env: bodyEnv,
29489
- k: [fnBodyFrame, ...k]
29490
- };
29491
29232
  return {
29492
29233
  type: "Eval",
29493
29234
  node: bodyNodes[0],
@@ -29511,10 +29252,15 @@ function applyFrame(frame, value, k) {
29511
29252
  case "ArrayBuild": return applyArrayBuild(frame, value, k);
29512
29253
  case "ObjectBuild": return applyObjectBuild(frame, value, k);
29513
29254
  case "LetBind": return applyLetBind(frame, value, k);
29255
+ case "LetBindComplete": return applyLetBindComplete(frame, value, k);
29514
29256
  case "LoopBind": return applyLoopBind(frame, value, k);
29257
+ case "LoopBindComplete": return applyLoopBindComplete(frame, value, k);
29515
29258
  case "LoopIterate": return applyLoopIterate(frame, value, k);
29516
29259
  case "ForLoop": return applyForLoop(frame, value, k);
29260
+ case "ForElementBindComplete": return applyForElementBindComplete(frame, value, k);
29261
+ case "ForLetBind": return applyForLetBind(frame, value, k);
29517
29262
  case "Recur": return applyRecur(frame, value, k);
29263
+ case "RecurLoopRebind": return applyRecurLoopRebind(frame, value, k);
29518
29264
  case "PerformArgs": return applyPerformArgs(frame, value, k);
29519
29265
  case "TryWith": return applyTryWith(value, k);
29520
29266
  case "EffectResume": return applyEffectResume(frame, value, k);
@@ -29522,7 +29268,22 @@ function applyFrame(frame, value, k) {
29522
29268
  case "EvalArgs": return applyEvalArgs(frame, value, k);
29523
29269
  case "CallFn": return applyCallFn(frame, value, k);
29524
29270
  case "FnBody": return applyFnBody(frame, value, k);
29525
- case "BindingDefault": return applyBindingDefault(frame, value, k);
29271
+ case "FnArgBind": return applyFnArgBind(frame, value, k);
29272
+ case "FnArgSlotComplete": return applyFnArgSlotComplete(frame, value, k);
29273
+ case "FnRestArgComplete": return applyFnRestArgComplete(frame, value, k);
29274
+ case "BindingSlot": return applyBindingSlot(frame, value, k);
29275
+ case "MatchSlot": return applyMatchSlot(frame, value, k);
29276
+ case "EffectRef": return applyEffectRef(frame, value, k);
29277
+ case "HandlerInvoke": return applyHandlerInvoke(frame, value, k);
29278
+ case "Complement": return {
29279
+ type: "Value",
29280
+ value: !value,
29281
+ k
29282
+ };
29283
+ case "Comp": return applyComp(frame, value, k);
29284
+ case "Juxt": return applyJuxt(frame, value, k);
29285
+ case "EveryPred": return applyEveryPred(frame, value, k);
29286
+ case "SomePred": return applySomePred(frame, value, k);
29526
29287
  case "NanCheck": return applyNanCheck(frame, value, k);
29527
29288
  case "DebugStep": return applyDebugStep(frame, value, k);
29528
29289
  case "ImportMerge": {
@@ -29658,44 +29419,17 @@ function applyMatch(frame, value, k) {
29658
29419
  }
29659
29420
  /**
29660
29421
  * Process match cases starting from `frame.index`.
29661
- * Uses recursive tryMatch with evaluateNodeRecursive for pattern matching.
29422
+ * Uses frame-based slot processing for pattern matching.
29662
29423
  */
29663
29424
  function processMatchCase(frame, k) {
29664
29425
  const { matchValue, cases, index, env, sourceCodeInfo } = frame;
29665
- for (let i = index; i < cases.length; i++) {
29666
- const [pattern, body, guard] = cases[i];
29667
- const bindings = tryMatch(pattern, matchValue, (n) => evaluateNodeRecursive(n, env));
29668
- if (bindings instanceof Promise) throw new DvalaError("Async pattern matching not supported in trampoline yet", sourceCodeInfo);
29669
- if (bindings === null) continue;
29670
- if (guard) {
29671
- const context = {};
29672
- for (const [name, val] of Object.entries(bindings)) context[name] = { value: val };
29673
- return {
29674
- type: "Eval",
29675
- node: guard,
29676
- env: env.create(context),
29677
- k: [{
29678
- ...frame,
29679
- phase: "guard",
29680
- index: i,
29681
- bindings
29682
- }, ...k]
29683
- };
29684
- }
29685
- const context = {};
29686
- for (const [name, val] of Object.entries(bindings)) context[name] = { value: val };
29687
- return {
29688
- type: "Eval",
29689
- node: body,
29690
- env: env.create(context),
29691
- k
29692
- };
29693
- }
29694
- return {
29426
+ if (index >= cases.length) return {
29695
29427
  type: "Value",
29696
29428
  value: null,
29697
29429
  k
29698
29430
  };
29431
+ const [pattern] = cases[index];
29432
+ return startMatchSlots(pattern, matchValue, frame, env, sourceCodeInfo, k);
29699
29433
  }
29700
29434
  function applyAnd(frame, value, k) {
29701
29435
  if (!value) return {
@@ -29892,50 +29626,74 @@ function applyObjectBuild(frame, value, k) {
29892
29626
  }
29893
29627
  function applyLetBind(frame, value, k) {
29894
29628
  const { target, env, sourceCodeInfo } = frame;
29895
- return chain(evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env)), (br) => {
29896
- env.addValues(br, sourceCodeInfo);
29897
- return {
29898
- type: "Value",
29899
- value,
29900
- k
29901
- };
29902
- });
29629
+ return startBindingSlots(target, value, env, sourceCodeInfo, [{
29630
+ type: "LetBindComplete",
29631
+ originalValue: value,
29632
+ env,
29633
+ sourceCodeInfo
29634
+ }, ...k]);
29635
+ }
29636
+ function applyLetBindComplete(frame, record, k) {
29637
+ const { originalValue, env, sourceCodeInfo } = frame;
29638
+ env.addValues(record, sourceCodeInfo);
29639
+ return {
29640
+ type: "Value",
29641
+ value: originalValue,
29642
+ k
29643
+ };
29903
29644
  }
29904
29645
  function applyLoopBind(frame, value, k) {
29905
29646
  const { bindingNodes, index, context, body, env, sourceCodeInfo } = frame;
29906
29647
  const target = bindingNodes[index][1][0];
29907
- return chain(evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env.create(context))), (vr) => {
29908
- Object.entries(vr).forEach(([name, val]) => {
29909
- context[name] = { value: val };
29910
- });
29911
- const nextIndex = index + 1;
29912
- if (nextIndex >= bindingNodes.length) {
29913
- const loopEnv = env.create(context);
29914
- return {
29915
- type: "Eval",
29916
- node: body,
29917
- env: loopEnv,
29918
- k: [{
29919
- type: "LoopIterate",
29920
- bindingNodes,
29921
- bindingContext: context,
29922
- body,
29923
- env: loopEnv,
29924
- sourceCodeInfo
29925
- }, ...k]
29926
- };
29927
- }
29928
- const newFrame = {
29929
- ...frame,
29930
- index: nextIndex
29931
- };
29648
+ const completeFrame = {
29649
+ type: "LoopBindComplete",
29650
+ bindingNodes,
29651
+ index,
29652
+ context,
29653
+ body,
29654
+ env,
29655
+ sourceCodeInfo
29656
+ };
29657
+ return startBindingSlots(target, value, env.create(context), sourceCodeInfo, [completeFrame, ...k]);
29658
+ }
29659
+ function applyLoopBindComplete(frame, record, k) {
29660
+ const { bindingNodes, index, context, body, env, sourceCodeInfo } = frame;
29661
+ Object.entries(record).forEach(([name, val]) => {
29662
+ context[name] = { value: val };
29663
+ });
29664
+ const nextIndex = index + 1;
29665
+ if (nextIndex >= bindingNodes.length) {
29666
+ const loopEnv = env.create(context);
29932
29667
  return {
29933
29668
  type: "Eval",
29934
- node: bindingNodes[nextIndex][1][1],
29935
- env: env.create(context),
29936
- k: [newFrame, ...k]
29669
+ node: body,
29670
+ env: loopEnv,
29671
+ k: [{
29672
+ type: "LoopIterate",
29673
+ bindingNodes,
29674
+ bindingContext: context,
29675
+ body,
29676
+ env: loopEnv,
29677
+ sourceCodeInfo
29678
+ }, ...k]
29937
29679
  };
29938
- });
29680
+ }
29681
+ const newFrame = {
29682
+ type: "LoopBind",
29683
+ phase: "value",
29684
+ bindingNodes,
29685
+ index: nextIndex,
29686
+ context,
29687
+ body,
29688
+ env,
29689
+ sourceCodeInfo
29690
+ };
29691
+ return {
29692
+ type: "Eval",
29693
+ node: bindingNodes[nextIndex][1][1],
29694
+ env: env.create(context),
29695
+ k: [newFrame, ...k]
29696
+ };
29939
29697
  }
29940
29698
  function applyLoopIterate(_frame, value, k) {
29941
29699
  return {
@@ -29945,7 +29703,7 @@ function applyLoopIterate(_frame, value, k) {
29945
29703
  };
29946
29704
  }
29947
29705
  function applyForLoop(frame, value, k) {
29948
- const { returnResult, bindingNodes, result, env, sourceCodeInfo, context } = frame;
29706
+ const { returnResult, bindingNodes, result, env, sourceCodeInfo } = frame;
29949
29707
  const { asColl, isSeq } = getCollectionUtils();
29950
29708
  switch (frame.phase) {
29951
29709
  case "evalCollection": {
@@ -29957,21 +29715,19 @@ function applyForLoop(frame, value, k) {
29957
29715
  collection: seq,
29958
29716
  index: 0
29959
29717
  };
29960
- const binding = bindingNodes[frame.bindingLevel];
29961
- const targetNode = binding[0][1][0];
29718
+ const targetNode = bindingNodes[frame.bindingLevel][0][1][0];
29962
29719
  const element = seq[0];
29963
- return chain(evaluateBindingNodeValues(targetNode, asAny(element, sourceCodeInfo), (n) => evaluateNodeRecursive(n, env)), (vr) => {
29964
- Object.entries(vr).forEach(([name, val]) => {
29965
- context[name] = { value: val };
29966
- });
29967
- const letBindings = binding[1];
29968
- if (letBindings.length > 0) return processForLetBindings(frame, levelStates, letBindings, 0, k);
29969
- return processForGuards(frame, levelStates, k);
29970
- });
29720
+ return startBindingSlots(targetNode, asAny(element, sourceCodeInfo), env, sourceCodeInfo, [{
29721
+ type: "ForElementBindComplete",
29722
+ forFrame: {
29723
+ ...frame,
29724
+ levelStates
29725
+ },
29726
+ levelStates,
29727
+ env,
29728
+ sourceCodeInfo
29729
+ }, ...k]);
29971
29730
  }
29972
- case "evalLet":
29973
- /* v8 ignore next 1 */
29974
- throw new DvalaError("ForLoop evalLet should not reach applyFrame", sourceCodeInfo);
29975
29731
  case "evalWhen": {
29976
29732
  if (!value) return advanceForElement(frame, k);
29977
29733
  const whileNode = bindingNodes[frame.bindingLevel][3];
@@ -30002,14 +29758,7 @@ function applyForLoop(frame, value, k) {
30002
29758
  case "evalBody":
30003
29759
  if (returnResult) result.push(value);
30004
29760
  return advanceForElement(frame, k);
30005
- case "evalElement": throw new DvalaError(`Unexpected ForLoop phase: ${frame.phase}`, sourceCodeInfo);
30006
29761
  }
30007
- /* v8 ignore next 1 */
30008
- return {
30009
- type: "Value",
30010
- value: null,
30011
- k
30012
- };
30013
29762
  }
30014
29763
  /** Handle for-loop abort: no more elements at the outermost level. */
30015
29764
  function handleForAbort(frame, k) {
@@ -30021,7 +29770,7 @@ function handleForAbort(frame, k) {
30021
29770
  }
30022
29771
  /** Advance to the next element at the current binding level. */
30023
29772
  function advanceForElement(frame, k) {
30024
- const { bindingNodes, env, sourceCodeInfo, context } = frame;
29773
+ const { bindingNodes, env, sourceCodeInfo } = frame;
30025
29774
  const levelStates = [...frame.levelStates];
30026
29775
  const currentLevel = frame.bindingLevel;
30027
29776
  const currentState = levelStates[currentLevel];
@@ -30037,47 +29786,71 @@ function advanceForElement(frame, k) {
30037
29786
  ...currentState,
30038
29787
  index: nextElementIndex
30039
29788
  };
30040
- const binding = bindingNodes[currentLevel];
30041
- const targetNode = binding[0][1][0];
29789
+ const targetNode = bindingNodes[currentLevel][0][1][0];
30042
29790
  const element = currentState.collection[nextElementIndex];
30043
- return chain(evaluateBindingNodeValues(targetNode, asAny(element, sourceCodeInfo), (n) => evaluateNodeRecursive(n, env)), (vr) => {
30044
- Object.entries(vr).forEach(([name, val]) => {
30045
- context[name] = { value: val };
30046
- });
30047
- const letBindings = binding[1];
30048
- if (letBindings.length > 0) return processForLetBindings({
29791
+ return startBindingSlots(targetNode, asAny(element, sourceCodeInfo), env, sourceCodeInfo, [{
29792
+ type: "ForElementBindComplete",
29793
+ forFrame: {
30049
29794
  ...frame,
30050
29795
  levelStates,
30051
29796
  bindingLevel: currentLevel
30052
- }, levelStates, letBindings, 0, k);
30053
- return processForGuards({
30054
- ...frame,
30055
- levelStates,
30056
- bindingLevel: currentLevel
30057
- }, levelStates, k);
29797
+ },
29798
+ levelStates,
29799
+ env,
29800
+ sourceCodeInfo
29801
+ }, ...k]);
29802
+ }
29803
+ /** Handle completion of for-loop element binding. */
29804
+ function applyForElementBindComplete(frame, record, k) {
29805
+ const { forFrame, levelStates, env, sourceCodeInfo } = frame;
29806
+ Object.entries(record).forEach(([name, val]) => {
29807
+ forFrame.context[name] = { value: val };
30058
29808
  });
29809
+ const letBindings = forFrame.bindingNodes[forFrame.bindingLevel][1];
29810
+ if (letBindings.length > 0) return startForLetBindings(forFrame, levelStates, letBindings, 0, env, sourceCodeInfo, k);
29811
+ return processForGuards(forFrame, levelStates, k);
30059
29812
  }
30060
- /** Process let-bindings at the current for-loop level. */
30061
- function processForLetBindings(frame, levelStates, letBindings, letIndex, k) {
30062
- const { env, context } = frame;
30063
- let result = void 0;
30064
- for (let i = letIndex; i < letBindings.length; i++) {
30065
- const bindingIndex = i;
30066
- result = chain(result, () => {
30067
- const [target, bindingValue] = letBindings[bindingIndex][1];
30068
- return chain(evaluateNodeRecursive(bindingValue, env), (v) => {
30069
- return chain(evaluateBindingNodeValues(target, v, (n) => evaluateNodeRecursive(n, env)), (vr) => {
30070
- Object.entries(vr).forEach(([name, value]) => {
30071
- context[name] = { value };
30072
- });
30073
- });
30074
- });
30075
- });
29813
+ /** Start processing let-bindings at the current for-loop level. */
29814
+ function startForLetBindings(forFrame, levelStates, letBindings, letIndex, env, sourceCodeInfo, k) {
29815
+ return {
29816
+ type: "Eval",
29817
+ node: letBindings[letIndex][1][1],
29818
+ env,
29819
+ k: [{
29820
+ type: "ForLetBind",
29821
+ phase: "evalValue",
29822
+ forFrame,
29823
+ levelStates,
29824
+ letBindings,
29825
+ letIndex,
29826
+ env,
29827
+ sourceCodeInfo
29828
+ }, ...k]
29829
+ };
29830
+ }
29831
+ /** Handle continuation after evaluating a for-loop let-binding value or destructuring. */
29832
+ function applyForLetBind(frame, value, k) {
29833
+ const { phase, forFrame, levelStates, letBindings, letIndex, env, sourceCodeInfo } = frame;
29834
+ if (phase === "evalValue") {
29835
+ const target = letBindings[letIndex][1][0];
29836
+ return startBindingSlots(target, value, env, sourceCodeInfo, [{
29837
+ type: "ForLetBind",
29838
+ phase: "destructure",
29839
+ forFrame,
29840
+ levelStates,
29841
+ letBindings,
29842
+ letIndex,
29843
+ currentValue: value,
29844
+ env,
29845
+ sourceCodeInfo
29846
+ }, ...k]);
30076
29847
  }
30077
- return chain(result, () => processForGuards({
30078
- ...frame,
30079
- levelStates
30080
- }, levelStates, k));
29848
+ Object.entries(value).forEach(([name, val]) => {
29849
+ forFrame.context[name] = { value: val };
29850
+ });
29851
+ const nextIndex = letIndex + 1;
29852
+ if (nextIndex >= letBindings.length) return processForGuards(forFrame, levelStates, k);
29853
+ return startForLetBindings(forFrame, levelStates, letBindings, nextIndex, env, sourceCodeInfo, k);
30081
29854
  }
30082
29855
  /** Process when/while guards at the current level. */
30083
29856
  function processForGuards(frame, levelStates, k) {
@@ -30182,8 +29955,7 @@ function applyRecur(frame, value, k) {
30182
29955
  /**
30183
29956
  * Handle recur by searching the continuation stack for the nearest
30184
29957
  * LoopIterateFrame or FnBodyFrame, rebinding parameters, and restarting.
30185
- * This replaces the exception-based RecurSignal approach from the recursive
30186
- * evaluator with proper continuation-based control flow.
29958
+ * Uses frame-based slot binding for proper suspension support.
30187
29959
  */
30188
29960
  function handleRecur(params, k, sourceCodeInfo) {
30189
29961
  for (let i = 0; i < k.length; i++) {
@@ -30192,30 +29964,7 @@ function handleRecur(params, k, sourceCodeInfo) {
30192
29964
  const { bindingNodes, bindingContext, body, env } = frame;
30193
29965
  const remainingK = k.slice(i + 1);
30194
29966
  if (params.length !== bindingNodes.length) throw new DvalaError(`recur expected ${bindingNodes.length} parameters, got ${params.length}`, sourceCodeInfo);
30195
- return chain(forEachSequential(bindingNodes, (bindingNode, j) => {
30196
- const target = bindingNode[1][0];
30197
- return chain(evaluateBindingNodeValues(target, toAny(params[j]), (n) => evaluateNodeRecursive(n, env)), (valueRecord) => {
30198
- Object.entries(valueRecord).forEach(([name, val]) => {
30199
- bindingContext[name] = { value: val };
30200
- });
30201
- });
30202
- }), () => {
30203
- const innermostContext = env.getContextsRaw()[0];
30204
- if (innermostContext !== bindingContext) for (const [name, entry] of Object.entries(bindingContext)) innermostContext[name] = entry;
30205
- return {
30206
- type: "Eval",
30207
- node: body,
30208
- env,
30209
- k: [{
30210
- type: "LoopIterate",
30211
- bindingNodes,
30212
- bindingContext,
30213
- body,
30214
- env,
30215
- sourceCodeInfo: frame.sourceCodeInfo
30216
- }, ...remainingK]
30217
- };
30218
- });
29967
+ return startRecurLoopRebind(bindingNodes, 0, params, bindingContext, body, env, remainingK, sourceCodeInfo);
30219
29968
  }
30220
29969
  if (frame.type === "FnBody") {
30221
29970
  const { fn, outerEnv } = frame;
@@ -30225,6 +29974,51 @@ function handleRecur(params, k, sourceCodeInfo) {
30225
29974
  }
30226
29975
  throw new DvalaError("recur called outside of loop or function body", sourceCodeInfo);
30227
29976
  }
29977
+ /**
29978
+ * Start rebinding loop variables during recur using slot-based binding.
29979
+ */
29980
+ function startRecurLoopRebind(bindingNodes, bindingIndex, params, bindingContext, body, env, remainingK, sourceCodeInfo) {
29981
+ if (bindingIndex >= bindingNodes.length) {
29982
+ const innermostContext = env.getContextsRaw()[0];
29983
+ if (innermostContext !== bindingContext) for (const [name, entry] of Object.entries(bindingContext)) innermostContext[name] = entry;
29984
+ return {
29985
+ type: "Eval",
29986
+ node: body,
29987
+ env,
29988
+ k: [{
29989
+ type: "LoopIterate",
29990
+ bindingNodes,
29991
+ bindingContext,
29992
+ body,
29993
+ env,
29994
+ sourceCodeInfo
29995
+ }, ...remainingK]
29996
+ };
29997
+ }
29998
+ const target = bindingNodes[bindingIndex][1][0];
29999
+ return startBindingSlots(target, toAny(params[bindingIndex]), env, sourceCodeInfo, [{
30000
+ type: "RecurLoopRebind",
30001
+ bindingNodes,
30002
+ bindingIndex,
30003
+ params,
30004
+ bindingContext,
30005
+ body,
30006
+ env,
30007
+ remainingK,
30008
+ sourceCodeInfo
30009
+ }, ...remainingK]);
30010
+ }
30011
+ /**
30012
+ * Handle completion of one loop binding during recur rebinding.
30013
+ */
30014
+ function applyRecurLoopRebind(frame, value, _k) {
30015
+ const { bindingNodes, bindingIndex, params, bindingContext, body, env, remainingK, sourceCodeInfo } = frame;
30016
+ const record = value;
30017
+ Object.entries(record).forEach(([name, val]) => {
30018
+ bindingContext[name] = { value: val };
30019
+ });
30020
+ return startRecurLoopRebind(bindingNodes, bindingIndex + 1, params, bindingContext, body, env, remainingK, sourceCodeInfo);
30021
+ }
30228
30022
  function applyTryWith(_value, k) {
30229
30023
  return {
30230
30024
  type: "Value",
@@ -30262,6 +30056,7 @@ function applyPerformArgs(frame, value, k) {
30262
30056
  if (index >= argNodes.length) {
30263
30057
  const effectRef = params[0];
30264
30058
  assertEffect(effectRef, frame.sourceCodeInfo);
30059
+ if (env.pure) throw new DvalaError(`Cannot perform effect '${effectRef.name}' in pure mode`, frame.sourceCodeInfo);
30265
30060
  return {
30266
30061
  type: "Perform",
30267
30062
  effect: effectRef,
@@ -30312,9 +30107,9 @@ function applyPerformArgs(frame, value, k) {
30312
30107
  function handlerMatchesEffect(handler, effect, env, sourceCodeInfo) {
30313
30108
  if (isEffect(handler.effectRef)) return handler.effectRef.name === effect.name;
30314
30109
  if (isDvalaFunction(handler.effectRef)) {
30315
- const result = executeFunctionRecursive(handler.effectRef, [effect], env, sourceCodeInfo);
30316
- if (result instanceof Promise) throw new DvalaError("Effect handler predicates must be synchronous", sourceCodeInfo);
30317
- return !!result;
30110
+ const step = dispatchFunction(handler.effectRef, [effect], [], env, sourceCodeInfo, []);
30111
+ if (step instanceof Promise) throw new DvalaError("Effect handler predicates must be synchronous", sourceCodeInfo);
30112
+ return !!runSyncTrampoline(step);
30318
30113
  }
30319
30114
  return false;
30320
30115
  }
@@ -30325,12 +30120,23 @@ function handlerMatchesEffect(handler, effect, env, sourceCodeInfo) {
30325
30120
  function invokeMatchedHandler(handler, frame, args, k, frameIndex, sourceCodeInfo) {
30326
30121
  const resumeK = k;
30327
30122
  const outerK = k.slice(frameIndex + 1);
30328
- const handlerK = [{
30329
- type: "EffectResume",
30330
- resumeK,
30123
+ const handlerInvokeFrame = {
30124
+ type: "HandlerInvoke",
30125
+ args,
30126
+ handlerK: [{
30127
+ type: "EffectResume",
30128
+ resumeK,
30129
+ sourceCodeInfo
30130
+ }, ...outerK],
30131
+ handlerEnv: frame.env,
30331
30132
  sourceCodeInfo
30332
- }, ...outerK];
30333
- return dispatchFunction(asFunctionLike(evaluateNodeRecursive(handler.handlerNode, frame.env), frame.sourceCodeInfo), [args], [], frame.env, sourceCodeInfo, handlerK);
30133
+ };
30134
+ return {
30135
+ type: "Eval",
30136
+ node: handler.handlerNode,
30137
+ env: frame.env,
30138
+ k: [handlerInvokeFrame, ...outerK]
30139
+ };
30334
30140
  }
30335
30141
  function dispatchPerform(effect, args, k, sourceCodeInfo, handlers, signal, snapshotState) {
30336
30142
  const standardDef = getStandardEffectDefinition(effect.name);
@@ -30338,14 +30144,14 @@ function dispatchPerform(effect, args, k, sourceCodeInfo, handlers, signal, snap
30338
30144
  if (effect.name === "dvala.checkpoint" && snapshotState) {
30339
30145
  const message = args[0];
30340
30146
  const meta = args[1];
30341
- const snapshot = {
30147
+ const snapshot = createSnapshot({
30342
30148
  continuation: serializeToObject(k),
30343
30149
  timestamp: Date.now(),
30344
30150
  index: snapshotState.nextSnapshotIndex++,
30345
- runId: snapshotState.runId,
30151
+ executionId: snapshotState.executionId,
30346
30152
  message,
30347
30153
  ...meta !== void 0 ? { meta } : {}
30348
- };
30154
+ });
30349
30155
  snapshotState.snapshots.push(snapshot);
30350
30156
  if (snapshotState.maxSnapshots !== void 0 && snapshotState.snapshots.length > snapshotState.maxSnapshots) snapshotState.snapshots.shift();
30351
30157
  }
@@ -30495,14 +30301,14 @@ function dispatchHostHandler(effectName, matchingHandlers, args, k, signal, sour
30495
30301
  },
30496
30302
  checkpoint: (message, meta) => {
30497
30303
  if (!snapshotState) throw new DvalaError("checkpoint is not available outside effect-enabled execution", sourceCodeInfo);
30498
- const snapshot = {
30304
+ const snapshot = createSnapshot({
30499
30305
  continuation: serializeToObject(k),
30500
30306
  timestamp: Date.now(),
30501
30307
  index: snapshotState.nextSnapshotIndex++,
30502
- runId: snapshotState.runId,
30308
+ executionId: snapshotState.executionId,
30503
30309
  message,
30504
30310
  ...meta !== void 0 ? { meta } : {}
30505
- };
30311
+ });
30506
30312
  snapshotState.snapshots.push(snapshot);
30507
30313
  if (snapshotState.maxSnapshots !== void 0 && snapshotState.snapshots.length > snapshotState.maxSnapshots) snapshotState.snapshots.shift();
30508
30314
  return snapshot;
@@ -30510,7 +30316,7 @@ function dispatchHostHandler(effectName, matchingHandlers, args, k, signal, sour
30510
30316
  resumeFrom: (snapshot, value) => {
30511
30317
  if (settled) throw new DvalaError("Effect handler called resumeFrom() after already calling another operation", sourceCodeInfo);
30512
30318
  if (!snapshotState) throw new DvalaError("resumeFrom is not available outside effect-enabled execution", sourceCodeInfo);
30513
- const found = snapshotState.snapshots.find((s) => s.index === snapshot.index && s.runId === snapshot.runId);
30319
+ const found = snapshotState.snapshots.find((s) => s.index === snapshot.index && s.executionId === snapshot.executionId);
30514
30320
  if (!found) throw new DvalaError(`Invalid snapshot: no snapshot with index ${snapshot.index} found in current run`, sourceCodeInfo);
30515
30321
  settled = true;
30516
30322
  outcome = {
@@ -30818,16 +30624,492 @@ function applyFnBody(frame, value, k) {
30818
30624
  k: [newFrame, ...k]
30819
30625
  };
30820
30626
  }
30821
- function applyBindingDefault(frame, value, k) {
30822
- const { target, record, env, sourceCodeInfo } = frame;
30823
- const valueRecord = evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env));
30824
- if (valueRecord instanceof Promise) throw new DvalaError("Async binding default evaluation not supported in trampoline yet", sourceCodeInfo);
30825
- Object.assign(record, valueRecord);
30627
+ /**
30628
+ * Handle function argument binding after a default value is evaluated.
30629
+ * Binds the value to the current argument using slots, then continues with remaining args.
30630
+ */
30631
+ function applyFnArgBind(frame, value, k) {
30632
+ const { fn, params, argIndex, context, outerEnv, sourceCodeInfo } = frame;
30633
+ const evaluatedFunc = fn.evaluatedfunction;
30634
+ const args = evaluatedFunc[0];
30635
+ const nbrOfNonRestArgs = args.filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
30636
+ const arg = args[argIndex];
30637
+ const closureContext = evaluatedFunc[2];
30638
+ return startBindingSlots(arg, value, outerEnv.create(closureContext).create(context), sourceCodeInfo, [{
30639
+ type: "FnArgSlotComplete",
30640
+ fn,
30641
+ params,
30642
+ argIndex,
30643
+ nbrOfNonRestArgs,
30644
+ context,
30645
+ outerEnv,
30646
+ sourceCodeInfo
30647
+ }, ...k]);
30648
+ }
30649
+ /**
30650
+ * Handle completion of slot-based binding for a function argument.
30651
+ * Merges the binding record into context and continues with next arg.
30652
+ */
30653
+ function applyFnArgSlotComplete(frame, value, k) {
30654
+ const { fn, params, argIndex, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo } = frame;
30655
+ const record = value;
30656
+ Object.entries(record).forEach(([key, val]) => {
30657
+ context[key] = { value: val };
30658
+ });
30659
+ return continueArgSlotBinding(fn, params, argIndex + 1, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k);
30660
+ }
30661
+ /**
30662
+ * Handle completion of rest argument slot-based binding.
30663
+ * Merges bindings into context and proceeds to body evaluation.
30664
+ */
30665
+ function applyFnRestArgComplete(frame, value, k) {
30666
+ const { fn, context, outerEnv, sourceCodeInfo } = frame;
30667
+ const record = value;
30668
+ Object.entries(record).forEach(([key, val]) => {
30669
+ context[key] = { value: val };
30670
+ });
30671
+ return proceedToFnBody(fn, context, outerEnv, sourceCodeInfo, k);
30672
+ }
30673
+ /**
30674
+ * Continue binding function arguments starting from argIndex.
30675
+ * Handles only the default evaluation phase - rest handling moved to handleRestArgAndBody.
30676
+ */
30677
+ function continueBindingArgs(fn, params, argIndex, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k) {
30678
+ const evaluatedFunc = fn.evaluatedfunction;
30679
+ const args = evaluatedFunc[0];
30680
+ const closureContext = evaluatedFunc[2];
30681
+ const bindingEnv = outerEnv.create(closureContext).create(context);
30682
+ for (let i = argIndex; i < nbrOfNonRestArgs; i++) {
30683
+ const defaultNode = args[i][1][1];
30684
+ if (!defaultNode) throw new DvalaError(`Missing required argument ${i}`, sourceCodeInfo);
30685
+ return {
30686
+ type: "Eval",
30687
+ node: defaultNode,
30688
+ env: bindingEnv,
30689
+ k: [{
30690
+ type: "FnArgBind",
30691
+ phase: "default",
30692
+ fn,
30693
+ params,
30694
+ argIndex: i,
30695
+ context,
30696
+ outerEnv,
30697
+ sourceCodeInfo
30698
+ }, ...k]
30699
+ };
30700
+ }
30701
+ return handleRestArgAndBody(fn, params, nbrOfNonRestArgs, context, outerEnv, sourceCodeInfo, k);
30702
+ }
30703
+ /**
30704
+ * Start processing a binding pattern using linearized slots.
30705
+ * This is the entry point for frame-based destructuring.
30706
+ * @internal Exported for testing/incremental migration
30707
+ */
30708
+ function startBindingSlots(target, rootValue, env, sourceCodeInfo, k) {
30709
+ validateBindingRootType(target, rootValue, sourceCodeInfo);
30710
+ return continueBindingSlots([{
30711
+ slots: flattenBindingPattern(target),
30712
+ index: 0,
30713
+ rootValue
30714
+ }], {}, env, sourceCodeInfo, k);
30715
+ }
30716
+ /**
30717
+ * Continue processing binding slots using the context stack.
30718
+ * Handles extracting values, evaluating defaults, and nested binding targets.
30719
+ */
30720
+ function continueBindingSlots(contexts, record, env, sourceCodeInfo, k) {
30721
+ while (contexts.length > 0) {
30722
+ const ctx = contexts[contexts.length - 1];
30723
+ if (ctx.index >= ctx.slots.length) {
30724
+ contexts.pop();
30725
+ continue;
30726
+ }
30727
+ const slot = ctx.slots[ctx.index];
30728
+ if (slot.isRest) {
30729
+ if (slot.restKeys !== void 0) {
30730
+ const parentValue = slot.path.length > 0 ? extractValueByPath(ctx.rootValue, slot.path, sourceCodeInfo) ?? null : ctx.rootValue;
30731
+ record[slot.name] = extractObjectRest(parentValue, slot.restKeys, sourceCodeInfo);
30732
+ } else if (slot.restIndex !== void 0) {
30733
+ const parentValue = slot.path.length > 0 ? extractValueByPath(ctx.rootValue, slot.path, sourceCodeInfo) ?? null : ctx.rootValue;
30734
+ record[slot.name] = extractArrayRest(parentValue, slot.restIndex, sourceCodeInfo);
30735
+ } else {
30736
+ const value = slot.path.length > 0 ? extractValueByPath(ctx.rootValue, slot.path, sourceCodeInfo) ?? null : ctx.rootValue;
30737
+ record[slot.name] = value;
30738
+ }
30739
+ ctx.index++;
30740
+ continue;
30741
+ }
30742
+ const value = extractValueByPath(ctx.rootValue, slot.path, sourceCodeInfo);
30743
+ if (value === void 0 && slot.defaultNode) {
30744
+ const frame = {
30745
+ type: "BindingSlot",
30746
+ contexts: contexts.map((c) => ({ ...c })),
30747
+ record,
30748
+ env,
30749
+ sourceCodeInfo
30750
+ };
30751
+ return {
30752
+ type: "Eval",
30753
+ node: slot.defaultNode,
30754
+ env,
30755
+ k: [frame, ...k]
30756
+ };
30757
+ }
30758
+ const resolvedValue = value ?? null;
30759
+ if (slot.nestedTarget) {
30760
+ const nestedSlots = flattenBindingPatternWithoutDefault(slot.nestedTarget);
30761
+ validateBindingRootType(slot.nestedTarget, resolvedValue, slot.sourceCodeInfo);
30762
+ contexts.push({
30763
+ slots: nestedSlots,
30764
+ index: 0,
30765
+ rootValue: resolvedValue
30766
+ });
30767
+ ctx.index++;
30768
+ continue;
30769
+ }
30770
+ record[slot.name] = resolvedValue;
30771
+ ctx.index++;
30772
+ }
30826
30773
  return {
30827
30774
  type: "Value",
30828
- value,
30775
+ value: record,
30776
+ k
30777
+ };
30778
+ }
30779
+ /**
30780
+ * Flatten a binding pattern without using its top-level default.
30781
+ * Used when we've already resolved the default and need to process the nested structure.
30782
+ */
30783
+ function flattenBindingPatternWithoutDefault(target) {
30784
+ return flattenBindingPattern([
30785
+ target[0],
30786
+ [target[1][0], void 0],
30787
+ target[2]
30788
+ ]);
30789
+ }
30790
+ /**
30791
+ * Handle continuation after evaluating a binding slot's default value.
30792
+ */
30793
+ function applyBindingSlot(frame, value, k) {
30794
+ const { contexts, record, env, sourceCodeInfo } = frame;
30795
+ const ctx = contexts[contexts.length - 1];
30796
+ const slot = ctx.slots[ctx.index];
30797
+ const resolvedValue = value ?? null;
30798
+ if (slot.nestedTarget) {
30799
+ const nestedSlots = flattenBindingPatternWithoutDefault(slot.nestedTarget);
30800
+ validateBindingRootType(slot.nestedTarget, resolvedValue, slot.sourceCodeInfo);
30801
+ contexts.push({
30802
+ slots: nestedSlots,
30803
+ index: 0,
30804
+ rootValue: resolvedValue
30805
+ });
30806
+ ctx.index++;
30807
+ } else {
30808
+ record[slot.name] = resolvedValue;
30809
+ ctx.index++;
30810
+ }
30811
+ return continueBindingSlots(contexts, record, env, sourceCodeInfo, k);
30812
+ }
30813
+ /**
30814
+ * Start pattern matching with slot-based processing.
30815
+ * Returns Step to continue matching, or moves to next case on failure.
30816
+ */
30817
+ function startMatchSlots(pattern, matchValue, matchFrame, env, sourceCodeInfo, k) {
30818
+ if (!checkObjectTypeConstraint(pattern, matchValue)) return tryNextMatchCase(matchFrame, k);
30819
+ if (!checkArrayLengthConstraint(pattern, matchValue)) return tryNextMatchCase(matchFrame, k);
30820
+ const slots = flattenMatchPattern(pattern);
30821
+ if (slots.length === 0) return matchSucceeded({}, matchFrame, k);
30822
+ return continueMatchSlots([{
30823
+ slots,
30824
+ index: 0,
30825
+ rootValue: matchValue
30826
+ }], {}, matchFrame, env, sourceCodeInfo, k);
30827
+ }
30828
+ /**
30829
+ * Continue processing match slots.
30830
+ * Returns Step for next action (eval, success, or try next case).
30831
+ */
30832
+ function continueMatchSlots(contexts, record, matchFrame, env, sourceCodeInfo, k) {
30833
+ while (contexts.length > 0) {
30834
+ const ctx = contexts[contexts.length - 1];
30835
+ if (ctx.index >= ctx.slots.length) {
30836
+ contexts.pop();
30837
+ continue;
30838
+ }
30839
+ const slot = ctx.slots[ctx.index];
30840
+ switch (slot.kind) {
30841
+ case "wildcard":
30842
+ ctx.index++;
30843
+ continue;
30844
+ case "typeCheck":
30845
+ if (!slot.requiredType || !checkTypeAtPath(ctx.rootValue, slot.path, slot.requiredType)) return tryNextMatchCase(matchFrame, k);
30846
+ ctx.index++;
30847
+ continue;
30848
+ case "literal": {
30849
+ const frame = {
30850
+ type: "MatchSlot",
30851
+ contexts: contexts.map((c) => ({ ...c })),
30852
+ record: { ...record },
30853
+ matchFrame,
30854
+ phase: "literal",
30855
+ currentSlot: slot,
30856
+ env,
30857
+ sourceCodeInfo
30858
+ };
30859
+ return {
30860
+ type: "Eval",
30861
+ node: slot.literalNode,
30862
+ env,
30863
+ k: [frame, ...k]
30864
+ };
30865
+ }
30866
+ case "rest":
30867
+ if (slot.restKeys !== void 0) record[slot.name] = extractMatchObjectRest(ctx.rootValue, slot.path, slot.restKeys);
30868
+ else if (slot.restIndex !== void 0) record[slot.name] = extractMatchArrayRest(ctx.rootValue, slot.path, slot.restIndex);
30869
+ else {
30870
+ const value = slot.path.length > 0 ? extractMatchValueByPath(ctx.rootValue, slot.path) ?? null : ctx.rootValue;
30871
+ record[slot.name] = value;
30872
+ }
30873
+ ctx.index++;
30874
+ continue;
30875
+ case "bind": {
30876
+ const value = extractMatchValueByPath(ctx.rootValue, slot.path);
30877
+ if (value === void 0 || value === null) {
30878
+ if (slot.defaultNode) {
30879
+ const frame = {
30880
+ type: "MatchSlot",
30881
+ contexts: contexts.map((c) => ({ ...c })),
30882
+ record: { ...record },
30883
+ matchFrame,
30884
+ phase: "default",
30885
+ currentSlot: slot,
30886
+ env,
30887
+ sourceCodeInfo
30888
+ };
30889
+ return {
30890
+ type: "Eval",
30891
+ node: slot.defaultNode,
30892
+ env,
30893
+ k: [frame, ...k]
30894
+ };
30895
+ }
30896
+ record[slot.name] = value ?? null;
30897
+ } else record[slot.name] = value;
30898
+ ctx.index++;
30899
+ continue;
30900
+ }
30901
+ }
30902
+ }
30903
+ return matchSucceeded(record, matchFrame, k);
30904
+ }
30905
+ /**
30906
+ * Handle continuation after evaluating a match slot value.
30907
+ */
30908
+ function applyMatchSlot(frame, value, k) {
30909
+ const { contexts, record, matchFrame, phase, currentSlot, env, sourceCodeInfo } = frame;
30910
+ const ctx = contexts[contexts.length - 1];
30911
+ if (phase === "literal") {
30912
+ if (!deepEqual$1(extractMatchValueByPath(ctx.rootValue, currentSlot.path), value)) return tryNextMatchCase(matchFrame, k);
30913
+ ctx.index++;
30914
+ } else {
30915
+ record[currentSlot.name] = value ?? null;
30916
+ ctx.index++;
30917
+ }
30918
+ return continueMatchSlots(contexts, record, matchFrame, env, sourceCodeInfo, k);
30919
+ }
30920
+ /**
30921
+ * Pattern matching succeeded — proceed to guard or body.
30922
+ */
30923
+ function matchSucceeded(bindings, matchFrame, k) {
30924
+ const { cases, index, env } = matchFrame;
30925
+ const [, body, guard] = cases[index];
30926
+ const context = {};
30927
+ for (const [name, val] of Object.entries(bindings)) context[name] = { value: val };
30928
+ if (guard) return {
30929
+ type: "Eval",
30930
+ node: guard,
30931
+ env: env.create(context),
30932
+ k: [{
30933
+ ...matchFrame,
30934
+ phase: "guard",
30935
+ bindings
30936
+ }, ...k]
30937
+ };
30938
+ return {
30939
+ type: "Eval",
30940
+ node: body,
30941
+ env: env.create(context),
30942
+ k
30943
+ };
30944
+ }
30945
+ /**
30946
+ * Current pattern didn't match — try next case.
30947
+ */
30948
+ function tryNextMatchCase(matchFrame, k) {
30949
+ return processMatchCase({
30950
+ ...matchFrame,
30951
+ index: matchFrame.index + 1
30952
+ }, k);
30953
+ }
30954
+ /**
30955
+ * Handles continuation after evaluating an effect reference expression.
30956
+ * Stores the evaluated ref, then either evaluates the next ref or starts the body.
30957
+ */
30958
+ function applyEffectRef(frame, value, k) {
30959
+ const { handlerNodes, evaluatedHandlers, index, bodyNodes, bodyEnv, env, sourceCodeInfo } = frame;
30960
+ const currentHandler = handlerNodes[index];
30961
+ evaluatedHandlers.push({
30962
+ effectRef: value,
30963
+ handlerNode: currentHandler[1]
30964
+ });
30965
+ const nextIndex = index + 1;
30966
+ if (nextIndex < handlerNodes.length) {
30967
+ const nextFrame = {
30968
+ type: "EffectRef",
30969
+ handlerNodes,
30970
+ evaluatedHandlers,
30971
+ index: nextIndex,
30972
+ bodyNodes,
30973
+ bodyEnv,
30974
+ env,
30975
+ sourceCodeInfo
30976
+ };
30977
+ return {
30978
+ type: "Eval",
30979
+ node: handlerNodes[nextIndex][0],
30980
+ env,
30981
+ k: [nextFrame, ...k]
30982
+ };
30983
+ }
30984
+ const bodyK = [{
30985
+ type: "TryWith",
30986
+ handlers: evaluatedHandlers,
30987
+ env,
30988
+ sourceCodeInfo
30989
+ }, ...k];
30990
+ if (bodyNodes.length === 0) return {
30991
+ type: "Value",
30992
+ value: null,
30993
+ k: bodyK
30994
+ };
30995
+ if (bodyNodes.length === 1) return {
30996
+ type: "Eval",
30997
+ node: bodyNodes[0],
30998
+ env: bodyEnv,
30999
+ k: bodyK
31000
+ };
31001
+ const sequenceFrame = {
31002
+ type: "Sequence",
31003
+ nodes: bodyNodes,
31004
+ index: 1,
31005
+ env: bodyEnv,
31006
+ sourceCodeInfo
31007
+ };
31008
+ return {
31009
+ type: "Eval",
31010
+ node: bodyNodes[0],
31011
+ env: bodyEnv,
31012
+ k: [sequenceFrame, ...bodyK]
31013
+ };
31014
+ }
31015
+ /**
31016
+ * Handler expression has been evaluated — dispatch the handler function.
31017
+ */
31018
+ function applyHandlerInvoke(frame, value, _k) {
31019
+ return dispatchFunction(asFunctionLike(value, frame.sourceCodeInfo), [frame.args], [], frame.handlerEnv, frame.sourceCodeInfo, frame.handlerK);
31020
+ }
31021
+ /**
31022
+ * Comp iteration — chain to the next function in the composition.
31023
+ * Result from previous function is wrapped in array and passed to next.
31024
+ */
31025
+ function applyComp(frame, value, k) {
31026
+ const { fns, index, env, sourceCodeInfo } = frame;
31027
+ const nextParams = [value];
31028
+ if (index < 0) return {
31029
+ type: "Value",
31030
+ value: asAny(value, sourceCodeInfo),
31031
+ k
31032
+ };
31033
+ const nextFrame = {
31034
+ type: "Comp",
31035
+ fns,
31036
+ index: index - 1,
31037
+ env,
31038
+ sourceCodeInfo
31039
+ };
31040
+ return dispatchFunction(asFunctionLike(fns[index], sourceCodeInfo), nextParams, [], env, sourceCodeInfo, [nextFrame, ...k]);
31041
+ }
31042
+ /**
31043
+ * Juxt iteration — collect result and call next function.
31044
+ */
31045
+ function applyJuxt(frame, value, k) {
31046
+ const { fns, params, index, results, env, sourceCodeInfo } = frame;
31047
+ const newResults = [...results, value];
31048
+ if (index >= fns.length) return {
31049
+ type: "Value",
31050
+ value: newResults,
31051
+ k
31052
+ };
31053
+ const nextFrame = {
31054
+ type: "Juxt",
31055
+ fns,
31056
+ params,
31057
+ index: index + 1,
31058
+ results: newResults,
31059
+ env,
31060
+ sourceCodeInfo
31061
+ };
31062
+ return dispatchFunction(asFunctionLike(fns[index], sourceCodeInfo), params, [], env, sourceCodeInfo, [nextFrame, ...k]);
31063
+ }
31064
+ /**
31065
+ * EveryPred iteration — short-circuit on falsy, continue on truthy.
31066
+ */
31067
+ function applyEveryPred(frame, value, k) {
31068
+ const { checks, index, env, sourceCodeInfo } = frame;
31069
+ if (!value) return {
31070
+ type: "Value",
31071
+ value: false,
31072
+ k
31073
+ };
31074
+ if (index >= checks.length) return {
31075
+ type: "Value",
31076
+ value: true,
30829
31077
  k
30830
31078
  };
31079
+ const nextFrame = {
31080
+ type: "EveryPred",
31081
+ checks,
31082
+ index: index + 1,
31083
+ env,
31084
+ sourceCodeInfo
31085
+ };
31086
+ const check = checks[index];
31087
+ return dispatchFunction(check.fn, [check.param], [], env, sourceCodeInfo, [nextFrame, ...k]);
31088
+ }
31089
+ /**
31090
+ * SomePred iteration — short-circuit on truthy, continue on falsy.
31091
+ */
31092
+ function applySomePred(frame, value, k) {
31093
+ const { checks, index, env, sourceCodeInfo } = frame;
31094
+ if (value) return {
31095
+ type: "Value",
31096
+ value: true,
31097
+ k
31098
+ };
31099
+ if (index >= checks.length) return {
31100
+ type: "Value",
31101
+ value: false,
31102
+ k
31103
+ };
31104
+ const nextFrame = {
31105
+ type: "SomePred",
31106
+ checks,
31107
+ index: index + 1,
31108
+ env,
31109
+ sourceCodeInfo
31110
+ };
31111
+ const check = checks[index];
31112
+ return dispatchFunction(check.fn, [check.param], [], env, sourceCodeInfo, [nextFrame, ...k]);
30831
31113
  }
30832
31114
  function applyNanCheck(frame, value, k) {
30833
31115
  if (typeof value === "number" && Number.isNaN(value)) throw new DvalaError("Number is NaN", frame.sourceCodeInfo);
@@ -30996,7 +31278,7 @@ function tick(step, handlers, signal, snapshotState) {
30996
31278
  function runSyncTrampoline(initial, effectHandlers) {
30997
31279
  let step = initial;
30998
31280
  for (;;) {
30999
- if (step instanceof Promise) throw new DvalaError("Unexpected async operation in synchronous context. Use async.run() for async operations.", void 0);
31281
+ if (step instanceof Promise) throw new DvalaError("Unexpected async operation in synchronous context.", void 0);
31000
31282
  if (step.type === "Value" && step.k.length === 0) return step.value;
31001
31283
  step = tick(step, effectHandlers);
31002
31284
  }
@@ -31056,30 +31338,6 @@ function evaluate(ast, contextStack) {
31056
31338
  }
31057
31339
  }
31058
31340
  /**
31059
- * Evaluate a single AST node using the trampoline.
31060
- * Used as the `evaluateNode` callback passed to `getUndefinedSymbols`
31061
- * and other utilities.
31062
- */
31063
- function evaluateNode(node, contextStack) {
31064
- const initial = {
31065
- type: "Eval",
31066
- node,
31067
- env: contextStack,
31068
- k: []
31069
- };
31070
- try {
31071
- return runSyncTrampoline(initial);
31072
- } catch (error) {
31073
- if (error instanceof DvalaError && error.message.includes("Unexpected async operation")) return runAsyncTrampoline({
31074
- type: "Eval",
31075
- node,
31076
- env: contextStack,
31077
- k: []
31078
- });
31079
- throw error;
31080
- }
31081
- }
31082
- /**
31083
31341
  * Evaluate an AST with full effect handler support.
31084
31342
  *
31085
31343
  * Uses the async trampoline loop, passing `handlers` and `signal` to `tick`
@@ -31130,18 +31388,42 @@ async function runEffectLoop(initial, handlers, signal, initialSnapshotState, ma
31130
31388
  const snapshotState = {
31131
31389
  snapshots: initialSnapshotState ? initialSnapshotState.snapshots : [],
31132
31390
  nextSnapshotIndex: initialSnapshotState ? initialSnapshotState.nextSnapshotIndex : 0,
31133
- runId: generateRunId(),
31391
+ executionId: generateUUID(),
31134
31392
  ...maxSnapshots !== void 0 ? { maxSnapshots } : {},
31135
31393
  ...autoCheckpoint ? { autoCheckpoint } : {}
31136
31394
  };
31137
31395
  let step = initial;
31396
+ function createTerminalSnapshot(options) {
31397
+ if (!snapshotState.autoCheckpoint) return;
31398
+ const continuation = serializeTerminalSnapshot(snapshotState.snapshots, snapshotState.nextSnapshotIndex);
31399
+ const meta = {};
31400
+ if (options?.error) meta.error = options.error.toJSON();
31401
+ if (options?.result !== void 0) meta.result = options.result;
31402
+ const message = options?.error ? "Run failed with error" : "Run completed successfully";
31403
+ return createSnapshot({
31404
+ continuation,
31405
+ timestamp: Date.now(),
31406
+ index: snapshotState.nextSnapshotIndex,
31407
+ executionId: snapshotState.executionId,
31408
+ message,
31409
+ terminal: true,
31410
+ ...Object.keys(meta).length > 0 ? { meta } : {}
31411
+ });
31412
+ }
31138
31413
  for (;;) try {
31139
31414
  for (;;) {
31140
31415
  if (step instanceof Promise) step = await step;
31141
- if (step.type === "Value" && step.k.length === 0) return {
31142
- type: "completed",
31143
- value: step.value
31144
- };
31416
+ if (step.type === "Value" && step.k.length === 0) {
31417
+ const snapshot = createTerminalSnapshot({ result: step.value });
31418
+ return snapshot ? {
31419
+ type: "completed",
31420
+ value: step.value,
31421
+ snapshot
31422
+ } : {
31423
+ type: "completed",
31424
+ value: step.value
31425
+ };
31426
+ }
31145
31427
  if (debugMode && step.type === "Eval" && step.node[2]) {
31146
31428
  const nodeType = step.node[0];
31147
31429
  if (nodeType === NodeTypes.NormalExpression || nodeType === NodeTypes.SpecialExpression) {
@@ -31173,24 +31455,37 @@ async function runEffectLoop(initial, handlers, signal, initialSnapshotState, ma
31173
31455
  }
31174
31456
  if (isSuspensionSignal(error)) return {
31175
31457
  type: "suspended",
31176
- snapshot: {
31458
+ snapshot: createSnapshot({
31177
31459
  continuation: serializeSuspensionBlob(error.k, error.snapshots, error.nextSnapshotIndex, error.meta),
31178
31460
  timestamp: Date.now(),
31179
31461
  index: snapshotState.nextSnapshotIndex++,
31180
- runId: snapshotState.runId,
31462
+ executionId: snapshotState.executionId,
31181
31463
  message: SUSPENDED_MESSAGE,
31182
31464
  meta: error.meta,
31183
31465
  effectName: error.effectName,
31184
31466
  effectArgs: error.effectArgs
31185
- }
31467
+ })
31186
31468
  };
31187
- if (error instanceof DvalaError) return {
31469
+ if (error instanceof DvalaError) {
31470
+ const snapshot = createTerminalSnapshot({ error });
31471
+ return snapshot ? {
31472
+ type: "error",
31473
+ error,
31474
+ snapshot
31475
+ } : {
31476
+ type: "error",
31477
+ error
31478
+ };
31479
+ }
31480
+ const snapshot = createTerminalSnapshot();
31481
+ const dvalaError = new DvalaError(`${error}`, void 0);
31482
+ return snapshot ? {
31188
31483
  type: "error",
31189
- error
31190
- };
31191
- return {
31484
+ error: dvalaError,
31485
+ snapshot
31486
+ } : {
31192
31487
  type: "error",
31193
- error: new DvalaError(`${error}`, void 0)
31488
+ error: dvalaError
31194
31489
  };
31195
31490
  }
31196
31491
  }
@@ -31298,7 +31593,7 @@ function getUndefinedSymbols(source, options) {
31298
31593
  return getUndefinedSymbols$1({
31299
31594
  body: parse(minifyTokenStream(tokenize(source, false, void 0), { removeWhiteSpace: true })),
31300
31595
  hasDebugData: false
31301
- }, contextStack, builtin, evaluateNode);
31596
+ }, contextStack, builtin);
31302
31597
  }
31303
31598
  //#endregion
31304
31599
  //#region src/createDvala.ts
@@ -31331,6 +31626,7 @@ function createDvala(options) {
31331
31626
  const modules = options?.modules ? new Map(options.modules.map((m) => [m.name, m])) : void 0;
31332
31627
  const factoryBindings = options?.bindings;
31333
31628
  const factoryEffectHandlers = options?.effectHandlers;
31629
+ const factoryDisableTimeTravel = options?.disableAutoCheckpoint ?? false;
31334
31630
  const debug = options?.debug ?? false;
31335
31631
  const cache = options?.cache ? new Cache(options.cache) : null;
31336
31632
  function buildAst(source, filePath) {
@@ -31406,10 +31702,12 @@ function createDvala(options) {
31406
31702
  }
31407
31703
  contextStack.pure = savedPure;
31408
31704
  }
31409
- const result = await evaluateWithEffects(buildAst(isDvalaBundle(source) ? source.program : source), contextStack, effectHandlers, runOptions?.maxSnapshots, {
31705
+ const ast = buildAst(isDvalaBundle(source) ? source.program : source);
31706
+ const disableAutoCheckpoint = runOptions?.disableAutoCheckpoint ?? factoryDisableTimeTravel;
31707
+ const result = await evaluateWithEffects(ast, contextStack, effectHandlers, runOptions?.maxSnapshots, {
31410
31708
  values: bindings,
31411
31709
  modules
31412
- }, runOptions?.autoCheckpoint);
31710
+ }, !disableAutoCheckpoint);
31413
31711
  if (result.type === "completed") return {
31414
31712
  ...result,
31415
31713
  definedBindings: contextStack.getModuleScopeBindings()