@elaraai/east 0.0.1-beta.1 → 0.0.1-beta.11
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/LICENSE.md +15 -666
- package/README.md +15 -6
- package/dist/src/analyze.d.ts +4 -4
- package/dist/src/analyze.d.ts.map +1 -1
- package/dist/src/analyze.js +142 -44
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/ast.d.ts +18 -7
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast.js +1 -146
- package/dist/src/ast.js.map +1 -1
- package/dist/src/ast_to_ir.d.ts +7 -0
- package/dist/src/ast_to_ir.d.ts.map +1 -1
- package/dist/src/ast_to_ir.js +80 -11
- package/dist/src/ast_to_ir.js.map +1 -1
- package/dist/src/builtins.d.ts +1 -1
- package/dist/src/builtins.d.ts.map +1 -1
- package/dist/src/builtins.js +89 -64
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/comparison.d.ts.map +1 -1
- package/dist/src/comparison.js +19 -2
- package/dist/src/comparison.js.map +1 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +137 -221
- package/dist/src/compile.js.map +1 -1
- package/dist/src/default.d.ts.map +1 -1
- package/dist/src/default.js +2 -0
- package/dist/src/default.js.map +1 -1
- package/dist/src/eastir.d.ts +12 -10
- package/dist/src/eastir.d.ts.map +1 -1
- package/dist/src/eastir.js +20 -19
- package/dist/src/eastir.js.map +1 -1
- package/dist/src/expr/array.d.ts +66 -0
- package/dist/src/expr/array.d.ts.map +1 -1
- package/dist/src/expr/array.js +161 -51
- package/dist/src/expr/array.js.map +1 -1
- package/dist/src/expr/ast.d.ts.map +1 -1
- package/dist/src/expr/ast.js +6 -0
- package/dist/src/expr/ast.js.map +1 -1
- package/dist/src/expr/asyncfunction.d.ts +49 -0
- package/dist/src/expr/asyncfunction.d.ts.map +1 -0
- package/dist/src/expr/asyncfunction.js +60 -0
- package/dist/src/expr/asyncfunction.js.map +1 -0
- package/dist/src/expr/blob.d.ts +25 -1
- package/dist/src/expr/blob.d.ts.map +1 -1
- package/dist/src/expr/blob.js +36 -1
- package/dist/src/expr/blob.js.map +1 -1
- package/dist/src/expr/block.d.ts +82 -8
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +278 -16
- package/dist/src/expr/block.js.map +1 -1
- package/dist/src/expr/dict.js +47 -47
- package/dist/src/expr/dict.js.map +1 -1
- package/dist/src/expr/expr.d.ts +9 -0
- package/dist/src/expr/expr.d.ts.map +1 -1
- package/dist/src/expr/expr.js +5 -1
- package/dist/src/expr/expr.js.map +1 -1
- package/dist/src/expr/index.d.ts +112 -2
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/index.js +110 -8
- package/dist/src/expr/index.js.map +1 -1
- package/dist/src/expr/libs/array.js +1 -1
- package/dist/src/expr/libs/array.js.map +1 -1
- package/dist/src/expr/libs/dict.js +3 -3
- package/dist/src/expr/libs/dict.js.map +1 -1
- package/dist/src/expr/libs/integer.d.ts +19 -0
- package/dist/src/expr/libs/integer.d.ts.map +1 -1
- package/dist/src/expr/libs/integer.js +47 -0
- package/dist/src/expr/libs/integer.js.map +1 -1
- package/dist/src/expr/libs/set.js +2 -2
- package/dist/src/expr/libs/set.js.map +1 -1
- package/dist/src/expr/ref.js +1 -1
- package/dist/src/expr/ref.js.map +1 -1
- package/dist/src/expr/set.js +38 -38
- package/dist/src/expr/set.js.map +1 -1
- package/dist/src/expr/struct.d.ts +2 -0
- package/dist/src/expr/struct.d.ts.map +1 -1
- package/dist/src/expr/types.d.ts +8 -5
- package/dist/src/expr/types.d.ts.map +1 -1
- package/dist/src/expr/variant.d.ts +53 -0
- package/dist/src/expr/variant.d.ts.map +1 -1
- package/dist/src/expr/variant.js +56 -0
- package/dist/src/expr/variant.js.map +1 -1
- package/dist/src/fuzz.d.ts.map +1 -1
- package/dist/src/fuzz.js +5 -0
- package/dist/src/fuzz.js.map +1 -1
- package/dist/src/internal.d.ts +8 -0
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +8 -0
- package/dist/src/internal.js.map +1 -1
- package/dist/src/ir.d.ts +231 -33
- package/dist/src/ir.d.ts.map +1 -1
- package/dist/src/ir.js +3 -1
- package/dist/src/ir.js.map +1 -1
- package/dist/src/serialization/beast.d.ts.map +1 -1
- package/dist/src/serialization/beast.js +59 -18
- package/dist/src/serialization/beast.js.map +1 -1
- package/dist/src/serialization/beast2-stream.d.ts.map +1 -1
- package/dist/src/serialization/beast2-stream.js +5 -0
- package/dist/src/serialization/beast2-stream.js.map +1 -1
- package/dist/src/serialization/beast2.d.ts.map +1 -1
- package/dist/src/serialization/beast2.js +10 -4
- package/dist/src/serialization/beast2.js.map +1 -1
- package/dist/src/serialization/csv.d.ts +139 -0
- package/dist/src/serialization/csv.d.ts.map +1 -0
- package/dist/src/serialization/csv.js +615 -0
- package/dist/src/serialization/csv.js.map +1 -0
- package/dist/src/serialization/east.d.ts.map +1 -1
- package/dist/src/serialization/east.js +9 -1
- package/dist/src/serialization/east.js.map +1 -1
- package/dist/src/serialization/index.d.ts +1 -0
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +1 -0
- package/dist/src/serialization/index.js.map +1 -1
- package/dist/src/serialization/json.d.ts.map +1 -1
- package/dist/src/serialization/json.js +8 -2
- package/dist/src/serialization/json.js.map +1 -1
- package/dist/src/type_of_type.d.ts +20 -3
- package/dist/src/type_of_type.d.ts.map +1 -1
- package/dist/src/type_of_type.js +101 -13
- package/dist/src/type_of_type.js.map +1 -1
- package/dist/src/types.d.ts +59 -16
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +141 -91
- package/dist/src/types.js.map +1 -1
- package/package.json +4 -4
package/dist/src/compile.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
|
-
import {
|
|
5
|
+
import {} from "./builtins.js";
|
|
6
6
|
import { printLocationValue } from "./ir.js";
|
|
7
7
|
import { compareFor, equalFor, greaterEqualFor, greaterFor, isFor, lessEqualFor, lessFor, notEqualFor } from "./comparison.js";
|
|
8
8
|
import { printFor, parseFor } from "./serialization/east.js";
|
|
@@ -11,10 +11,10 @@ import { EastError } from "./error.js";
|
|
|
11
11
|
import { SortedSet } from "./containers/sortedset.js";
|
|
12
12
|
import { SortedMap } from "./containers/sortedmap.js";
|
|
13
13
|
import { BufferWriter } from "./serialization/binary-utils.js";
|
|
14
|
-
import { decodeBeast2For, decodeBeastFor, encodeBeast2For, encodeBeastFor, fromJSONFor, toJSONFor } from "./serialization/index.js";
|
|
14
|
+
import { decodeBeast2For, decodeBeastFor, encodeBeast2For, encodeBeastFor, fromJSONFor, toJSONFor, decodeCsvFor, encodeCsvFor } from "./serialization/index.js";
|
|
15
15
|
import { formatDateTime } from "./datetime_format/print.js";
|
|
16
16
|
import { parseDateTimeFormatted } from "./datetime_format/parse.js";
|
|
17
|
-
import { EastTypeValueType, isTypeValueEqual,
|
|
17
|
+
import { EastTypeValueType, isTypeValueEqual, expandTypeValue } from "./type_of_type.js";
|
|
18
18
|
import { ref } from "./containers/ref.js";
|
|
19
19
|
export { isTypeValueEqual };
|
|
20
20
|
export const printTypeValue = printFor(EastTypeValueType);
|
|
@@ -64,25 +64,11 @@ class BreakException {
|
|
|
64
64
|
* @internal
|
|
65
65
|
*/
|
|
66
66
|
export function compile_internal(ir, ctx, platform, asyncPlatformFns, fresh_ctx = true, compilingNodes = new Set()) {
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// Track this node (exception-safe with try-finally)
|
|
72
|
-
compilingNodes.add(ir);
|
|
73
|
-
try {
|
|
74
|
-
return compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, compilingNodes);
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
compilingNodes.delete(ir);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/** Internal helper that does the actual compilation work */
|
|
81
|
-
function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, compilingNodes = new Set()) {
|
|
67
|
+
// The IR is checked prior to compilation, so we can assume it's valid here.
|
|
68
|
+
// The compiler needs to take care that Promises are properly awaited, so most IR nodes need both sync and async implementations.
|
|
69
|
+
// We assume unnecessary `async` functions degrade performance but unnecessary `await`s are not too bad, so while we could be more "specific" in our awaits we do not bother
|
|
70
|
+
// TODO if function calls accepted the call Location, we could probably simplify the call site code generation
|
|
82
71
|
if (ir.type === "Value") {
|
|
83
|
-
if (ir.value.type.type !== ir.value.value.type) {
|
|
84
|
-
throw new Error(`Value node expected value of type .${ir.value.type.type} but got .${ir.value.value.type} at ${printLocationValue(ir.value.location)}`);
|
|
85
|
-
}
|
|
86
72
|
const v = ir.value.value.value;
|
|
87
73
|
return (_ctx) => v;
|
|
88
74
|
}
|
|
@@ -191,13 +177,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
191
177
|
}
|
|
192
178
|
else if (ir.type === "Variable") {
|
|
193
179
|
const name = ir.value.name;
|
|
194
|
-
const ctx_type = ctx[name];
|
|
195
|
-
if (ctx_type === undefined) {
|
|
196
|
-
throw new Error(`Variable defined at ${printLocationValue(ir.value.location)} is not in scope at ${printLocationValue(ir.value.location)}`);
|
|
197
|
-
}
|
|
198
|
-
if (!isTypeValueEqual(ctx_type, ir.value.type)) {
|
|
199
|
-
throw new Error(`Variable defined at ${printLocationValue(ir.value.location)} has type ${printTypeValue(ctx_type)} but expected ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
200
|
-
}
|
|
201
180
|
if (ir.value.mutable && ir.value.captured) {
|
|
202
181
|
return (ctx) => ctx[name].x;
|
|
203
182
|
}
|
|
@@ -206,9 +185,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
206
185
|
}
|
|
207
186
|
}
|
|
208
187
|
else if (ir.type === "Let") {
|
|
209
|
-
if (!isSubtypeValue(ir.value.value.value.type, ir.value.variable.value.type)) {
|
|
210
|
-
throw new Error(`Cannot initialize a variable defined at ${printLocationValue(ir.value.variable.value.location)} of type ${printTypeValue(ir.value.variable.value.type)} to a value of type ${printTypeValue(ir.value.value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
211
|
-
}
|
|
212
188
|
const compiled_statement = compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
213
189
|
const name = ir.value.variable.value.name;
|
|
214
190
|
ctx[name] = ir.value.variable.value.type;
|
|
@@ -243,15 +219,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
243
219
|
}
|
|
244
220
|
else if (ir.type === "Assign") {
|
|
245
221
|
const name = ir.value.variable.value.name;
|
|
246
|
-
if (ctx[name] === undefined) {
|
|
247
|
-
throw new Error(`Attempting to reassign to a variable defined at ${printLocationValue(ir.value.variable.value.location)} which is not in scope at ${printLocationValue(ir.value.location)} at ${printLocationValue(ir.value.location)}`);
|
|
248
|
-
}
|
|
249
|
-
if (!isSubtypeValue(ir.value.value.value.type, ctx[name])) {
|
|
250
|
-
throw new Error(`Cannot reassign to a variable defined at ${printLocationValue(ir.value.variable.value.location)} of type ${printTypeValue(ir.value.variable.value.type)} to a value of type ${printTypeValue(ir.value.value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
251
|
-
}
|
|
252
|
-
if (!ir.value.variable.value.mutable) {
|
|
253
|
-
throw new Error(`Cannot reassign const variable ${name} at ${printLocationValue(ir.value.location)}`);
|
|
254
|
-
}
|
|
255
222
|
const compiled_statement = compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
256
223
|
if (ir.value.variable.value.mutable && ir.value.variable.value.captured) {
|
|
257
224
|
if (ir.value.isAsync) {
|
|
@@ -293,58 +260,30 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
293
260
|
}
|
|
294
261
|
}
|
|
295
262
|
else if (ir.type === "As") {
|
|
296
|
-
if (!isSubtypeValue(ir.value.value.value.type, ir.value.type)) {
|
|
297
|
-
throw new Error(`Cannot cast value of type ${printTypeValue(ir.value.value.value.type)} to type ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
298
|
-
}
|
|
299
263
|
// in dynamically typed runtimes like Javascript, this is a no-op
|
|
300
264
|
// (for statically typed runtimes this assists in unifying types in branches)
|
|
301
265
|
return compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, fresh_ctx, compilingNodes);
|
|
302
266
|
}
|
|
303
267
|
else if (ir.type === "UnwrapRecursive") {
|
|
304
|
-
// TODO there seems to be cases of Wrap / Unwrap that could be optimized away during compilation
|
|
305
|
-
if (!isTypeValueEqual(ir.value.value.value.type, ir.value.type)) {
|
|
306
|
-
throw new Error(`Cannot unwrap recursive value of type ${printTypeValue(ir.value.value.value.type)} to type ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
307
|
-
}
|
|
308
268
|
// in dynamically typed runtimes like Javascript, this is a no-op
|
|
309
269
|
// (for statically typed runtimes this assists in e.g. typing a reference or pointer)
|
|
310
270
|
return compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, fresh_ctx, compilingNodes);
|
|
311
271
|
}
|
|
312
272
|
else if (ir.type === "WrapRecursive") {
|
|
313
|
-
// TODO there seems to be cases of Wrap / Unwrap that could be optimized away during compilation
|
|
314
|
-
if (!isSubtypeValue(ir.value.value.value.type, ir.value.type)) {
|
|
315
|
-
throw new Error(`Cannot wrap value of type ${printTypeValue(ir.value.value.value.type)} to recursive type ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
316
|
-
}
|
|
317
273
|
// in dynamically typed runtimes like Javascript, this is a no-op
|
|
318
274
|
// (for statically typed runtimes this assists in e.g. typing a heap allocation)
|
|
319
275
|
return compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
320
276
|
}
|
|
321
277
|
else if (ir.type === "Function") {
|
|
322
|
-
if (ir.value.type.type !== "Function") {
|
|
323
|
-
throw new Error(`Expected Function type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
324
|
-
}
|
|
325
278
|
const ctx2 = {};
|
|
326
279
|
for (const variable of ir.value.captures) {
|
|
327
|
-
const ctx_type = ctx[variable.value.name];
|
|
328
|
-
if (ctx_type === undefined) {
|
|
329
|
-
throw new Error(`Captured variable defined at ${printLocationValue(variable.value.location)} is not in scope at ${printLocationValue(ir.value.location)}`);
|
|
330
|
-
}
|
|
331
|
-
if (!isTypeValueEqual(ctx_type, variable.value.type)) {
|
|
332
|
-
throw new Error(`Captured variable defined at ${printLocationValue(variable.value.location)} has type ${printTypeValue(ctx_type)} but expected ${printTypeValue(variable.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
333
|
-
}
|
|
334
280
|
ctx2[variable.value.name] = variable.value.type;
|
|
335
281
|
}
|
|
336
282
|
for (const parameter of ir.value.parameters) {
|
|
337
283
|
const parameter_name = parameter.value.name;
|
|
338
284
|
ctx2[parameter_name] = parameter.value.type;
|
|
339
285
|
}
|
|
340
|
-
// Function return values are covariant
|
|
341
|
-
// TODO what is the semantics here in a static language? Should we use `As` here?
|
|
342
|
-
// Note: this requires unreachability analysis to be correct, since early terminating programs might have a final statement that produces never
|
|
343
|
-
if (!isSubtypeValue(ir.value.body.value.type, ir.value.type.value.output)) {
|
|
344
|
-
throw new Error(`Expected Function to return type ${printTypeValue(ir.value.type.value.output)}, got ${printTypeValue(ir.value.body.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
345
|
-
}
|
|
346
286
|
const compiled_body = compile_internal(ir.value.body, ctx2, platform, asyncPlatformFns, true, compilingNodes);
|
|
347
|
-
const bodyIsAsync = ir.value.type.value.platforms.some(p => asyncPlatformFns.has(p));
|
|
348
287
|
const capture_names = ir.value.captures.map(v => v.value.name);
|
|
349
288
|
const parameter_names = ir.value.parameters.map(v => v.value.name);
|
|
350
289
|
return (ctx) => {
|
|
@@ -352,47 +291,50 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
352
291
|
for (const name of capture_names) {
|
|
353
292
|
ctx2[name] = ctx[name];
|
|
354
293
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return await compiled_body(ctx3);
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
else {
|
|
364
|
-
return (...args) => {
|
|
365
|
-
const ctx3 = { ...ctx2 };
|
|
366
|
-
parameter_names.forEach((name, i) => ctx3[name] = args[i]);
|
|
367
|
-
return compiled_body(ctx3);
|
|
368
|
-
};
|
|
369
|
-
}
|
|
294
|
+
return (...args) => {
|
|
295
|
+
const ctx3 = { ...ctx2 };
|
|
296
|
+
parameter_names.forEach((name, i) => ctx3[name] = args[i]);
|
|
297
|
+
return compiled_body(ctx3);
|
|
298
|
+
};
|
|
370
299
|
};
|
|
371
300
|
}
|
|
372
|
-
else if (ir.type === "
|
|
373
|
-
|
|
374
|
-
|
|
301
|
+
else if (ir.type === "AsyncFunction") {
|
|
302
|
+
const ctx2 = {};
|
|
303
|
+
for (const variable of ir.value.captures) {
|
|
304
|
+
ctx2[variable.value.name] = variable.value.type;
|
|
375
305
|
}
|
|
376
|
-
|
|
377
|
-
|
|
306
|
+
for (const parameter of ir.value.parameters) {
|
|
307
|
+
const parameter_name = parameter.value.name;
|
|
308
|
+
ctx2[parameter_name] = parameter.value.type;
|
|
378
309
|
}
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
310
|
+
const compiled_body = compile_internal(ir.value.body, ctx2, platform, asyncPlatformFns, true, compilingNodes);
|
|
311
|
+
const capture_names = ir.value.captures.map(v => v.value.name);
|
|
312
|
+
const parameter_names = ir.value.parameters.map(v => v.value.name);
|
|
313
|
+
return (ctx) => {
|
|
314
|
+
const ctx2 = {};
|
|
315
|
+
for (const name of capture_names) {
|
|
316
|
+
ctx2[name] = ctx[name];
|
|
383
317
|
}
|
|
384
|
-
|
|
318
|
+
return (...args) => {
|
|
319
|
+
const ctx3 = { ...ctx2 };
|
|
320
|
+
parameter_names.forEach((name, i) => ctx3[name] = args[i]);
|
|
321
|
+
return compiled_body(ctx3); // Promise can pass through in tail position
|
|
322
|
+
};
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
else if (ir.type === "Call") {
|
|
385
326
|
const compiled_f = compile_internal(ir.value.function, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
386
327
|
const compiled_args = ir.value.arguments.map(argument => compile_internal(argument, ctx, platform, asyncPlatformFns, false, compilingNodes));
|
|
387
328
|
const location = ir.value.location;
|
|
388
|
-
if (ir.value.
|
|
329
|
+
if (ir.value.isAsync) {
|
|
330
|
+
// need to await the arguments
|
|
389
331
|
return async (ctx) => {
|
|
390
332
|
try {
|
|
391
333
|
const args = [];
|
|
392
334
|
for (const compiled_arg of compiled_args) {
|
|
393
335
|
args.push(await compiled_arg(ctx));
|
|
394
336
|
}
|
|
395
|
-
return
|
|
337
|
+
return compiled_f(ctx)(...args);
|
|
396
338
|
}
|
|
397
339
|
catch (e) {
|
|
398
340
|
if (e instanceof ReturnException) {
|
|
@@ -440,9 +382,45 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
440
382
|
};
|
|
441
383
|
}
|
|
442
384
|
}
|
|
385
|
+
else if (ir.type === "CallAsync") {
|
|
386
|
+
const compiled_f = compile_internal(ir.value.function, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
387
|
+
const compiled_args = ir.value.arguments.map(argument => compile_internal(argument, ctx, platform, asyncPlatformFns, false, compilingNodes));
|
|
388
|
+
const location = ir.value.location;
|
|
389
|
+
return async (ctx) => {
|
|
390
|
+
try {
|
|
391
|
+
const args = [];
|
|
392
|
+
for (const compiled_arg of compiled_args) {
|
|
393
|
+
args.push(await compiled_arg(ctx));
|
|
394
|
+
}
|
|
395
|
+
return await compiled_f(ctx)(...args);
|
|
396
|
+
}
|
|
397
|
+
catch (e) {
|
|
398
|
+
if (e instanceof ReturnException) {
|
|
399
|
+
return e.value;
|
|
400
|
+
}
|
|
401
|
+
else if (e instanceof EastError) {
|
|
402
|
+
e.location.push(location); // The fact that we need to push the call location not the definition location means we need to handle this here
|
|
403
|
+
throw (e);
|
|
404
|
+
}
|
|
405
|
+
else if (e instanceof ContinueException) {
|
|
406
|
+
throw new Error(`continue failed to find label ${e.label} at ${printLocationValue(ir.value.location)}`);
|
|
407
|
+
}
|
|
408
|
+
else if (e instanceof BreakException) {
|
|
409
|
+
throw new Error(`break failed to find label ${e.label} at ${printLocationValue(ir.value.location)}`);
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
throw (e);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
}
|
|
443
417
|
else if (ir.type === "IfElse") {
|
|
444
418
|
const ifs = [];
|
|
419
|
+
let asyncPredicate = false;
|
|
445
420
|
for (const { predicate, body } of ir.value.ifs) {
|
|
421
|
+
if (predicate.value.isAsync) {
|
|
422
|
+
asyncPredicate = true;
|
|
423
|
+
}
|
|
446
424
|
ifs.push({
|
|
447
425
|
predicate: compile_internal(predicate, ctx, platform, asyncPlatformFns, false, compilingNodes),
|
|
448
426
|
body: compile_internal(body, Object.create(ctx), platform, asyncPlatformFns, true, compilingNodes),
|
|
@@ -450,14 +428,26 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
450
428
|
}
|
|
451
429
|
const else_body = compile_internal(ir.value.else_body, Object.create(ctx), platform, asyncPlatformFns, true, compilingNodes);
|
|
452
430
|
if (ir.value.isAsync) {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
431
|
+
if (asyncPredicate) {
|
|
432
|
+
return async (ctx) => {
|
|
433
|
+
for (const { predicate, body } of ifs) {
|
|
434
|
+
if (await predicate(ctx)) {
|
|
435
|
+
return await body(Object.create(ctx));
|
|
436
|
+
}
|
|
457
437
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
}
|
|
438
|
+
return await else_body(Object.create(ctx));
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
return async (ctx) => {
|
|
443
|
+
for (const { predicate, body } of ifs) {
|
|
444
|
+
if (predicate(ctx)) {
|
|
445
|
+
return await body(Object.create(ctx));
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
return await else_body(Object.create(ctx));
|
|
449
|
+
};
|
|
450
|
+
}
|
|
461
451
|
}
|
|
462
452
|
else {
|
|
463
453
|
return (ctx) => {
|
|
@@ -482,12 +472,22 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
482
472
|
compiled_cases[k] = compile_internal(body, ctx2, platform, asyncPlatformFns, true, compilingNodes);
|
|
483
473
|
}
|
|
484
474
|
if (ir.value.isAsync) {
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
475
|
+
if (ir.value.variant.value.isAsync) {
|
|
476
|
+
return async (ctx) => {
|
|
477
|
+
const v = await compiled_variant(ctx);
|
|
478
|
+
const ctx2 = Object.create(ctx);
|
|
479
|
+
ctx2[data_names[v.type]] = v.value;
|
|
480
|
+
return await compiled_cases[v.type](ctx2);
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
return async (ctx) => {
|
|
485
|
+
const v = compiled_variant(ctx);
|
|
486
|
+
const ctx2 = Object.create(ctx);
|
|
487
|
+
ctx2[data_names[v.type]] = v.value;
|
|
488
|
+
return await compiled_cases[v.type](ctx2);
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
491
|
}
|
|
492
492
|
else {
|
|
493
493
|
return (ctx) => {
|
|
@@ -768,15 +768,10 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
768
768
|
// The pattern of creating a new context (e.g. a function) and then immediately invoking a block (e.g. as the function body) is very common.
|
|
769
769
|
// Here we avoid creating a second context when possible, as an optimization.
|
|
770
770
|
if (fresh_ctx) {
|
|
771
|
-
let last_type = variant("Null", null);
|
|
772
771
|
const compiled_statements = [];
|
|
773
772
|
for (const statement of ir.value.statements) {
|
|
774
773
|
const compiled_statement = compile_internal(statement, ctx, platform, asyncPlatformFns, true, compilingNodes);
|
|
775
774
|
compiled_statements.push(compiled_statement);
|
|
776
|
-
last_type = statement.value.type;
|
|
777
|
-
}
|
|
778
|
-
if (!isSubtypeValue(last_type, ir.value.type)) {
|
|
779
|
-
throw new Error(`Block evaluates to type ${printTypeValue(last_type)} but expected ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
780
775
|
}
|
|
781
776
|
if (ir.value.isAsync) {
|
|
782
777
|
return async (ctx) => {
|
|
@@ -799,15 +794,10 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
799
794
|
}
|
|
800
795
|
else {
|
|
801
796
|
const ctx2 = Object.create(ctx);
|
|
802
|
-
let last_type = variant("Null", null);
|
|
803
797
|
const compiled_statements = [];
|
|
804
798
|
for (const statement of ir.value.statements) {
|
|
805
799
|
const compiled_statement = compile_internal(statement, ctx2, platform, asyncPlatformFns, true, compilingNodes);
|
|
806
800
|
compiled_statements.push(compiled_statement);
|
|
807
|
-
last_type = statement.value.type;
|
|
808
|
-
}
|
|
809
|
-
if (!isSubtypeValue(last_type, ir.value.type)) {
|
|
810
|
-
throw new Error(`Block evaluates to type ${printTypeValue(last_type)} but expected ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
811
801
|
}
|
|
812
802
|
if (ir.value.isAsync) {
|
|
813
803
|
return async (ctx) => {
|
|
@@ -832,16 +822,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
832
822
|
}
|
|
833
823
|
}
|
|
834
824
|
else if (ir.type === "GetField") {
|
|
835
|
-
if (ir.value.struct.value.type.type !== "Struct") {
|
|
836
|
-
throw new Error(`GetField expected Struct, got ${printTypeValue(ir.value.struct.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
837
|
-
}
|
|
838
|
-
const struct_field = expandTypeValue(ir.value.struct.value.type).value.find(f => f.name === ir.value.field);
|
|
839
|
-
if (!struct_field) {
|
|
840
|
-
throw new Error(`GetField field ${ir.value.field} not found in struct ${printTypeValue(ir.value.struct.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
841
|
-
}
|
|
842
|
-
if (!isTypeValueEqual(struct_field.type, ir.value.type)) {
|
|
843
|
-
throw new Error(`GetField expected to have type ${printTypeValue(ir.value.type)}, got ${printTypeValue(struct_field.type)} at ${printLocationValue(ir.value.location)}`);
|
|
844
|
-
}
|
|
845
825
|
const struct = compile_internal(ir.value.struct, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
846
826
|
const field = ir.value.field;
|
|
847
827
|
if (ir.value.isAsync) {
|
|
@@ -852,17 +832,7 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
852
832
|
}
|
|
853
833
|
}
|
|
854
834
|
else if (ir.type === "Struct") {
|
|
855
|
-
|
|
856
|
-
throw new Error(`Expected Struct output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
857
|
-
}
|
|
858
|
-
const fields = ir.value.fields.map((f, i) => {
|
|
859
|
-
const struct_field = expandTypeValue(ir.value.type).value[i];
|
|
860
|
-
if (!struct_field || struct_field.name !== f.name) {
|
|
861
|
-
throw new Error(`Struct field ${f.name} not found at position ${i} in struct type ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
862
|
-
}
|
|
863
|
-
if (!isSubtypeValue(f.value.value.type, struct_field.type)) {
|
|
864
|
-
throw new Error(`Struct field ${f.name} expected to have type ${printTypeValue(struct_field.type)}, got ${printTypeValue(f.value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
865
|
-
}
|
|
835
|
+
const fields = ir.value.fields.map(f => {
|
|
866
836
|
return compile_internal(f.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
867
837
|
});
|
|
868
838
|
const keys = ir.value.fields.map(f => f.name);
|
|
@@ -880,17 +850,7 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
880
850
|
}
|
|
881
851
|
}
|
|
882
852
|
else if (ir.type === "Variant") {
|
|
883
|
-
if (ir.value.type.type !== "Variant") {
|
|
884
|
-
throw new Error(`Expected Variant output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
885
|
-
}
|
|
886
853
|
const k = ir.value.case;
|
|
887
|
-
const variant_case = expandTypeValue(ir.value.type).value.find(c => c.name === k);
|
|
888
|
-
if (!variant_case) {
|
|
889
|
-
throw new Error(`Variant case ${k} not found in variant type ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
890
|
-
}
|
|
891
|
-
if (!isSubtypeValue(ir.value.value.value.type, variant_case.type)) {
|
|
892
|
-
throw new Error(`Variant case ${k} expected to have type ${printTypeValue(variant_case.type)}, got ${printTypeValue(ir.value.value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
893
|
-
}
|
|
894
854
|
const v = compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
895
855
|
if (ir.value.isAsync) {
|
|
896
856
|
return async (ctx) => variant(k, await v(ctx));
|
|
@@ -900,12 +860,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
900
860
|
}
|
|
901
861
|
}
|
|
902
862
|
else if (ir.type === "NewRef") {
|
|
903
|
-
if (ir.value.type.type !== "Ref") {
|
|
904
|
-
throw new Error(`Expected Ref output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
905
|
-
}
|
|
906
|
-
if (!isSubtypeValue(ir.value.value.value.type, expandTypeValue(ir.value.type).value)) {
|
|
907
|
-
throw new Error(`NewRef value expected to have type ${printTypeValue(ir.value.type.value)}, got ${printTypeValue(ir.value.value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
908
|
-
}
|
|
909
863
|
const value = compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
910
864
|
if (ir.value.isAsync) {
|
|
911
865
|
return async (ctx) => ref(await value(ctx));
|
|
@@ -915,13 +869,7 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
915
869
|
}
|
|
916
870
|
}
|
|
917
871
|
else if (ir.type === "NewArray") {
|
|
918
|
-
if (ir.value.type.type !== "Array") {
|
|
919
|
-
throw new Error(`Expected Array output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
920
|
-
}
|
|
921
872
|
const values = ir.value.values.map(a => {
|
|
922
|
-
if (!isSubtypeValue(a.value.type, expandTypeValue(ir.value.type).value)) {
|
|
923
|
-
throw new Error(`NewArray element expected to have type ${printTypeValue(ir.value.type.value)}, got ${printTypeValue(a.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
924
|
-
}
|
|
925
873
|
return compile_internal(a, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
926
874
|
});
|
|
927
875
|
if (ir.value.isAsync) {
|
|
@@ -938,13 +886,7 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
938
886
|
}
|
|
939
887
|
}
|
|
940
888
|
else if (ir.type === "NewSet") {
|
|
941
|
-
if (ir.value.type.type !== "Set") {
|
|
942
|
-
throw new Error(`Expected Set output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
943
|
-
}
|
|
944
889
|
const values = ir.value.values.map(a => {
|
|
945
|
-
if (!isSubtypeValue(a.value.type, expandTypeValue(ir.value.type).value)) {
|
|
946
|
-
throw new Error(`NewSet element expected to have type ${printTypeValue(ir.value.type.value)}, got ${printTypeValue(a.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
947
|
-
}
|
|
948
890
|
return compile_internal(a, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
949
891
|
});
|
|
950
892
|
const keyComparer = compareFor(ir.value.type.value);
|
|
@@ -962,16 +904,7 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
962
904
|
}
|
|
963
905
|
}
|
|
964
906
|
else if (ir.type === "NewDict") {
|
|
965
|
-
if (ir.value.type.type !== "Dict") {
|
|
966
|
-
throw new Error(`Expected Dict output type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
967
|
-
}
|
|
968
907
|
const values = ir.value.values.map(({ key, value }) => {
|
|
969
|
-
if (!isSubtypeValue(key.value.type, expandTypeValue(ir.value.type).value.key)) {
|
|
970
|
-
throw new Error(`NewDict key expected to have type ${printTypeValue(ir.value.type.value.key)}, got ${printTypeValue(key.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
971
|
-
}
|
|
972
|
-
if (!isSubtypeValue(value.value.type, expandTypeValue(ir.value.type).value.value)) {
|
|
973
|
-
throw new Error(`NewDict value expected to have type ${printTypeValue(ir.value.type.value.value)}, got ${printTypeValue(value.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
974
|
-
}
|
|
975
908
|
return [compile_internal(key, ctx, platform, asyncPlatformFns, false, compilingNodes), compile_internal(value, ctx, platform, asyncPlatformFns, false, compilingNodes)];
|
|
976
909
|
});
|
|
977
910
|
const keyComparer = compareFor(ir.value.type.value.key);
|
|
@@ -989,10 +922,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
989
922
|
}
|
|
990
923
|
}
|
|
991
924
|
else if (ir.type === "Return") {
|
|
992
|
-
if (ir.value.type.type !== "Never") {
|
|
993
|
-
throw new Error(`Return must have Never type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
994
|
-
}
|
|
995
|
-
// TODO pipe through return type context so we can check it here
|
|
996
925
|
const compiled_value = compile_internal(ir.value.value, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
997
926
|
if (ir.value.isAsync) {
|
|
998
927
|
return async (ctx) => {
|
|
@@ -1006,61 +935,25 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
1006
935
|
}
|
|
1007
936
|
}
|
|
1008
937
|
else if (ir.type === "Continue") {
|
|
1009
|
-
if (ir.value.type.type !== "Never") {
|
|
1010
|
-
throw new Error(`Continue must have Never type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
1011
|
-
}
|
|
1012
938
|
const label = ir.value.label;
|
|
1013
|
-
// TODO pipe through local label context so we can check it here
|
|
1014
939
|
return (_ctx) => {
|
|
1015
940
|
throw new ContinueException(label.name);
|
|
1016
941
|
};
|
|
1017
942
|
}
|
|
1018
943
|
else if (ir.type === "Break") {
|
|
1019
|
-
if (ir.value.type.type !== "Never") {
|
|
1020
|
-
throw new Error(`Break must have Never type, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
1021
|
-
}
|
|
1022
944
|
const label = ir.value.label;
|
|
1023
|
-
// TODO pipe through local label context so we can check it here
|
|
1024
945
|
return (_ctx) => {
|
|
1025
946
|
throw new BreakException(label.name);
|
|
1026
947
|
};
|
|
1027
948
|
}
|
|
1028
949
|
else if (ir.type === "Builtin") {
|
|
1029
|
-
// TODO - I haven't dealt with builtins implementations yet
|
|
1030
|
-
// check types match
|
|
1031
|
-
let b = Builtins[ir.value.builtin];
|
|
1032
|
-
if (b === undefined) {
|
|
1033
|
-
throw new Error(`Builtin ${JSON.stringify(ir.value.builtin)} not found at ${printLocationValue(ir.value.location)}`);
|
|
1034
|
-
}
|
|
1035
|
-
if (b.type_parameters.length !== ir.value.type_parameters.length) {
|
|
1036
|
-
throw new Error(`Builtin ${JSON.stringify(ir.value.builtin)} expected ${b.type_parameters.length} type parameters, got ${ir.value.type_parameters.length} type parameters at ${printLocationValue(ir.value.location)}`);
|
|
1037
|
-
}
|
|
1038
|
-
if (b.inputs.length !== ir.value.arguments.length) {
|
|
1039
|
-
throw new Error(`Builtin ${JSON.stringify(ir.value.builtin)} expected ${b.inputs.length} arguments, got ${ir.value.arguments.length} arguments at ${printLocationValue(ir.value.location)}`);
|
|
1040
|
-
}
|
|
1041
|
-
const type_params = new Map(b.type_parameters.map((T, i) => [T, ir.value.type_parameters[i]]));
|
|
1042
950
|
let argsAsync = false;
|
|
1043
951
|
const args = ir.value.arguments.map((a, _i) => {
|
|
1044
|
-
// TODO these checks seem to fail for some builtins - particularly comparisons with recursive types
|
|
1045
|
-
// The issue appears to be that the type parameters in ir.value.type_parameters have been expanded too much
|
|
1046
|
-
// The Expr machinery and UnionType are possibly places to investigate why the identity of types is getting lost (or else we might need a more structural, not identity-based, approach to toEastTypeValue)
|
|
1047
|
-
// The failures here do not cause faults, but it might make life harder for a static compiler
|
|
1048
|
-
// const builtin_arg_type = b.inputs[i]!;
|
|
1049
|
-
// const expected_type = applyTypeParameters(toEastTypeValue(builtin_arg_type), type_params);
|
|
1050
|
-
// TODO what is the semantics here in a static language? Should we use `As` here?
|
|
1051
|
-
// if (!isSubtypeValue(a.value.type, expected_type)) {
|
|
1052
|
-
// throw new Error(`Argument ${i+1} to builtin ${JSON.stringify(ir.value.builtin)} with type parameters [${ir.value.type_parameters.map(t => printTypeValue(t)).join(", ")}] expected to have type ${printTypeValue(expected_type)}, got ${printTypeValue(a.value.type)} at ${printLocationValue(a.value.location)}`)
|
|
1053
|
-
// }
|
|
1054
952
|
if (a.value.isAsync) {
|
|
1055
953
|
argsAsync = true;
|
|
1056
954
|
}
|
|
1057
955
|
return compile_internal(a, ctx, platform, asyncPlatformFns, false, compilingNodes);
|
|
1058
956
|
});
|
|
1059
|
-
const expected_output_type = applyTypeParameters(typeof b.output === "string" ? b.output : toEastTypeValue(b.output), type_params);
|
|
1060
|
-
// TODO what is the semantics here in a static language? Should we use `As` here? What about variance?
|
|
1061
|
-
if (!isTypeValueEqual(ir.value.type, expected_output_type)) {
|
|
1062
|
-
throw new Error(`Builtin ${JSON.stringify(ir.value.builtin)} output type expected to have type ${printTypeValue(expected_output_type)}, got ${printTypeValue(ir.value.type)} at ${printLocationValue(ir.value.location)}`);
|
|
1063
|
-
}
|
|
1064
957
|
// Special optimization for regex builtins with literal pattern/flags
|
|
1065
958
|
if ((ir.value.builtin === "RegexContains" || ir.value.builtin === "RegexIndexOf" || ir.value.builtin === "RegexReplace") &&
|
|
1066
959
|
ir.value.arguments[1]?.type === "Value" &&
|
|
@@ -1249,7 +1142,6 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
1249
1142
|
}
|
|
1250
1143
|
}
|
|
1251
1144
|
else if (ir.type === "Platform") {
|
|
1252
|
-
// TODO check types match (would require having the platform's expected types here)
|
|
1253
1145
|
let argsAsync = false;
|
|
1254
1146
|
const args = ir.value.arguments.map(a => {
|
|
1255
1147
|
if (a.value.isAsync) {
|
|
@@ -1267,11 +1159,11 @@ function compileNodeInternal(ir, ctx, platform, asyncPlatformFns, fresh_ctx, com
|
|
|
1267
1159
|
for (const a of args) {
|
|
1268
1160
|
args_resolved.push(await a(ctx));
|
|
1269
1161
|
}
|
|
1270
|
-
return evaluator(...args_resolved);
|
|
1162
|
+
return evaluator(...args_resolved); // evaluator can return Promise unconditionally in tail position if the platform function is async
|
|
1271
1163
|
};
|
|
1272
1164
|
}
|
|
1273
1165
|
else {
|
|
1274
|
-
return (ctx) => evaluator(...args.map(a => a(ctx)));
|
|
1166
|
+
return (ctx) => evaluator(...args.map(a => a(ctx))); // evaluator can return Promise unconditionally in tail position if the platform function is async
|
|
1275
1167
|
}
|
|
1276
1168
|
}
|
|
1277
1169
|
else {
|
|
@@ -1697,6 +1589,28 @@ const builtin_evaluators = {
|
|
|
1697
1589
|
}
|
|
1698
1590
|
};
|
|
1699
1591
|
},
|
|
1592
|
+
BlobDecodeCsv: (location, structType, _configType) => {
|
|
1593
|
+
return (data, config) => {
|
|
1594
|
+
try {
|
|
1595
|
+
const decoder = decodeCsvFor(structType, config);
|
|
1596
|
+
return decoder(data);
|
|
1597
|
+
}
|
|
1598
|
+
catch (e) {
|
|
1599
|
+
throw new EastError(`Failed to decode CSV data: ${e.message}`, { location });
|
|
1600
|
+
}
|
|
1601
|
+
};
|
|
1602
|
+
},
|
|
1603
|
+
ArrayEncodeCsv: (location, structType, _configType) => {
|
|
1604
|
+
return (data, config) => {
|
|
1605
|
+
try {
|
|
1606
|
+
const encoder = encodeCsvFor(structType, config);
|
|
1607
|
+
return encoder(data);
|
|
1608
|
+
}
|
|
1609
|
+
catch (e) {
|
|
1610
|
+
throw new EastError(`Failed to encode CSV data: ${e.message}`, { location });
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
},
|
|
1700
1614
|
RefGet: (_location, _T) => (ref) => {
|
|
1701
1615
|
return ref.value;
|
|
1702
1616
|
},
|
|
@@ -3250,8 +3164,10 @@ export function applyTypeParameters(t, params) {
|
|
|
3250
3164
|
return t;
|
|
3251
3165
|
}
|
|
3252
3166
|
else if (t.type === "Function") {
|
|
3253
|
-
|
|
3254
|
-
|
|
3167
|
+
return variant("Function", { inputs: t.value.inputs.map(i => applyTypeParameters(i, params)), output: applyTypeParameters(t.value.output, params) });
|
|
3168
|
+
}
|
|
3169
|
+
else if (t.type === "AsyncFunction") {
|
|
3170
|
+
return variant("AsyncFunction", { inputs: t.value.inputs.map(i => applyTypeParameters(i, params)), output: applyTypeParameters(t.value.output, params) });
|
|
3255
3171
|
}
|
|
3256
3172
|
else {
|
|
3257
3173
|
throw new Error(`Unhandled type ${t.type}`);
|