* Add result-or-promise (RP) exec model to interpreter (async-first). * Add centralized table property access with fast misses. * Update table string keys to be object map. * Update error contexts to be more consistent and precise. * Update evaluator to return either values or _Promises_. * Update func calls, unary and bin operations, and expression lists. * Update _stdlib_ to the changes and improve errors. * Add tests to validate async control flow and error contexts. * Add dedicated benches that isolate the _runtime_ from parsing.
39 lines
1.0 KiB
TypeScript
39 lines
1.0 KiB
TypeScript
// Result-or-Promise helpers
|
|
|
|
export type RP<T> = T | Promise<T>;
|
|
|
|
// Returns true when v is a Promise or a has a then function.
|
|
export function isPromise<T>(v: RP<T>): v is Promise<T> {
|
|
return v !== null && typeof v === "object" &&
|
|
typeof (v as any).then === "function";
|
|
}
|
|
|
|
export function rpThen<A, B>(v: RP<A>, f: (a: A) => RP<B>): RP<B> {
|
|
return isPromise(v) ? (v as Promise<A>).then(f) : f(v as A);
|
|
}
|
|
|
|
/**
|
|
* Collect an array of Result-or-Promise values into a single array
|
|
* avoiding Promise allocation when all inputs are synchronous.
|
|
*/
|
|
export function rpAll<T>(arr: RP<T>[]): RP<T[]> {
|
|
let hasPromise = false;
|
|
for (let i = 0; i < arr.length; i++) {
|
|
if (isPromise(arr[i])) {
|
|
hasPromise = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasPromise) {
|
|
// All sync values: return as-is
|
|
return arr as T[];
|
|
}
|
|
|
|
// At least one Promise: allocate a new array
|
|
const out = new Array<T | Promise<T>>(arr.length);
|
|
for (let i = 0; i < arr.length; i++) {
|
|
out[i] = arr[i] as any;
|
|
}
|
|
return Promise.all(out as Promise<T>[]);
|
|
}
|