@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.
- package/README.md +10 -14
- package/dist/cli/cli.js +1564 -1227
- 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.
|
|
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
|
|
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
|
|
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
|
|
5731
|
+
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
|
|
5950
5732
|
const result = /* @__PURE__ */ new Set();
|
|
5951
|
-
getUndefinedSymbols([node[1][1]], contextStack, builtin
|
|
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
|
|
5957
|
-
getUndefinedSymbols([body], caseContextStack, builtin
|
|
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
|
|
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
|
|
6016
|
-
const bodyResult = getUndefinedSymbols(node[1][1], contextStack.create({}), builtin
|
|
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
|
|
6022
|
-
const handlerResult = getUndefinedSymbols([handlerFn], contextStack, builtin
|
|
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
|
|
5814
|
+
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
|
|
6033
5815
|
const fn = node[1][1];
|
|
6034
|
-
return getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin
|
|
5816
|
+
return getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin);
|
|
6035
5817
|
}
|
|
6036
5818
|
};
|
|
6037
|
-
function getFunctionUnresolvedSymbols(fn, contextStack, getUndefinedSymbols, builtin
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
5934
|
+
const bindingResult = getUndefinedSymbols([value], contextStack, builtin);
|
|
6153
5935
|
walkDefaults(target, (defaultNode) => {
|
|
6154
|
-
addToSet(bindingResult, getUndefinedSymbols([defaultNode], contextStack, builtin
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
6221
|
-
if (whileNode) getUndefinedSymbols([whileNode], contextStack.create(newContext), builtin
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
6584
|
-
return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin
|
|
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
|
|
6397
|
+
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin }) => {
|
|
6616
6398
|
const [, effectExpr, argExprs] = node[1];
|
|
6617
|
-
return joinSets(getUndefinedSymbols([effectExpr], contextStack, builtin
|
|
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
|
|
6634
|
-
return joinSets(...node[1][1].map((branch) => getUndefinedSymbols([branch], contextStack, builtin
|
|
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-
|
|
6762
|
+
"assert-fails": {
|
|
6978
6763
|
category: "assertion",
|
|
6979
|
-
description: "If $fun does not
|
|
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-
|
|
6987
|
-
seeAlso: ["assertion.assert-
|
|
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-
|
|
6775
|
+
"assert-fails-with": {
|
|
6991
6776
|
category: "assertion",
|
|
6992
|
-
description: "If $fun does not
|
|
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-
|
|
7005
|
-
seeAlso: ["assertion.assert-
|
|
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-
|
|
6793
|
+
"assert-succeeds": {
|
|
7009
6794
|
category: "assertion",
|
|
7010
|
-
description: "If $fun
|
|
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-
|
|
7018
|
-
seeAlso: ["assertion.assert-
|
|
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-
|
|
7408
|
-
evaluate: (
|
|
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-
|
|
7425
|
-
evaluate: (
|
|
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-
|
|
7447
|
-
evaluate: (
|
|
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: (
|
|
17970
|
-
|
|
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: (
|
|
18090
|
-
|
|
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: (
|
|
18364
|
-
|
|
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: (
|
|
19014
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
18807
|
+
function createTakeWhileNormalExpression(maxLength) {
|
|
19309
18808
|
return {
|
|
19310
|
-
evaluate: (
|
|
19311
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
26494
|
+
findUnresolvedSymbolsInNode(expressionNode, contextStack, builtin)?.forEach((symbol) => unresolvedSymbols.add(symbol));
|
|
26644
26495
|
}
|
|
26645
|
-
for (const subNode of normalExpressionNode[1][1]) findUnresolvedSymbolsInNode(subNode, contextStack, builtin
|
|
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
|
|
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
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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
|
-
|
|
28951
|
-
|
|
28952
|
-
|
|
28953
|
-
|
|
28954
|
-
|
|
28955
|
-
|
|
28956
|
-
|
|
28957
|
-
|
|
28958
|
-
|
|
28959
|
-
|
|
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
|
|
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
|
|
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, ...
|
|
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
|
|
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
|
|
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 "
|
|
29404
|
-
|
|
29405
|
-
|
|
29406
|
-
|
|
29407
|
-
|
|
29408
|
-
case "
|
|
29409
|
-
|
|
29410
|
-
|
|
29411
|
-
|
|
29412
|
-
|
|
29413
|
-
|
|
29414
|
-
|
|
29415
|
-
|
|
29416
|
-
|
|
29417
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
-
*
|
|
29432
|
-
*
|
|
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
|
|
29440
|
-
const
|
|
29441
|
-
|
|
29442
|
-
|
|
29443
|
-
|
|
29444
|
-
|
|
29445
|
-
|
|
29446
|
-
|
|
29447
|
-
|
|
29448
|
-
|
|
29449
|
-
|
|
29450
|
-
|
|
29451
|
-
|
|
29452
|
-
|
|
29453
|
-
|
|
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
|
-
|
|
29464
|
-
|
|
29465
|
-
|
|
29466
|
-
|
|
29467
|
-
|
|
29468
|
-
}
|
|
29469
|
-
|
|
29470
|
-
|
|
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
|
|
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 "
|
|
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
|
|
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
|
-
|
|
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
|
|
29894
|
-
|
|
29895
|
-
|
|
29896
|
-
|
|
29897
|
-
|
|
29898
|
-
|
|
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
|
-
|
|
29906
|
-
|
|
29907
|
-
|
|
29908
|
-
|
|
29909
|
-
|
|
29910
|
-
|
|
29911
|
-
|
|
29912
|
-
|
|
29913
|
-
|
|
29914
|
-
|
|
29915
|
-
|
|
29916
|
-
|
|
29917
|
-
|
|
29918
|
-
|
|
29919
|
-
|
|
29920
|
-
|
|
29921
|
-
|
|
29922
|
-
|
|
29923
|
-
|
|
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:
|
|
29933
|
-
env:
|
|
29934
|
-
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
|
|
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
|
|
29959
|
-
const targetNode = binding[0][1][0];
|
|
29718
|
+
const targetNode = bindingNodes[frame.bindingLevel][0][1][0];
|
|
29960
29719
|
const element = seq[0];
|
|
29961
|
-
return
|
|
29962
|
-
|
|
29963
|
-
|
|
29964
|
-
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
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
|
|
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
|
|
30039
|
-
const targetNode = binding[0][1][0];
|
|
29789
|
+
const targetNode = bindingNodes[currentLevel][0][1][0];
|
|
30040
29790
|
const element = currentState.collection[nextElementIndex];
|
|
30041
|
-
return
|
|
30042
|
-
|
|
30043
|
-
|
|
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
|
-
},
|
|
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
|
-
/**
|
|
30059
|
-
function
|
|
30060
|
-
|
|
30061
|
-
|
|
30062
|
-
|
|
30063
|
-
|
|
30064
|
-
|
|
30065
|
-
|
|
30066
|
-
|
|
30067
|
-
|
|
30068
|
-
|
|
30069
|
-
|
|
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
|
-
|
|
30076
|
-
|
|
30077
|
-
|
|
30078
|
-
|
|
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
|
-
*
|
|
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
|
|
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
|
|
30314
|
-
if (
|
|
30315
|
-
return !!
|
|
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
|
|
30327
|
-
type: "
|
|
30328
|
-
|
|
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
|
-
}
|
|
30331
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
30799
|
-
|
|
30800
|
-
|
|
30801
|
-
|
|
30802
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
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)
|
|
31102
|
-
|
|
31103
|
-
|
|
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
|
-
|
|
31141
|
-
message:
|
|
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)
|
|
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
|
-
|
|
31484
|
+
error: dvalaError,
|
|
31485
|
+
snapshot
|
|
31486
|
+
} : {
|
|
31152
31487
|
type: "error",
|
|
31153
|
-
error:
|
|
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
|
|
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
|
-
|
|
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 &&
|
|
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
|
|
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: {
|
|
33882
|
-
|
|
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;
|