@mojir/dvala 0.0.12 → 0.0.14

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 +1564 -1227
  3. package/package.json +3 -5
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.12";
480
+ var version = "0.0.14";
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,18 +26096,378 @@ function createContextStack(params = {}, modules, pure) {
26605
26096
  return params.globalModuleScope ? contextStack : contextStack.create({});
26606
26097
  }
26607
26098
  //#endregion
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;
26144
+ }
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
26154
+ });
26155
+ break;
26156
+ }
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
26608
26459
  //#region src/getUndefinedSymbols/index.ts
26609
- const getUndefinedSymbols$1 = (ast, contextStack, builtin, evaluateNode) => {
26460
+ const getUndefinedSymbols$1 = (ast, contextStack, builtin) => {
26610
26461
  const nodes = Array.isArray(ast) ? ast : [[NodeTypes.SpecialExpression, [
26611
26462
  specialExpressionTypes.block,
26612
26463
  ast.body,
26613
26464
  void 0
26614
26465
  ]]];
26615
26466
  const unresolvedSymbols = /* @__PURE__ */ new Set();
26616
- for (const subNode of nodes) findUnresolvedSymbolsInNode(subNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26467
+ for (const subNode of nodes) findUnresolvedSymbolsInNode(subNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26617
26468
  return unresolvedSymbols;
26618
26469
  };
26619
- function findUnresolvedSymbolsInNode(node, contextStack, builtin, evaluateNode) {
26470
+ function findUnresolvedSymbolsInNode(node, contextStack, builtin) {
26620
26471
  const nodeType = node[0];
26621
26472
  switch (nodeType) {
26622
26473
  case NodeTypes.UserDefinedSymbol: {
@@ -26640,9 +26491,9 @@ function findUnresolvedSymbolsInNode(node, contextStack, builtin, evaluateNode)
26640
26491
  }
26641
26492
  } else {
26642
26493
  const [, [expressionNode]] = normalExpressionNode;
26643
- findUnresolvedSymbolsInNode(expressionNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26494
+ findUnresolvedSymbolsInNode(expressionNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26644
26495
  }
26645
- for (const subNode of normalExpressionNode[1][1]) findUnresolvedSymbolsInNode(subNode, contextStack, builtin, evaluateNode)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26496
+ for (const subNode of normalExpressionNode[1][1]) findUnresolvedSymbolsInNode(subNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
26646
26497
  return unresolvedSymbols;
26647
26498
  }
26648
26499
  case NodeTypes.SpecialExpression: {
@@ -26651,11 +26502,10 @@ function findUnresolvedSymbolsInNode(node, contextStack, builtin, evaluateNode)
26651
26502
  const castedGetUndefinedSymbols = builtin.specialExpressions[specialExpressionType].getUndefinedSymbols;
26652
26503
  return castedGetUndefinedSymbols(specialExpressionNode, contextStack, {
26653
26504
  getUndefinedSymbols: getUndefinedSymbols$1,
26654
- builtin,
26655
- evaluateNode
26505
+ builtin
26656
26506
  });
26657
26507
  }
26658
- case NodeTypes.Spread: return findUnresolvedSymbolsInNode(node[1], contextStack, builtin, evaluateNode);
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
  }
@@ -27788,11 +27638,12 @@ function minifyTokenStream(tokenStream, { removeWhiteSpace }) {
27788
27638
  }
27789
27639
  //#endregion
27790
27640
  //#region src/evaluator/effectTypes.ts
27641
+ const SUSPENDED_MESSAGE = "Program suspended";
27791
27642
  /**
27792
27643
  * Generate a UUID for identifying a run() or resume() call.
27793
27644
  * Uses crypto.randomUUID() when available, falls back to a simple generator.
27794
27645
  */
27795
- function generateRunId() {
27646
+ function generateUUID() {
27796
27647
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return crypto.randomUUID();
27797
27648
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
27798
27649
  const r = Math.random() * 16 | 0;
@@ -27800,6 +27651,15 @@ function generateRunId() {
27800
27651
  });
27801
27652
  }
27802
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
+ /**
27803
27663
  * Test whether a handler pattern key matches a given effect name.
27804
27664
  *
27805
27665
  * Rules:
@@ -27821,9 +27681,9 @@ function effectNameMatchesPattern(effectName, pattern) {
27821
27681
  * Returns an array of `[pattern, handler]` pairs.
27822
27682
  */
27823
27683
  function findMatchingHandlers(effectName, handlers) {
27824
- if (!handlers) return [];
27684
+ if (!handlers || handlers.length === 0) return [];
27825
27685
  const result = [];
27826
- for (const [pattern, handler] of Object.entries(handlers)) if (effectNameMatchesPattern(effectName, pattern)) result.push([pattern, handler]);
27686
+ for (const { pattern, handler } of handlers) if (effectNameMatchesPattern(effectName, pattern)) result.push([pattern, handler]);
27827
27687
  return result;
27828
27688
  }
27829
27689
  /**
@@ -28257,6 +28117,28 @@ function serializeSuspensionBlob(k, snapshots, nextSnapshotIndex, meta) {
28257
28117
  return base;
28258
28118
  }
28259
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
+ /**
28260
28142
  * Deserialize a plain object (as produced by `serializeToObject`) back into
28261
28143
  * a continuation stack and metadata.
28262
28144
  *
@@ -28323,7 +28205,7 @@ function deserializeFromObject(blobData, options) {
28323
28205
  };
28324
28206
  }
28325
28207
  //#endregion
28326
- //#region src/evaluator/trampoline.ts
28208
+ //#region src/evaluator/trampoline-evaluator.ts
28327
28209
  /**
28328
28210
  * Trampoline evaluator — explicit-stack evaluation engine.
28329
28211
  *
@@ -28341,292 +28223,10 @@ function deserializeFromObject(blobData, options) {
28341
28223
  * - `stepNode` is always synchronous and returns `Step`.
28342
28224
  * - `applyFrame` may return `Step | Promise<Step>` when normal expressions
28343
28225
  * or compound function types produce async results.
28344
- * - Normal built-in expressions are called directly with pre-evaluated args
28345
- * (they may still use the old recursive `evaluateNode` internally for
28346
- * higher-order callbacks — suspension through them is deferred).
28347
- * - Binding utilities (`evaluateBindingNodeValues`, `tryMatch`) are called
28348
- * 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.
28349
28228
  * - All state lives in frames (no JS closures) — enabling serialization later.
28350
28229
  */
28351
- function evaluateNodeRecursive(node, contextStack) {
28352
- switch (node[0]) {
28353
- case NodeTypes.Number: return node[1];
28354
- case NodeTypes.String: return node[1];
28355
- case NodeTypes.NormalBuiltinSymbol:
28356
- case NodeTypes.SpecialBuiltinSymbol:
28357
- case NodeTypes.UserDefinedSymbol: return contextStack.evaluateSymbol(node);
28358
- case NodeTypes.ReservedSymbol: return evaluateReservedSymbol(node);
28359
- case NodeTypes.NormalExpression: return chain(evaluateNormalExpressionRecursive(node, contextStack), (resolved) => {
28360
- if (typeof resolved === "number" && Number.isNaN(resolved)) throw new DvalaError("Number is NaN", node[2]);
28361
- return annotate(resolved);
28362
- });
28363
- case NodeTypes.SpecialExpression: {
28364
- const initial = {
28365
- type: "Eval",
28366
- node,
28367
- env: contextStack,
28368
- k: []
28369
- };
28370
- try {
28371
- return annotate(runSyncTrampoline(initial));
28372
- } catch (error) {
28373
- /* v8 ignore next 4 */
28374
- if (error instanceof DvalaError && error.message.includes("Unexpected async operation")) return runAsyncTrampoline({
28375
- type: "Eval",
28376
- node,
28377
- env: contextStack,
28378
- k: []
28379
- }).then((r) => annotate(r));
28380
- throw error;
28381
- }
28382
- }
28383
- default: throw new DvalaError(`${getNodeTypeName(node[0])}-node cannot be evaluated`, node[2]);
28384
- }
28385
- }
28386
- function evaluateParamsRecursive(paramNodes, contextStack) {
28387
- const params = [];
28388
- const placeholders = [];
28389
- return chain(forEachSequential(paramNodes, (paramNode, index) => {
28390
- if (isSpreadNode(paramNode))
28391
- /* v8 ignore start */
28392
- return chain(evaluateNodeRecursive(paramNode[1], contextStack), (spreadValue) => {
28393
- if (Array.isArray(spreadValue)) params.push(...spreadValue);
28394
- else throw new DvalaError(`Spread operator requires an array, got ${valueToString(paramNode)}`, paramNode[2]);
28395
- });
28396
- else if (paramNode[0] === NodeTypes.ReservedSymbol && paramNode[1] === "_") placeholders.push(index);
28397
- else return chain(evaluateNodeRecursive(paramNode, contextStack), (value) => {
28398
- params.push(value);
28399
- });
28400
- }), () => ({
28401
- params,
28402
- placeholders
28403
- }));
28404
- }
28405
- function evaluateNormalExpressionRecursive(node, contextStack) {
28406
- const sourceCodeInfo = node[2];
28407
- return chain(evaluateParamsRecursive(node[1][1], contextStack), ({ params, placeholders }) => {
28408
- if (isNormalExpressionNodeWithName(node)) {
28409
- const nameSymbol = node[1][0];
28410
- if (placeholders.length > 0) return chain(evaluateNodeRecursive(nameSymbol, contextStack), (resolvedFn) => {
28411
- return {
28412
- [FUNCTION_SYMBOL]: true,
28413
- function: asFunctionLike(resolvedFn, sourceCodeInfo),
28414
- functionType: "Partial",
28415
- params,
28416
- placeholders,
28417
- sourceCodeInfo,
28418
- arity: toFixedArity(placeholders.length)
28419
- };
28420
- });
28421
- if (isNormalBuiltinSymbolNode(nameSymbol)) {
28422
- const type = nameSymbol[1];
28423
- const normalExpression = builtin.allNormalExpressions[type];
28424
- if (contextStack.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${normalExpression.name}' in pure mode`, node[2]);
28425
- /* v8 ignore next 3 */
28426
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, node[2]);
28427
- return normalExpression.evaluate(params, node[2], contextStack, { executeFunction: executeFunctionRecursive });
28428
- } else {
28429
- const fn = contextStack.getValue(nameSymbol[1]);
28430
- if (fn !== void 0) return executeFunctionRecursive(asFunctionLike(fn, sourceCodeInfo), params, contextStack, sourceCodeInfo);
28431
- /* v8 ignore next 1 */
28432
- throw new UndefinedSymbolError(nameSymbol[1], node[2]);
28433
- }
28434
- } else {
28435
- const fnNode = node[1][0];
28436
- /* v8 ignore start */
28437
- return chain(evaluateNodeRecursive(fnNode, contextStack), (resolvedFn) => {
28438
- const fn = asFunctionLike(resolvedFn, sourceCodeInfo);
28439
- if (placeholders.length > 0) return {
28440
- [FUNCTION_SYMBOL]: true,
28441
- function: fn,
28442
- functionType: "Partial",
28443
- params,
28444
- placeholders,
28445
- sourceCodeInfo,
28446
- arity: toFixedArity(placeholders.length)
28447
- };
28448
- return executeFunctionRecursive(fn, params, contextStack, sourceCodeInfo);
28449
- });
28450
- }
28451
- });
28452
- }
28453
- function executeFunctionRecursive(fn, params, contextStack, sourceCodeInfo) {
28454
- if (isDvalaFunction(fn)) return executeDvalaFunctionRecursive(fn, params, contextStack, sourceCodeInfo);
28455
- if (Array.isArray(fn)) return evaluateArrayAsFunction(fn, params, sourceCodeInfo);
28456
- if (isObj(fn)) return evaluateObjectAsFunction(fn, params, sourceCodeInfo);
28457
- if (typeof fn === "string") return evaluateStringAsFunction(fn, params, sourceCodeInfo);
28458
- if (isNumber(fn)) return evaluateNumberAsFunction(fn, params, sourceCodeInfo);
28459
- /* v8 ignore next 1 */
28460
- throw new DvalaError("Unexpected function type", sourceCodeInfo);
28461
- }
28462
- /**
28463
- * Execute a DvalaFunction recursively. This is the old-style executor
28464
- * used as a fallback for normal expression callbacks.
28465
- */
28466
- function executeDvalaFunctionRecursive(fn, params, contextStack, sourceCodeInfo) {
28467
- switch (fn.functionType) {
28468
- case "UserDefined": return executeUserDefinedRecursive(fn, params, contextStack, sourceCodeInfo);
28469
- case "Partial": return executePartialRecursive(fn, params, contextStack, sourceCodeInfo);
28470
- case "Comp": return executeCompRecursive(fn, params, contextStack, sourceCodeInfo);
28471
- case "Constantly": return fn.value;
28472
- case "Juxt": return executeJuxtRecursive(fn, params, contextStack, sourceCodeInfo);
28473
- case "Complement": return chain(executeFunctionRecursive(fn.function, params, contextStack, sourceCodeInfo), (result) => !result);
28474
- case "EveryPred": return executeEveryPredRecursive(fn, params, contextStack, sourceCodeInfo);
28475
- case "SomePred": return executeSomePredRecursive(fn, params, contextStack, sourceCodeInfo);
28476
- case "Fnull": return executeFnullRecursive(fn, params, contextStack, sourceCodeInfo);
28477
- case "EffectMatcher": return executeEffectMatcherRecursive(fn, params, sourceCodeInfo);
28478
- case "Builtin": {
28479
- const normalExpression = builtin.allNormalExpressions[fn.normalBuiltinSymbolType];
28480
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, sourceCodeInfo);
28481
- return executeBuiltinRecursive(fn, params, contextStack, sourceCodeInfo);
28482
- }
28483
- case "SpecialBuiltin": return executeSpecialBuiltinRecursive(fn, params, contextStack, sourceCodeInfo);
28484
- case "Module": return executeModuleRecursive(fn, params, contextStack, sourceCodeInfo);
28485
- }
28486
- }
28487
- function executeUserDefinedRecursive(fn, params, contextStack, sourceCodeInfo) {
28488
- function setupAndExecute(currentParams) {
28489
- if (!arityAcceptsMin(fn.arity, currentParams.length)) throw new DvalaError(`Expected ${fn.arity} arguments, got ${currentParams.length}.`, sourceCodeInfo);
28490
- const evaluatedFunction = fn.evaluatedfunction;
28491
- const args = evaluatedFunction[0];
28492
- const nbrOfNonRestArgs = args.filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
28493
- const newContextStack = contextStack.create(fn.evaluatedfunction[2]);
28494
- const newContext = { self: { value: fn } };
28495
- const rest = [];
28496
- let paramSetup = void 0;
28497
- for (let i = 0; i < currentParams.length; i += 1) if (i < nbrOfNonRestArgs) {
28498
- const paramIndex = i;
28499
- paramSetup = chain(paramSetup, () => {
28500
- const param = toAny(currentParams[paramIndex]);
28501
- return chain(evaluateBindingNodeValues(args[paramIndex], param, (node) => evaluateNodeRecursive(node, newContextStack.create(newContext))), (valueRecord) => {
28502
- Object.entries(valueRecord).forEach(([key, value]) => {
28503
- newContext[key] = { value };
28504
- });
28505
- });
28506
- });
28507
- } else rest.push(toAny(currentParams[i]));
28508
- let defaultSetup = void 0;
28509
- for (let i = currentParams.length; i < nbrOfNonRestArgs; i++) {
28510
- const argIndex = i;
28511
- defaultSetup = chain(defaultSetup, () => {
28512
- const arg = args[argIndex];
28513
- return chain(evaluateNodeRecursive(arg[1][1], contextStack.create(newContext)), (defaultValue) => {
28514
- return chain(evaluateBindingNodeValues(arg, defaultValue, (node) => evaluateNodeRecursive(node, contextStack.create(newContext))), (valueRecord) => {
28515
- Object.entries(valueRecord).forEach(([key, value]) => {
28516
- newContext[key] = { value };
28517
- });
28518
- });
28519
- });
28520
- });
28521
- }
28522
- return chain(paramSetup, () => chain(defaultSetup, () => {
28523
- const restArgument = args.find((arg) => arg[0] === bindingTargetTypes.rest);
28524
- return chain(restArgument !== void 0 ? chain(evaluateBindingNodeValues(restArgument, rest, (node) => evaluateNodeRecursive(node, contextStack.create(newContext))), (valueRecord) => {
28525
- Object.entries(valueRecord).forEach(([key, value]) => {
28526
- newContext[key] = { value };
28527
- });
28528
- }) : void 0, () => {
28529
- const newContextStack2 = newContextStack.create(newContext);
28530
- const bodyResult = reduceSequential(evaluatedFunction[1], (_acc, node) => evaluateNodeRecursive(node, newContextStack2), null);
28531
- /* v8 ignore start */
28532
- if (bodyResult instanceof Promise) return bodyResult.catch((error) => {
28533
- if (error instanceof RecurSignal) return setupAndExecute(error.params);
28534
- throw error;
28535
- });
28536
- /* v8 ignore stop */
28537
- return bodyResult;
28538
- });
28539
- }));
28540
- }
28541
- for (;;) try {
28542
- return setupAndExecute(params);
28543
- } catch (error) {
28544
- if (error instanceof RecurSignal) {
28545
- params = error.params;
28546
- continue;
28547
- }
28548
- throw error;
28549
- }
28550
- }
28551
- function executePartialRecursive(fn, params, contextStack, sourceCodeInfo) {
28552
- const actualParams = [...fn.params];
28553
- /* v8 ignore next 3 */
28554
- if (params.length !== fn.placeholders.length) throw new DvalaError(`(partial) expects ${fn.placeholders.length} arguments, got ${params.length}.`, sourceCodeInfo);
28555
- const paramsCopy = [...params];
28556
- for (const placeholderIndex of fn.placeholders) actualParams.splice(placeholderIndex, 0, paramsCopy.shift());
28557
- return executeFunctionRecursive(fn.function, actualParams, contextStack, sourceCodeInfo);
28558
- }
28559
- function executeCompRecursive(fn, params, contextStack, sourceCodeInfo) {
28560
- const { params: f } = fn;
28561
- if (f.length === 0) {
28562
- if (params.length !== 1) throw new DvalaError(`(comp) expects one argument, got ${valueToString(params.length)}.`, sourceCodeInfo);
28563
- return asAny(params[0], sourceCodeInfo);
28564
- }
28565
- let result = params;
28566
- for (let i = f.length - 1; i >= 0; i--) {
28567
- const fun = f[i];
28568
- result = chain(result, (currentParams) => chain(executeFunctionRecursive(asFunctionLike(fun, sourceCodeInfo), currentParams, contextStack, sourceCodeInfo), (r) => [r]));
28569
- }
28570
- return chain(result, (finalArr) => asAny(finalArr[0], sourceCodeInfo));
28571
- }
28572
- function executeJuxtRecursive(fn, params, contextStack, sourceCodeInfo) {
28573
- return mapSequential(fn.params, (fun) => executeFunctionRecursive(asFunctionLike(fun, sourceCodeInfo), params, contextStack, sourceCodeInfo));
28574
- }
28575
- function executeEveryPredRecursive(fn, params, contextStack, sourceCodeInfo) {
28576
- const checks = [];
28577
- for (const f of fn.params) for (const param of params) checks.push(() => executeFunctionRecursive(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
28578
- return reduceSequential(checks, (acc, check) => {
28579
- if (!acc) return false;
28580
- return chain(check(), (result) => !!result);
28581
- }, true);
28582
- }
28583
- function executeSomePredRecursive(fn, params, contextStack, sourceCodeInfo) {
28584
- const checks = [];
28585
- for (const f of fn.params) for (const param of params) checks.push(() => executeFunctionRecursive(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
28586
- return reduceSequential(checks, (acc, check) => {
28587
- if (acc) return true;
28588
- return chain(check(), (result) => !!result);
28589
- }, false);
28590
- }
28591
- function executeFnullRecursive(fn, params, contextStack, sourceCodeInfo) {
28592
- const fnulledParams = params.map((param, index) => param === null ? toAny(fn.params[index]) : param);
28593
- return executeFunctionRecursive(asFunctionLike(fn.function, sourceCodeInfo), fnulledParams, contextStack, sourceCodeInfo);
28594
- }
28595
- function executeEffectMatcherRecursive(fn, params, sourceCodeInfo) {
28596
- assertNumberOfParams({
28597
- min: 1,
28598
- max: 1
28599
- }, params.length, fn.sourceCodeInfo ?? sourceCodeInfo);
28600
- const effectRef = params[0];
28601
- assertEffect(effectRef, sourceCodeInfo);
28602
- const effectName = effectRef.name;
28603
- if (fn.matchType === "string") return effectNameMatchesPattern(effectName, fn.pattern);
28604
- return new RegExp(fn.pattern, fn.flags).test(effectName);
28605
- }
28606
- function executeBuiltinRecursive(fn, params, contextStack, sourceCodeInfo) {
28607
- const normalExpression = asNonUndefined(builtin.allNormalExpressions[fn.normalBuiltinSymbolType], sourceCodeInfo);
28608
- /* v8 ignore next 6 */
28609
- if (contextStack.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${fn.name}' in pure mode`, sourceCodeInfo);
28610
- if (normalExpression.dvalaImpl) return executeUserDefinedRecursive(normalExpression.dvalaImpl, params, contextStack, sourceCodeInfo);
28611
- return normalExpression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28612
- }
28613
- /* v8 ignore start */
28614
- function executeSpecialBuiltinRecursive(fn, params, contextStack, sourceCodeInfo) {
28615
- const specialExpression = asNonUndefined(builtin.specialExpressions[fn.specialBuiltinSymbolType], sourceCodeInfo);
28616
- if (specialExpression.evaluateAsNormalExpression) return specialExpression.evaluateAsNormalExpression(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28617
- throw new DvalaError(`Special builtin function ${fn.specialBuiltinSymbolType} is not supported as normal expression.`, sourceCodeInfo);
28618
- }
28619
- function executeModuleRecursive(fn, params, contextStack, sourceCodeInfo) {
28620
- const dvalaModule = contextStack.getModule(fn.moduleName);
28621
- if (!dvalaModule) throw new DvalaError(`Module '${fn.moduleName}' not found.`, sourceCodeInfo);
28622
- const expression = dvalaModule.functions[fn.functionName];
28623
- if (!expression) throw new DvalaError(`Function '${fn.functionName}' not found in module '${fn.moduleName}'.`, sourceCodeInfo);
28624
- if (contextStack.pure && expression.pure === false) throw new DvalaError(`Cannot call impure function '${fn.functionName}' in pure mode`, sourceCodeInfo);
28625
- assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
28626
- if (expression.dvalaImpl) return executeUserDefinedRecursive(expression.dvalaImpl, params, contextStack, sourceCodeInfo);
28627
- return expression.evaluate(params, sourceCodeInfo, contextStack, { executeFunction: executeFunctionRecursive });
28628
- }
28629
- /* v8 ignore stop */
28630
28230
  function evaluateObjectAsFunction(fn, params, sourceCodeInfo) {
28631
28231
  if (params.length !== 1) throw new DvalaError("Object as function requires one string parameter.", sourceCodeInfo);
28632
28232
  const key = params[0];
@@ -28674,7 +28274,7 @@ function evaluateFunction(fn, contextStack) {
28674
28274
  });
28675
28275
  return ctx;
28676
28276
  }, {});
28677
- getUndefinedSymbols$1(fn[1], contextStack.new(context), builtin, evaluateNodeRecursive).forEach((name) => {
28277
+ getUndefinedSymbols$1(fn[1], contextStack.new(context), builtin).forEach((name) => {
28678
28278
  const value = contextStack.getValue(name);
28679
28279
  if (isAny(value)) functionContext[name] = { value };
28680
28280
  });
@@ -28947,26 +28547,34 @@ function stepSpecialExpression(node, env, k) {
28947
28547
  const nodes = node[1][1];
28948
28548
  const withHandlerNodes = node[1][2];
28949
28549
  const newEnv = env.create({});
28950
- let bodyK = k;
28951
- if (withHandlerNodes && withHandlerNodes.length > 0) bodyK = [{
28952
- type: "TryWith",
28953
- handlers: withHandlerNodes.map(([effectExpr, handlerNode]) => ({
28954
- effectRef: evaluateNodeRecursive(effectExpr, env),
28955
- handlerNode
28956
- })),
28957
- env,
28958
- sourceCodeInfo
28959
- }, ...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
+ }
28960
28568
  if (nodes.length === 0) return {
28961
28569
  type: "Value",
28962
28570
  value: null,
28963
- k: bodyK
28571
+ k
28964
28572
  };
28965
28573
  if (nodes.length === 1) return {
28966
28574
  type: "Eval",
28967
28575
  node: nodes[0],
28968
28576
  env: newEnv,
28969
- k: bodyK
28577
+ k
28970
28578
  };
28971
28579
  const frame = {
28972
28580
  type: "Sequence",
@@ -28979,7 +28587,7 @@ function stepSpecialExpression(node, env, k) {
28979
28587
  type: "Eval",
28980
28588
  node: nodes[0],
28981
28589
  env: newEnv,
28982
- k: [frame, ...bodyK]
28590
+ k: [frame, ...k]
28983
28591
  };
28984
28592
  }
28985
28593
  case specialExpressionTypes.let: {
@@ -29334,7 +28942,7 @@ function dispatchCall(frame, k) {
29334
28942
  if (env.pure && normalExpression.pure === false) throw new DvalaError(`Cannot call impure function '${normalExpression.name}' in pure mode`, sourceCodeInfo);
29335
28943
  /* v8 ignore next 3 */
29336
28944
  if (normalExpression.dvalaImpl) return setupUserDefinedCall(normalExpression.dvalaImpl, params, env, sourceCodeInfo, k);
29337
- return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env, { executeFunction: executeFunctionRecursive }), k);
28945
+ return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env), k);
29338
28946
  }
29339
28947
  const fn = env.getValue(nameSymbol[1]);
29340
28948
  if (fn !== void 0) return dispatchFunction(asFunctionLike(fn, sourceCodeInfo), params, placeholders, env, sourceCodeInfo, k);
@@ -29395,79 +29003,219 @@ function dispatchFunction(fn, params, placeholders, env, sourceCodeInfo, k) {
29395
29003
  }
29396
29004
  /**
29397
29005
  * Dispatch a DvalaFunction. User-defined functions are set up with frames;
29398
- * compound function types (Comp, Juxt, etc.) use the recursive executor.
29006
+ * some compound function types still use the recursive executor for iteration.
29399
29007
  */
29400
29008
  function dispatchDvalaFunction(fn, params, env, sourceCodeInfo, k) {
29401
29009
  switch (fn.functionType) {
29402
29010
  case "UserDefined": return setupUserDefinedCall(fn, params, env, sourceCodeInfo, k);
29403
- case "Partial":
29404
- case "Comp":
29405
- case "Constantly":
29406
- case "Juxt":
29407
- case "Complement":
29408
- case "EveryPred":
29409
- case "SomePred":
29410
- case "Fnull":
29411
- case "EffectMatcher":
29412
- case "SpecialBuiltin": return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
29413
- case "Module": {
29414
- const expression = env.getModule(fn.moduleName)?.functions[fn.functionName];
29415
- if (expression?.dvalaImpl) {
29416
- assertNumberOfParams(expression.arity, params.length, sourceCodeInfo);
29417
- return setupUserDefinedCall(expression.dvalaImpl, 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
+ };
29034
+ }
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
+ };
29418
29062
  }
29419
- return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
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);
29420
29147
  }
29421
29148
  case "Builtin": {
29422
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);
29423
29151
  if (normalExpression.dvalaImpl) return setupUserDefinedCall(normalExpression.dvalaImpl, params, env, sourceCodeInfo, k);
29424
- return wrapMaybePromiseAsStep(executeDvalaFunctionRecursive(fn, params, env, sourceCodeInfo), k);
29152
+ return wrapMaybePromiseAsStep(normalExpression.evaluate(params, sourceCodeInfo, env), k);
29425
29153
  }
29426
29154
  }
29427
29155
  }
29428
29156
  /**
29429
29157
  * Set up a user-defined function call: bind params, push FnBodyFrame.
29430
29158
  *
29431
- * For Phase 1, parameter binding (including destructuring defaults) is done
29432
- * synchronously via evaluateBindingNodeValues with the recursive evaluator.
29433
- * 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.
29434
29161
  */
29435
29162
  function setupUserDefinedCall(fn, params, env, sourceCodeInfo, k) {
29436
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) {
29437
29172
  const evaluatedFunc = fn.evaluatedfunction;
29438
29173
  const args = evaluatedFunc[0];
29439
- const nbrOfNonRestArgs = args.filter((arg) => arg[0] !== bindingTargetTypes.rest).length;
29440
- const newContextStack = env.create(fn.evaluatedfunction[2]);
29441
- const newContext = { self: { value: fn } };
29442
- const rest = [];
29443
- for (let i = 0; i < params.length; i += 1) if (i < nbrOfNonRestArgs) {
29444
- const param = toAny(params[i]);
29445
- const valueRecord = evaluateBindingNodeValues(args[i], param, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29446
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29447
- Object.entries(valueRecord).forEach(([key, value]) => {
29448
- newContext[key] = { value };
29449
- });
29450
- } else rest.push(toAny(params[i]));
29451
- for (let i = params.length; i < nbrOfNonRestArgs; i++) {
29452
- const arg = args[i];
29453
- const defaultValue = evaluateNodeRecursive(arg[1][1], newContextStack.create(newContext));
29454
- if (defaultValue instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29455
- const valueRecord = evaluateBindingNodeValues(arg, defaultValue, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29456
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29457
- Object.entries(valueRecord).forEach(([key, value]) => {
29458
- newContext[key] = { value };
29459
- });
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]);
29460
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);
29461
29202
  const restArgument = args.find((arg) => arg[0] === bindingTargetTypes.rest);
29462
- if (restArgument) {
29463
- const valueRecord = evaluateBindingNodeValues(restArgument, rest, (n) => evaluateNodeRecursive(n, newContextStack.create(newContext)));
29464
- if (valueRecord instanceof Promise) return wrapMaybePromiseAsStep(executeUserDefinedRecursive(fn, params, env, sourceCodeInfo), k);
29465
- Object.entries(valueRecord).forEach(([key, value]) => {
29466
- newContext[key] = { value };
29467
- });
29468
- }
29469
- const bodyNodes = evaluatedFunc[1];
29470
- 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];
29471
29219
  if (bodyNodes.length === 0) return {
29472
29220
  type: "Value",
29473
29221
  value: null,
@@ -29478,15 +29226,9 @@ function setupUserDefinedCall(fn, params, env, sourceCodeInfo, k) {
29478
29226
  fn,
29479
29227
  bodyIndex: 1,
29480
29228
  env: bodyEnv,
29481
- outerEnv: env,
29229
+ outerEnv,
29482
29230
  sourceCodeInfo
29483
29231
  };
29484
- if (bodyNodes.length === 1) return {
29485
- type: "Eval",
29486
- node: bodyNodes[0],
29487
- env: bodyEnv,
29488
- k: [fnBodyFrame, ...k]
29489
- };
29490
29232
  return {
29491
29233
  type: "Eval",
29492
29234
  node: bodyNodes[0],
@@ -29510,10 +29252,15 @@ function applyFrame(frame, value, k) {
29510
29252
  case "ArrayBuild": return applyArrayBuild(frame, value, k);
29511
29253
  case "ObjectBuild": return applyObjectBuild(frame, value, k);
29512
29254
  case "LetBind": return applyLetBind(frame, value, k);
29255
+ case "LetBindComplete": return applyLetBindComplete(frame, value, k);
29513
29256
  case "LoopBind": return applyLoopBind(frame, value, k);
29257
+ case "LoopBindComplete": return applyLoopBindComplete(frame, value, k);
29514
29258
  case "LoopIterate": return applyLoopIterate(frame, value, k);
29515
29259
  case "ForLoop": return applyForLoop(frame, value, k);
29260
+ case "ForElementBindComplete": return applyForElementBindComplete(frame, value, k);
29261
+ case "ForLetBind": return applyForLetBind(frame, value, k);
29516
29262
  case "Recur": return applyRecur(frame, value, k);
29263
+ case "RecurLoopRebind": return applyRecurLoopRebind(frame, value, k);
29517
29264
  case "PerformArgs": return applyPerformArgs(frame, value, k);
29518
29265
  case "TryWith": return applyTryWith(value, k);
29519
29266
  case "EffectResume": return applyEffectResume(frame, value, k);
@@ -29521,7 +29268,22 @@ function applyFrame(frame, value, k) {
29521
29268
  case "EvalArgs": return applyEvalArgs(frame, value, k);
29522
29269
  case "CallFn": return applyCallFn(frame, value, k);
29523
29270
  case "FnBody": return applyFnBody(frame, value, k);
29524
- 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);
29525
29287
  case "NanCheck": return applyNanCheck(frame, value, k);
29526
29288
  case "DebugStep": return applyDebugStep(frame, value, k);
29527
29289
  case "ImportMerge": {
@@ -29543,6 +29305,7 @@ function applyFrame(frame, value, k) {
29543
29305
  k
29544
29306
  };
29545
29307
  }
29308
+ case "AutoCheckpoint": return applyAutoCheckpoint(frame, k);
29546
29309
  default: throw new DvalaError(`Unhandled frame type: ${frame.type}`, void 0);
29547
29310
  }
29548
29311
  }
@@ -29656,44 +29419,17 @@ function applyMatch(frame, value, k) {
29656
29419
  }
29657
29420
  /**
29658
29421
  * Process match cases starting from `frame.index`.
29659
- * Uses recursive tryMatch with evaluateNodeRecursive for pattern matching.
29422
+ * Uses frame-based slot processing for pattern matching.
29660
29423
  */
29661
29424
  function processMatchCase(frame, k) {
29662
29425
  const { matchValue, cases, index, env, sourceCodeInfo } = frame;
29663
- for (let i = index; i < cases.length; i++) {
29664
- const [pattern, body, guard] = cases[i];
29665
- const bindings = tryMatch(pattern, matchValue, (n) => evaluateNodeRecursive(n, env));
29666
- if (bindings instanceof Promise) throw new DvalaError("Async pattern matching not supported in trampoline yet", sourceCodeInfo);
29667
- if (bindings === null) continue;
29668
- if (guard) {
29669
- const context = {};
29670
- for (const [name, val] of Object.entries(bindings)) context[name] = { value: val };
29671
- return {
29672
- type: "Eval",
29673
- node: guard,
29674
- env: env.create(context),
29675
- k: [{
29676
- ...frame,
29677
- phase: "guard",
29678
- index: i,
29679
- bindings
29680
- }, ...k]
29681
- };
29682
- }
29683
- const context = {};
29684
- for (const [name, val] of Object.entries(bindings)) context[name] = { value: val };
29685
- return {
29686
- type: "Eval",
29687
- node: body,
29688
- env: env.create(context),
29689
- k
29690
- };
29691
- }
29692
- return {
29426
+ if (index >= cases.length) return {
29693
29427
  type: "Value",
29694
29428
  value: null,
29695
29429
  k
29696
29430
  };
29431
+ const [pattern] = cases[index];
29432
+ return startMatchSlots(pattern, matchValue, frame, env, sourceCodeInfo, k);
29697
29433
  }
29698
29434
  function applyAnd(frame, value, k) {
29699
29435
  if (!value) return {
@@ -29890,50 +29626,74 @@ function applyObjectBuild(frame, value, k) {
29890
29626
  }
29891
29627
  function applyLetBind(frame, value, k) {
29892
29628
  const { target, env, sourceCodeInfo } = frame;
29893
- return chain(evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env)), (br) => {
29894
- env.addValues(br, sourceCodeInfo);
29895
- return {
29896
- type: "Value",
29897
- value,
29898
- k
29899
- };
29900
- });
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
+ };
29901
29644
  }
29902
29645
  function applyLoopBind(frame, value, k) {
29903
29646
  const { bindingNodes, index, context, body, env, sourceCodeInfo } = frame;
29904
29647
  const target = bindingNodes[index][1][0];
29905
- return chain(evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env.create(context))), (vr) => {
29906
- Object.entries(vr).forEach(([name, val]) => {
29907
- context[name] = { value: val };
29908
- });
29909
- const nextIndex = index + 1;
29910
- if (nextIndex >= bindingNodes.length) {
29911
- const loopEnv = env.create(context);
29912
- return {
29913
- type: "Eval",
29914
- node: body,
29915
- env: loopEnv,
29916
- k: [{
29917
- type: "LoopIterate",
29918
- bindingNodes,
29919
- bindingContext: context,
29920
- body,
29921
- env: loopEnv,
29922
- sourceCodeInfo
29923
- }, ...k]
29924
- };
29925
- }
29926
- const newFrame = {
29927
- ...frame,
29928
- index: nextIndex
29929
- };
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);
29930
29667
  return {
29931
29668
  type: "Eval",
29932
- node: bindingNodes[nextIndex][1][1],
29933
- env: env.create(context),
29934
- 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]
29935
29679
  };
29936
- });
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
+ };
29937
29697
  }
29938
29698
  function applyLoopIterate(_frame, value, k) {
29939
29699
  return {
@@ -29943,7 +29703,7 @@ function applyLoopIterate(_frame, value, k) {
29943
29703
  };
29944
29704
  }
29945
29705
  function applyForLoop(frame, value, k) {
29946
- const { returnResult, bindingNodes, result, env, sourceCodeInfo, context } = frame;
29706
+ const { returnResult, bindingNodes, result, env, sourceCodeInfo } = frame;
29947
29707
  const { asColl, isSeq } = getCollectionUtils();
29948
29708
  switch (frame.phase) {
29949
29709
  case "evalCollection": {
@@ -29955,21 +29715,19 @@ function applyForLoop(frame, value, k) {
29955
29715
  collection: seq,
29956
29716
  index: 0
29957
29717
  };
29958
- const binding = bindingNodes[frame.bindingLevel];
29959
- const targetNode = binding[0][1][0];
29718
+ const targetNode = bindingNodes[frame.bindingLevel][0][1][0];
29960
29719
  const element = seq[0];
29961
- return chain(evaluateBindingNodeValues(targetNode, asAny(element, sourceCodeInfo), (n) => evaluateNodeRecursive(n, env)), (vr) => {
29962
- Object.entries(vr).forEach(([name, val]) => {
29963
- context[name] = { value: val };
29964
- });
29965
- const letBindings = binding[1];
29966
- if (letBindings.length > 0) return processForLetBindings(frame, levelStates, letBindings, 0, k);
29967
- return processForGuards(frame, levelStates, k);
29968
- });
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]);
29969
29730
  }
29970
- case "evalLet":
29971
- /* v8 ignore next 1 */
29972
- throw new DvalaError("ForLoop evalLet should not reach applyFrame", sourceCodeInfo);
29973
29731
  case "evalWhen": {
29974
29732
  if (!value) return advanceForElement(frame, k);
29975
29733
  const whileNode = bindingNodes[frame.bindingLevel][3];
@@ -30000,14 +29758,7 @@ function applyForLoop(frame, value, k) {
30000
29758
  case "evalBody":
30001
29759
  if (returnResult) result.push(value);
30002
29760
  return advanceForElement(frame, k);
30003
- case "evalElement": throw new DvalaError(`Unexpected ForLoop phase: ${frame.phase}`, sourceCodeInfo);
30004
29761
  }
30005
- /* v8 ignore next 1 */
30006
- return {
30007
- type: "Value",
30008
- value: null,
30009
- k
30010
- };
30011
29762
  }
30012
29763
  /** Handle for-loop abort: no more elements at the outermost level. */
30013
29764
  function handleForAbort(frame, k) {
@@ -30019,7 +29770,7 @@ function handleForAbort(frame, k) {
30019
29770
  }
30020
29771
  /** Advance to the next element at the current binding level. */
30021
29772
  function advanceForElement(frame, k) {
30022
- const { bindingNodes, env, sourceCodeInfo, context } = frame;
29773
+ const { bindingNodes, env, sourceCodeInfo } = frame;
30023
29774
  const levelStates = [...frame.levelStates];
30024
29775
  const currentLevel = frame.bindingLevel;
30025
29776
  const currentState = levelStates[currentLevel];
@@ -30035,47 +29786,71 @@ function advanceForElement(frame, k) {
30035
29786
  ...currentState,
30036
29787
  index: nextElementIndex
30037
29788
  };
30038
- const binding = bindingNodes[currentLevel];
30039
- const targetNode = binding[0][1][0];
29789
+ const targetNode = bindingNodes[currentLevel][0][1][0];
30040
29790
  const element = currentState.collection[nextElementIndex];
30041
- return chain(evaluateBindingNodeValues(targetNode, asAny(element, sourceCodeInfo), (n) => evaluateNodeRecursive(n, env)), (vr) => {
30042
- Object.entries(vr).forEach(([name, val]) => {
30043
- context[name] = { value: val };
30044
- });
30045
- const letBindings = binding[1];
30046
- if (letBindings.length > 0) return processForLetBindings({
30047
- ...frame,
30048
- levelStates,
30049
- bindingLevel: currentLevel
30050
- }, levelStates, letBindings, 0, k);
30051
- return processForGuards({
29791
+ return startBindingSlots(targetNode, asAny(element, sourceCodeInfo), env, sourceCodeInfo, [{
29792
+ type: "ForElementBindComplete",
29793
+ forFrame: {
30052
29794
  ...frame,
30053
29795
  levelStates,
30054
29796
  bindingLevel: currentLevel
30055
- }, 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 };
30056
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);
30057
29812
  }
30058
- /** Process let-bindings at the current for-loop level. */
30059
- function processForLetBindings(frame, levelStates, letBindings, letIndex, k) {
30060
- const { env, context } = frame;
30061
- let result = void 0;
30062
- for (let i = letIndex; i < letBindings.length; i++) {
30063
- const bindingIndex = i;
30064
- result = chain(result, () => {
30065
- const [target, bindingValue] = letBindings[bindingIndex][1];
30066
- return chain(evaluateNodeRecursive(bindingValue, env), (v) => {
30067
- return chain(evaluateBindingNodeValues(target, v, (n) => evaluateNodeRecursive(n, env)), (vr) => {
30068
- Object.entries(vr).forEach(([name, value]) => {
30069
- context[name] = { value };
30070
- });
30071
- });
30072
- });
30073
- });
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]);
30074
29847
  }
30075
- return chain(result, () => processForGuards({
30076
- ...frame,
30077
- levelStates
30078
- }, 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);
30079
29854
  }
30080
29855
  /** Process when/while guards at the current level. */
30081
29856
  function processForGuards(frame, levelStates, k) {
@@ -30180,8 +29955,7 @@ function applyRecur(frame, value, k) {
30180
29955
  /**
30181
29956
  * Handle recur by searching the continuation stack for the nearest
30182
29957
  * LoopIterateFrame or FnBodyFrame, rebinding parameters, and restarting.
30183
- * This replaces the exception-based RecurSignal approach from the recursive
30184
- * evaluator with proper continuation-based control flow.
29958
+ * Uses frame-based slot binding for proper suspension support.
30185
29959
  */
30186
29960
  function handleRecur(params, k, sourceCodeInfo) {
30187
29961
  for (let i = 0; i < k.length; i++) {
@@ -30190,30 +29964,7 @@ function handleRecur(params, k, sourceCodeInfo) {
30190
29964
  const { bindingNodes, bindingContext, body, env } = frame;
30191
29965
  const remainingK = k.slice(i + 1);
30192
29966
  if (params.length !== bindingNodes.length) throw new DvalaError(`recur expected ${bindingNodes.length} parameters, got ${params.length}`, sourceCodeInfo);
30193
- return chain(forEachSequential(bindingNodes, (bindingNode, j) => {
30194
- const target = bindingNode[1][0];
30195
- return chain(evaluateBindingNodeValues(target, toAny(params[j]), (n) => evaluateNodeRecursive(n, env)), (valueRecord) => {
30196
- Object.entries(valueRecord).forEach(([name, val]) => {
30197
- bindingContext[name] = { value: val };
30198
- });
30199
- });
30200
- }), () => {
30201
- const innermostContext = env.getContextsRaw()[0];
30202
- if (innermostContext !== bindingContext) for (const [name, entry] of Object.entries(bindingContext)) innermostContext[name] = entry;
30203
- return {
30204
- type: "Eval",
30205
- node: body,
30206
- env,
30207
- k: [{
30208
- type: "LoopIterate",
30209
- bindingNodes,
30210
- bindingContext,
30211
- body,
30212
- env,
30213
- sourceCodeInfo: frame.sourceCodeInfo
30214
- }, ...remainingK]
30215
- };
30216
- });
29967
+ return startRecurLoopRebind(bindingNodes, 0, params, bindingContext, body, env, remainingK, sourceCodeInfo);
30217
29968
  }
30218
29969
  if (frame.type === "FnBody") {
30219
29970
  const { fn, outerEnv } = frame;
@@ -30223,6 +29974,51 @@ function handleRecur(params, k, sourceCodeInfo) {
30223
29974
  }
30224
29975
  throw new DvalaError("recur called outside of loop or function body", sourceCodeInfo);
30225
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
+ }
30226
30022
  function applyTryWith(_value, k) {
30227
30023
  return {
30228
30024
  type: "Value",
@@ -30260,6 +30056,7 @@ function applyPerformArgs(frame, value, k) {
30260
30056
  if (index >= argNodes.length) {
30261
30057
  const effectRef = params[0];
30262
30058
  assertEffect(effectRef, frame.sourceCodeInfo);
30059
+ if (env.pure) throw new DvalaError(`Cannot perform effect '${effectRef.name}' in pure mode`, frame.sourceCodeInfo);
30263
30060
  return {
30264
30061
  type: "Perform",
30265
30062
  effect: effectRef,
@@ -30310,9 +30107,9 @@ function applyPerformArgs(frame, value, k) {
30310
30107
  function handlerMatchesEffect(handler, effect, env, sourceCodeInfo) {
30311
30108
  if (isEffect(handler.effectRef)) return handler.effectRef.name === effect.name;
30312
30109
  if (isDvalaFunction(handler.effectRef)) {
30313
- const result = executeFunctionRecursive(handler.effectRef, [effect], env, sourceCodeInfo);
30314
- if (result instanceof Promise) throw new DvalaError("Effect handler predicates must be synchronous", sourceCodeInfo);
30315
- 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);
30316
30113
  }
30317
30114
  return false;
30318
30115
  }
@@ -30323,12 +30120,23 @@ function handlerMatchesEffect(handler, effect, env, sourceCodeInfo) {
30323
30120
  function invokeMatchedHandler(handler, frame, args, k, frameIndex, sourceCodeInfo) {
30324
30121
  const resumeK = k;
30325
30122
  const outerK = k.slice(frameIndex + 1);
30326
- const handlerK = [{
30327
- type: "EffectResume",
30328
- resumeK,
30123
+ const handlerInvokeFrame = {
30124
+ type: "HandlerInvoke",
30125
+ args,
30126
+ handlerK: [{
30127
+ type: "EffectResume",
30128
+ resumeK,
30129
+ sourceCodeInfo
30130
+ }, ...outerK],
30131
+ handlerEnv: frame.env,
30329
30132
  sourceCodeInfo
30330
- }, ...outerK];
30331
- 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
+ };
30332
30140
  }
30333
30141
  function dispatchPerform(effect, args, k, sourceCodeInfo, handlers, signal, snapshotState) {
30334
30142
  const standardDef = getStandardEffectDefinition(effect.name);
@@ -30336,17 +30144,38 @@ function dispatchPerform(effect, args, k, sourceCodeInfo, handlers, signal, snap
30336
30144
  if (effect.name === "dvala.checkpoint" && snapshotState) {
30337
30145
  const message = args[0];
30338
30146
  const meta = args[1];
30339
- const snapshot = {
30147
+ const snapshot = createSnapshot({
30340
30148
  continuation: serializeToObject(k),
30341
30149
  timestamp: Date.now(),
30342
30150
  index: snapshotState.nextSnapshotIndex++,
30343
- runId: snapshotState.runId,
30151
+ executionId: snapshotState.executionId,
30344
30152
  message,
30345
30153
  ...meta !== void 0 ? { meta } : {}
30346
- };
30154
+ });
30347
30155
  snapshotState.snapshots.push(snapshot);
30348
30156
  if (snapshotState.maxSnapshots !== void 0 && snapshotState.snapshots.length > snapshotState.maxSnapshots) snapshotState.snapshots.shift();
30349
30157
  }
30158
+ if (snapshotState?.autoCheckpoint && effect.name !== "dvala.checkpoint") {
30159
+ const topFrame = k[0];
30160
+ if (topFrame?.type === "AutoCheckpoint" && topFrame.phase === "awaitEffect") k = k.slice(1);
30161
+ else {
30162
+ const autoCheckpointFrame = {
30163
+ type: "AutoCheckpoint",
30164
+ phase: "awaitCheckpoint",
30165
+ effect,
30166
+ args,
30167
+ sourceCodeInfo
30168
+ };
30169
+ const checkpointMessage = `Auto checkpoint before ${effect.name}`;
30170
+ return {
30171
+ type: "Perform",
30172
+ effect: getEffectRef("dvala.checkpoint"),
30173
+ args: [checkpointMessage],
30174
+ k: [autoCheckpointFrame, ...k],
30175
+ sourceCodeInfo
30176
+ };
30177
+ }
30178
+ }
30350
30179
  for (let i = 0; i < k.length; i++) {
30351
30180
  const frame = k[i];
30352
30181
  if (frame.type === "TryWith") {
@@ -30472,14 +30301,14 @@ function dispatchHostHandler(effectName, matchingHandlers, args, k, signal, sour
30472
30301
  },
30473
30302
  checkpoint: (message, meta) => {
30474
30303
  if (!snapshotState) throw new DvalaError("checkpoint is not available outside effect-enabled execution", sourceCodeInfo);
30475
- const snapshot = {
30304
+ const snapshot = createSnapshot({
30476
30305
  continuation: serializeToObject(k),
30477
30306
  timestamp: Date.now(),
30478
30307
  index: snapshotState.nextSnapshotIndex++,
30479
- runId: snapshotState.runId,
30308
+ executionId: snapshotState.executionId,
30480
30309
  message,
30481
30310
  ...meta !== void 0 ? { meta } : {}
30482
- };
30311
+ });
30483
30312
  snapshotState.snapshots.push(snapshot);
30484
30313
  if (snapshotState.maxSnapshots !== void 0 && snapshotState.snapshots.length > snapshotState.maxSnapshots) snapshotState.snapshots.shift();
30485
30314
  return snapshot;
@@ -30487,7 +30316,7 @@ function dispatchHostHandler(effectName, matchingHandlers, args, k, signal, sour
30487
30316
  resumeFrom: (snapshot, value) => {
30488
30317
  if (settled) throw new DvalaError("Effect handler called resumeFrom() after already calling another operation", sourceCodeInfo);
30489
30318
  if (!snapshotState) throw new DvalaError("resumeFrom is not available outside effect-enabled execution", sourceCodeInfo);
30490
- 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);
30491
30320
  if (!found) throw new DvalaError(`Invalid snapshot: no snapshot with index ${snapshot.index} found in current run`, sourceCodeInfo);
30492
30321
  settled = true;
30493
30322
  outcome = {
@@ -30795,17 +30624,493 @@ function applyFnBody(frame, value, k) {
30795
30624
  k: [newFrame, ...k]
30796
30625
  };
30797
30626
  }
30798
- function applyBindingDefault(frame, value, k) {
30799
- const { target, record, env, sourceCodeInfo } = frame;
30800
- const valueRecord = evaluateBindingNodeValues(target, value, (n) => evaluateNodeRecursive(n, env));
30801
- if (valueRecord instanceof Promise) throw new DvalaError("Async binding default evaluation not supported in trampoline yet", sourceCodeInfo);
30802
- 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
+ }
30803
30773
  return {
30804
30774
  type: "Value",
30805
- 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),
30806
30942
  k
30807
30943
  };
30808
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,
31077
+ k
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]);
31113
+ }
30809
31114
  function applyNanCheck(frame, value, k) {
30810
31115
  if (typeof value === "number" && Number.isNaN(value)) throw new DvalaError("Number is NaN", frame.sourceCodeInfo);
30811
31116
  return {
@@ -30873,6 +31178,22 @@ function applyDebugStep(frame, value, k) {
30873
31178
  k
30874
31179
  };
30875
31180
  }
31181
+ function applyAutoCheckpoint(frame, k) {
31182
+ const markerFrame = {
31183
+ type: "AutoCheckpoint",
31184
+ phase: "awaitEffect",
31185
+ effect: frame.effect,
31186
+ args: frame.args,
31187
+ sourceCodeInfo: frame.sourceCodeInfo
31188
+ };
31189
+ return {
31190
+ type: "Perform",
31191
+ effect: frame.effect,
31192
+ args: frame.args,
31193
+ k: [markerFrame, ...k],
31194
+ sourceCodeInfo: frame.sourceCodeInfo
31195
+ };
31196
+ }
30876
31197
  /**
30877
31198
  * Wrap a MaybePromise<Any> result into a Step or Promise<Step>.
30878
31199
  * If the result is a value, return a ValueStep immediately.
@@ -30957,7 +31278,7 @@ function tick(step, handlers, signal, snapshotState) {
30957
31278
  function runSyncTrampoline(initial, effectHandlers) {
30958
31279
  let step = initial;
30959
31280
  for (;;) {
30960
- 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);
30961
31282
  if (step.type === "Value" && step.k.length === 0) return step.value;
30962
31283
  step = tick(step, effectHandlers);
30963
31284
  }
@@ -31017,30 +31338,6 @@ function evaluate(ast, contextStack) {
31017
31338
  }
31018
31339
  }
31019
31340
  /**
31020
- * Evaluate a single AST node using the trampoline.
31021
- * Used as the `evaluateNode` callback passed to `getUndefinedSymbols`
31022
- * and other utilities.
31023
- */
31024
- function evaluateNode(node, contextStack) {
31025
- const initial = {
31026
- type: "Eval",
31027
- node,
31028
- env: contextStack,
31029
- k: []
31030
- };
31031
- try {
31032
- return runSyncTrampoline(initial);
31033
- } catch (error) {
31034
- if (error instanceof DvalaError && error.message.includes("Unexpected async operation")) return runAsyncTrampoline({
31035
- type: "Eval",
31036
- node,
31037
- env: contextStack,
31038
- k: []
31039
- });
31040
- throw error;
31041
- }
31042
- }
31043
- /**
31044
31341
  * Evaluate an AST with full effect handler support.
31045
31342
  *
31046
31343
  * Uses the async trampoline loop, passing `handlers` and `signal` to `tick`
@@ -31054,9 +31351,9 @@ function evaluateNode(node, contextStack) {
31054
31351
  * is passed to every host handler. Used for `race()` cancellation (Phase 6)
31055
31352
  * and host-side timeouts.
31056
31353
  */
31057
- async function evaluateWithEffects(ast, contextStack, handlers, maxSnapshots, deserializeOptions) {
31354
+ async function evaluateWithEffects(ast, contextStack, handlers, maxSnapshots, deserializeOptions, autoCheckpoint) {
31058
31355
  const signal = new AbortController().signal;
31059
- return runEffectLoop(buildInitialStep(ast.body, contextStack), handlers, signal, void 0, maxSnapshots, deserializeOptions);
31356
+ return runEffectLoop(buildInitialStep(ast.body, contextStack), handlers, signal, void 0, maxSnapshots, deserializeOptions, autoCheckpoint);
31060
31357
  }
31061
31358
  /**
31062
31359
  * Evaluate an AST synchronously with effect handler support.
@@ -31086,22 +31383,47 @@ function evaluateWithSyncEffects(ast, contextStack, effectHandlers) {
31086
31383
  * to fire a `perform(dvala.debug.step, stepInfo)` after evaluation,
31087
31384
  * enabling the time-travel debugger.
31088
31385
  */
31089
- async function runEffectLoop(initial, handlers, signal, initialSnapshotState, maxSnapshots, deserializeOptions) {
31090
- const debugMode = handlers !== null && handlers !== void 0 && "dvala.debug.step" in handlers;
31386
+ async function runEffectLoop(initial, handlers, signal, initialSnapshotState, maxSnapshots, deserializeOptions, autoCheckpoint) {
31387
+ const debugMode = Array.isArray(handlers) && handlers.some((h) => h.pattern === "dvala.debug.step");
31091
31388
  const snapshotState = {
31092
31389
  snapshots: initialSnapshotState ? initialSnapshotState.snapshots : [],
31093
31390
  nextSnapshotIndex: initialSnapshotState ? initialSnapshotState.nextSnapshotIndex : 0,
31094
- runId: generateRunId(),
31095
- ...maxSnapshots !== void 0 ? { maxSnapshots } : {}
31391
+ executionId: generateUUID(),
31392
+ ...maxSnapshots !== void 0 ? { maxSnapshots } : {},
31393
+ ...autoCheckpoint ? { autoCheckpoint } : {}
31096
31394
  };
31097
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
+ }
31098
31413
  for (;;) try {
31099
31414
  for (;;) {
31100
31415
  if (step instanceof Promise) step = await step;
31101
- if (step.type === "Value" && step.k.length === 0) return {
31102
- type: "completed",
31103
- value: step.value
31104
- };
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
+ }
31105
31427
  if (debugMode && step.type === "Eval" && step.node[2]) {
31106
31428
  const nodeType = step.node[0];
31107
31429
  if (nodeType === NodeTypes.NormalExpression || nodeType === NodeTypes.SpecialExpression) {
@@ -31133,24 +31455,37 @@ async function runEffectLoop(initial, handlers, signal, initialSnapshotState, ma
31133
31455
  }
31134
31456
  if (isSuspensionSignal(error)) return {
31135
31457
  type: "suspended",
31136
- snapshot: {
31458
+ snapshot: createSnapshot({
31137
31459
  continuation: serializeSuspensionBlob(error.k, error.snapshots, error.nextSnapshotIndex, error.meta),
31138
31460
  timestamp: Date.now(),
31139
31461
  index: snapshotState.nextSnapshotIndex++,
31140
- runId: snapshotState.runId,
31141
- message: "suspended",
31462
+ executionId: snapshotState.executionId,
31463
+ message: SUSPENDED_MESSAGE,
31142
31464
  meta: error.meta,
31143
31465
  effectName: error.effectName,
31144
31466
  effectArgs: error.effectArgs
31145
- }
31467
+ })
31146
31468
  };
31147
- 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 ? {
31148
31483
  type: "error",
31149
- error
31150
- };
31151
- return {
31484
+ error: dvalaError,
31485
+ snapshot
31486
+ } : {
31152
31487
  type: "error",
31153
- error: new DvalaError(`${error}`, void 0)
31488
+ error: dvalaError
31154
31489
  };
31155
31490
  }
31156
31491
  }
@@ -31258,7 +31593,7 @@ function getUndefinedSymbols(source, options) {
31258
31593
  return getUndefinedSymbols$1({
31259
31594
  body: parse(minifyTokenStream(tokenize(source, false, void 0), { removeWhiteSpace: true })),
31260
31595
  hasDebugData: false
31261
- }, contextStack, builtin, evaluateNode);
31596
+ }, contextStack, builtin);
31262
31597
  }
31263
31598
  //#endregion
31264
31599
  //#region src/createDvala.ts
@@ -31291,6 +31626,7 @@ function createDvala(options) {
31291
31626
  const modules = options?.modules ? new Map(options.modules.map((m) => [m.name, m])) : void 0;
31292
31627
  const factoryBindings = options?.bindings;
31293
31628
  const factoryEffectHandlers = options?.effectHandlers;
31629
+ const factoryDisableTimeTravel = options?.disableAutoCheckpoint ?? false;
31294
31630
  const debug = options?.debug ?? false;
31295
31631
  const cache = options?.cache ? new Cache(options.cache) : null;
31296
31632
  function buildAst(source, filePath) {
@@ -31314,15 +31650,11 @@ function createDvala(options) {
31314
31650
  }
31315
31651
  function mergeEffectHandlers(runEffectHandlers) {
31316
31652
  if (!factoryEffectHandlers && !runEffectHandlers) return void 0;
31317
- const result = { ...runEffectHandlers };
31318
- if (factoryEffectHandlers) {
31319
- for (const [k, v] of Object.entries(factoryEffectHandlers)) if (!(k in result)) result[k] = v;
31320
- }
31321
- return result;
31653
+ return [...runEffectHandlers ?? [], ...factoryEffectHandlers ?? []];
31322
31654
  }
31323
31655
  function assertNotPureWithHandlers(pure, effectHandlers) {
31324
31656
  if (!pure) return;
31325
- if (effectHandlers && Object.keys(effectHandlers).length > 0) throw new TypeError("Cannot use pure mode with effect handlers");
31657
+ if (effectHandlers && effectHandlers.length > 0) throw new TypeError("Cannot use pure mode with effect handlers");
31326
31658
  }
31327
31659
  return {
31328
31660
  run(source, runOptions) {
@@ -31370,10 +31702,12 @@ function createDvala(options) {
31370
31702
  }
31371
31703
  contextStack.pure = savedPure;
31372
31704
  }
31373
- 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, {
31374
31708
  values: bindings,
31375
31709
  modules
31376
- });
31710
+ }, !disableAutoCheckpoint);
31377
31711
  if (result.type === "completed") return {
31378
31712
  ...result,
31379
31713
  definedBindings: contextStack.getModuleScopeBindings()
@@ -33878,9 +34212,12 @@ async function execute(expression, bindings, readLine) {
33878
34212
  try {
33879
34213
  const runResult = await _dvala.runAsync(expression, {
33880
34214
  bindings,
33881
- effectHandlers: { "dvala.io.read-line": async ({ args, resume }) => {
33882
- resume(await readLine(typeof args[0] === "string" ? args[0] : ""));
33883
- } }
34215
+ effectHandlers: [{
34216
+ pattern: "dvala.io.read-line",
34217
+ handler: async ({ args, resume }) => {
34218
+ resume(await readLine(typeof args[0] === "string" ? args[0] : ""));
34219
+ }
34220
+ }]
33884
34221
  });
33885
34222
  if (runResult.type === "error") throw runResult.error;
33886
34223
  const result = runResult.type === "completed" ? runResult.value : null;