@elaraai/east 0.0.1-beta.3 → 0.0.1-beta.31
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 +30 -8
- package/dist/src/analyze.d.ts +3 -0
- package/dist/src/analyze.d.ts.map +1 -1
- package/dist/src/analyze.js +76 -15
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/ast.d.ts +37 -33
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast_to_ir.d.ts +6 -0
- package/dist/src/ast_to_ir.d.ts.map +1 -1
- package/dist/src/ast_to_ir.js +135 -101
- 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 +32 -0
- package/dist/src/builtins.js.map +1 -1
- package/dist/src/comparison.d.ts.map +1 -1
- package/dist/src/comparison.js +12 -4
- package/dist/src/comparison.js.map +1 -1
- package/dist/src/compile.d.ts +26 -1
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +388 -257
- package/dist/src/compile.js.map +1 -1
- package/dist/src/datetime_format/types.d.ts +23 -23
- package/dist/src/eastir.d.ts +4 -0
- package/dist/src/eastir.d.ts.map +1 -1
- package/dist/src/eastir.js +27 -7
- package/dist/src/eastir.js.map +1 -1
- package/dist/src/error.d.ts +12 -1
- package/dist/src/error.d.ts.map +1 -1
- package/dist/src/error.js +31 -1
- package/dist/src/error.js.map +1 -1
- package/dist/src/expr/array.d.ts +109 -1
- package/dist/src/expr/array.d.ts.map +1 -1
- package/dist/src/expr/array.js +204 -44
- package/dist/src/expr/array.js.map +1 -1
- package/dist/src/expr/ast.d.ts +1 -1
- package/dist/src/expr/ast.d.ts.map +1 -1
- package/dist/src/expr/ast.js +16 -28
- package/dist/src/expr/ast.js.map +1 -1
- package/dist/src/expr/asyncfunction.js +1 -1
- package/dist/src/expr/asyncfunction.js.map +1 -1
- package/dist/src/expr/blob.d.ts +73 -1
- package/dist/src/expr/blob.d.ts.map +1 -1
- package/dist/src/expr/blob.js +97 -7
- package/dist/src/expr/blob.js.map +1 -1
- package/dist/src/expr/block.d.ts +232 -12
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +646 -140
- package/dist/src/expr/block.js.map +1 -1
- package/dist/src/expr/boolean.d.ts +44 -0
- package/dist/src/expr/boolean.d.ts.map +1 -1
- package/dist/src/expr/boolean.js +57 -5
- package/dist/src/expr/boolean.js.map +1 -1
- package/dist/src/expr/datetime.d.ts +135 -0
- package/dist/src/expr/datetime.d.ts.map +1 -1
- package/dist/src/expr/datetime.js +183 -33
- package/dist/src/expr/datetime.js.map +1 -1
- package/dist/src/expr/dict.d.ts +42 -0
- package/dist/src/expr/dict.d.ts.map +1 -1
- package/dist/src/expr/dict.js +105 -55
- package/dist/src/expr/dict.js.map +1 -1
- package/dist/src/expr/expr.d.ts +1 -1
- package/dist/src/expr/expr.d.ts.map +1 -1
- package/dist/src/expr/expr.js.map +1 -1
- package/dist/src/expr/float.d.ts +153 -0
- package/dist/src/expr/float.d.ts.map +1 -1
- package/dist/src/expr/float.js +190 -16
- package/dist/src/expr/float.js.map +1 -1
- package/dist/src/expr/function.d.ts +7 -2
- package/dist/src/expr/function.d.ts.map +1 -1
- package/dist/src/expr/function.js +1 -1
- package/dist/src/expr/function.js.map +1 -1
- package/dist/src/expr/index.d.ts +202 -2
- package/dist/src/expr/index.d.ts.map +1 -1
- package/dist/src/expr/index.js +207 -2
- package/dist/src/expr/index.js.map +1 -1
- package/dist/src/expr/integer.d.ts +180 -0
- package/dist/src/expr/integer.d.ts.map +1 -1
- package/dist/src/expr/integer.js +188 -17
- package/dist/src/expr/integer.js.map +1 -1
- package/dist/src/expr/libs/blob.js +2 -2
- package/dist/src/expr/libs/blob.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/string.js +1 -1
- package/dist/src/expr/libs/string.js.map +1 -1
- package/dist/src/expr/recursive.d.ts +83 -0
- package/dist/src/expr/recursive.d.ts.map +1 -0
- package/dist/src/expr/recursive.js +99 -0
- package/dist/src/expr/recursive.js.map +1 -0
- package/dist/src/expr/ref.js +3 -3
- package/dist/src/expr/ref.js.map +1 -1
- package/dist/src/expr/set.d.ts +44 -2
- package/dist/src/expr/set.d.ts.map +1 -1
- package/dist/src/expr/set.js +97 -47
- package/dist/src/expr/set.js.map +1 -1
- package/dist/src/expr/string.d.ts +134 -0
- package/dist/src/expr/string.d.ts.map +1 -1
- package/dist/src/expr/string.js +172 -22
- package/dist/src/expr/string.js.map +1 -1
- package/dist/src/expr/struct.d.ts +1 -1
- package/dist/src/expr/struct.d.ts.map +1 -1
- package/dist/src/expr/struct.js +1 -1
- package/dist/src/expr/struct.js.map +1 -1
- package/dist/src/expr/types.d.ts +7 -6
- package/dist/src/expr/types.d.ts.map +1 -1
- package/dist/src/expr/variant.d.ts +123 -1
- package/dist/src/expr/variant.d.ts.map +1 -1
- package/dist/src/expr/variant.js +66 -2
- package/dist/src/expr/variant.js.map +1 -1
- package/dist/src/fuzz.d.ts +36 -2
- package/dist/src/fuzz.d.ts.map +1 -1
- package/dist/src/fuzz.js +344 -77
- package/dist/src/fuzz.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/internal.d.ts +12 -0
- package/dist/src/internal.d.ts.map +1 -1
- package/dist/src/internal.js +13 -0
- package/dist/src/internal.js.map +1 -1
- package/dist/src/ir.d.ts +1551 -1505
- package/dist/src/ir.d.ts.map +1 -1
- package/dist/src/ir.js +49 -34
- package/dist/src/ir.js.map +1 -1
- package/dist/src/location.d.ts +30 -10
- package/dist/src/location.d.ts.map +1 -1
- package/dist/src/location.js +70 -28
- package/dist/src/location.js.map +1 -1
- package/dist/src/patch/apply.d.ts +15 -0
- package/dist/src/patch/apply.d.ts.map +1 -0
- package/dist/src/patch/apply.js +380 -0
- package/dist/src/patch/apply.js.map +1 -0
- package/dist/src/patch/compose.d.ts +15 -0
- package/dist/src/patch/compose.d.ts.map +1 -0
- package/dist/src/patch/compose.js +480 -0
- package/dist/src/patch/compose.js.map +1 -0
- package/dist/src/patch/diff.d.ts +15 -0
- package/dist/src/patch/diff.d.ts.map +1 -0
- package/dist/src/patch/diff.js +328 -0
- package/dist/src/patch/diff.js.map +1 -0
- package/dist/src/patch/fuzz.d.ts +73 -0
- package/dist/src/patch/fuzz.d.ts.map +1 -0
- package/dist/src/patch/fuzz.js +159 -0
- package/dist/src/patch/fuzz.js.map +1 -0
- package/dist/src/patch/index.d.ts +18 -0
- package/dist/src/patch/index.d.ts.map +1 -0
- package/dist/src/patch/index.js +20 -0
- package/dist/src/patch/index.js.map +1 -0
- package/dist/src/patch/invert.d.ts +15 -0
- package/dist/src/patch/invert.d.ts.map +1 -0
- package/dist/src/patch/invert.js +302 -0
- package/dist/src/patch/invert.js.map +1 -0
- package/dist/src/patch/type_of_patch.d.ts +17 -0
- package/dist/src/patch/type_of_patch.d.ts.map +1 -0
- package/dist/src/patch/type_of_patch.js +143 -0
- package/dist/src/patch/type_of_patch.js.map +1 -0
- package/dist/src/patch/types.d.ts +166 -0
- package/dist/src/patch/types.d.ts.map +1 -0
- package/dist/src/patch/types.js +69 -0
- package/dist/src/patch/types.js.map +1 -0
- package/dist/src/platform.d.ts +6 -0
- package/dist/src/platform.d.ts.map +1 -1
- package/dist/src/serialization/beast.d.ts.map +1 -1
- package/dist/src/serialization/beast.js +53 -18
- package/dist/src/serialization/beast.js.map +1 -1
- package/dist/src/serialization/beast2.d.ts +39 -3
- package/dist/src/serialization/beast2.d.ts.map +1 -1
- package/dist/src/serialization/beast2.js +241 -18
- 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/index.d.ts +2 -1
- package/dist/src/serialization/index.d.ts.map +1 -1
- package/dist/src/serialization/index.js +2 -1
- package/dist/src/serialization/index.js.map +1 -1
- package/dist/src/type_of_type.d.ts +45 -34
- package/dist/src/type_of_type.d.ts.map +1 -1
- package/dist/src/type_of_type.js +62 -1
- package/dist/src/type_of_type.js.map +1 -1
- package/dist/src/types.d.ts +8 -8
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js +4 -4
- package/dist/src/types.js.map +1 -1
- package/package.json +4 -5
package/dist/src/expr/block.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
4
|
*/
|
|
5
5
|
import {} from "../ast.js";
|
|
6
|
-
import { get_location,
|
|
6
|
+
import { get_location, printLocations } from "../location.js";
|
|
7
7
|
import { FunctionType, isSubtype, NullType, printType, isTypeEqual, StringType, NeverType, VariantType, BooleanType, TypeUnion, IntegerType, StructType, ArrayType, AsyncFunctionType } from "../types.js";
|
|
8
|
-
import { AstSymbol, Expr } from "./expr.js";
|
|
8
|
+
import { AstSymbol, Expr, TypeSymbol } from "./expr.js";
|
|
9
9
|
import { NeverExpr } from "./never.js";
|
|
10
10
|
import { NullExpr } from "./null.js";
|
|
11
11
|
import { BooleanExpr } from "./boolean.js";
|
|
@@ -19,11 +19,14 @@ import { SetExpr } from "./set.js";
|
|
|
19
19
|
import { DictExpr } from "./dict.js";
|
|
20
20
|
import { StructExpr } from "./struct.js";
|
|
21
21
|
import { VariantExpr } from "./variant.js";
|
|
22
|
-
import {
|
|
22
|
+
import { RecursiveExpr } from "./recursive.js";
|
|
23
|
+
import { createFunctionExpr, FunctionExpr } from "./function.js";
|
|
23
24
|
import { valueOrExprToAst, valueOrExprToAstTyped } from "./ast.js";
|
|
24
25
|
import { toEastTypeValue } from "../type_of_type.js";
|
|
26
|
+
import { isVariant } from "../containers/variant.js";
|
|
25
27
|
import { RefExpr } from "./ref.js";
|
|
26
|
-
import { createAsyncFunctionExpr } from "./asyncfunction.js";
|
|
28
|
+
import { AsyncFunctionExpr, createAsyncFunctionExpr } from "./asyncfunction.js";
|
|
29
|
+
import { PatchType } from "../patch/index.js";
|
|
27
30
|
/** A factory function to help build `Expr` from AST.
|
|
28
31
|
* We inject this into each concrete `Expr` type so they can create new expressions recursively, without having circular dependencies between JavaScript modules.
|
|
29
32
|
*/
|
|
@@ -72,14 +75,8 @@ export function fromAst(ast) {
|
|
|
72
75
|
return new VariantExpr(ast.type.cases, ast, fromAst);
|
|
73
76
|
}
|
|
74
77
|
else if (type === "Recursive") {
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
ast_type: "UnwrapRecursive",
|
|
78
|
-
type: ast.type.node,
|
|
79
|
-
location: ast.location,
|
|
80
|
-
value: ast,
|
|
81
|
-
};
|
|
82
|
-
return fromAst(as_ast);
|
|
78
|
+
// Return RecursiveExpr to preserve the RecursiveType wrapper for TypeOf
|
|
79
|
+
return new RecursiveExpr(ast.type.node, ast, fromAst);
|
|
83
80
|
}
|
|
84
81
|
else if (type === "Function") {
|
|
85
82
|
return createFunctionExpr(ast.type.inputs, ast.type.output, ast, fromAst);
|
|
@@ -88,9 +85,29 @@ export function fromAst(ast) {
|
|
|
88
85
|
return createAsyncFunctionExpr(ast.type.inputs, ast.type.output, ast, fromAst);
|
|
89
86
|
}
|
|
90
87
|
else {
|
|
91
|
-
throw new Error(`fromAst not implemented for type ${printType(ast.type)} at ${
|
|
88
|
+
throw new Error(`fromAst not implemented for type ${printType(ast.type)} at ${printLocations(ast.location)}`);
|
|
92
89
|
}
|
|
93
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* Compile a function expression into a JavaScript function.
|
|
93
|
+
*
|
|
94
|
+
* @param f the function expression to compile
|
|
95
|
+
* @param platform the platform functions available during compilation
|
|
96
|
+
* @returns the compiled function
|
|
97
|
+
*/
|
|
98
|
+
export function compile(f, platform) {
|
|
99
|
+
return f.toIR().compile(platform);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Compile an async function expression into a JavaScript function.
|
|
103
|
+
*
|
|
104
|
+
* @param f the async function expression to compile
|
|
105
|
+
* @param platform the platform functions available during compilation
|
|
106
|
+
* @returns the compiled async function
|
|
107
|
+
*/
|
|
108
|
+
export function compileAsync(f, platform) {
|
|
109
|
+
return f.toIR().compile(platform);
|
|
110
|
+
}
|
|
94
111
|
export function from(value, type) {
|
|
95
112
|
if (value instanceof Expr) {
|
|
96
113
|
if (type) {
|
|
@@ -110,7 +127,7 @@ export function from(value, type) {
|
|
|
110
127
|
const input_variables = inputs.map(i => ({
|
|
111
128
|
ast_type: "Variable",
|
|
112
129
|
type: i,
|
|
113
|
-
location: get_location(
|
|
130
|
+
location: get_location(),
|
|
114
131
|
mutable: false,
|
|
115
132
|
}));
|
|
116
133
|
const $ = BlockBuilder(output);
|
|
@@ -134,19 +151,19 @@ export function from(value, type) {
|
|
|
134
151
|
let body_ast;
|
|
135
152
|
if (isTypeEqual(output, NullType)) {
|
|
136
153
|
if (statements.length === 0) {
|
|
137
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
154
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
138
155
|
}
|
|
139
156
|
else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
|
|
140
157
|
body_ast = statements[0];
|
|
141
158
|
}
|
|
142
159
|
else {
|
|
143
160
|
if (!isSubtype(statements[statements.length - 1].type, NullType)) {
|
|
144
|
-
statements.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
161
|
+
statements.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
145
162
|
}
|
|
146
163
|
body_ast = {
|
|
147
164
|
ast_type: "Block",
|
|
148
165
|
type: statements[statements.length - 1].type,
|
|
149
|
-
location: get_location(
|
|
166
|
+
location: get_location(),
|
|
150
167
|
statements: statements,
|
|
151
168
|
};
|
|
152
169
|
}
|
|
@@ -168,7 +185,7 @@ export function from(value, type) {
|
|
|
168
185
|
body_ast = {
|
|
169
186
|
ast_type: "Block",
|
|
170
187
|
type: statements[statements.length - 1].type,
|
|
171
|
-
location: get_location(
|
|
188
|
+
location: get_location(),
|
|
172
189
|
statements: statements,
|
|
173
190
|
};
|
|
174
191
|
}
|
|
@@ -179,7 +196,7 @@ export function from(value, type) {
|
|
|
179
196
|
const ast = {
|
|
180
197
|
ast_type: "Function",
|
|
181
198
|
type: FunctionType(inputs, output),
|
|
182
|
-
location: get_location(
|
|
199
|
+
location: get_location(),
|
|
183
200
|
parameters: input_variables,
|
|
184
201
|
body: body_ast,
|
|
185
202
|
};
|
|
@@ -193,7 +210,7 @@ export function from(value, type) {
|
|
|
193
210
|
const input_variables = inputs.map(i => ({
|
|
194
211
|
ast_type: "Variable",
|
|
195
212
|
type: i,
|
|
196
|
-
location: get_location(
|
|
213
|
+
location: get_location(),
|
|
197
214
|
mutable: false,
|
|
198
215
|
}));
|
|
199
216
|
const $ = BlockBuilder(output);
|
|
@@ -217,19 +234,19 @@ export function from(value, type) {
|
|
|
217
234
|
let body_ast;
|
|
218
235
|
if (isTypeEqual(output, NullType)) {
|
|
219
236
|
if (statements.length === 0) {
|
|
220
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
237
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
221
238
|
}
|
|
222
239
|
else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
|
|
223
240
|
body_ast = statements[0];
|
|
224
241
|
}
|
|
225
242
|
else {
|
|
226
243
|
if (!isSubtype(statements[statements.length - 1].type, NullType)) {
|
|
227
|
-
statements.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
244
|
+
statements.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
228
245
|
}
|
|
229
246
|
body_ast = {
|
|
230
247
|
ast_type: "Block",
|
|
231
248
|
type: statements[statements.length - 1].type,
|
|
232
|
-
location: get_location(
|
|
249
|
+
location: get_location(),
|
|
233
250
|
statements: statements,
|
|
234
251
|
};
|
|
235
252
|
}
|
|
@@ -251,7 +268,7 @@ export function from(value, type) {
|
|
|
251
268
|
body_ast = {
|
|
252
269
|
ast_type: "Block",
|
|
253
270
|
type: statements[statements.length - 1].type,
|
|
254
|
-
location: get_location(
|
|
271
|
+
location: get_location(),
|
|
255
272
|
statements: statements,
|
|
256
273
|
};
|
|
257
274
|
}
|
|
@@ -262,7 +279,7 @@ export function from(value, type) {
|
|
|
262
279
|
const ast = {
|
|
263
280
|
ast_type: "AsyncFunction",
|
|
264
281
|
type: FunctionType(inputs, output),
|
|
265
|
-
location: get_location(
|
|
282
|
+
location: get_location(),
|
|
266
283
|
parameters: input_variables,
|
|
267
284
|
body: body_ast,
|
|
268
285
|
};
|
|
@@ -275,7 +292,7 @@ export function func(input_types, output_type, body) {
|
|
|
275
292
|
const parameters = input_types.map(i => ({
|
|
276
293
|
ast_type: "Variable",
|
|
277
294
|
type: i,
|
|
278
|
-
location: get_location(
|
|
295
|
+
location: get_location(),
|
|
279
296
|
mutable: false,
|
|
280
297
|
}));
|
|
281
298
|
const $ = BlockBuilder(output_type ?? NeverType);
|
|
@@ -292,7 +309,7 @@ export function func(input_types, output_type, body) {
|
|
|
292
309
|
const ret_type = ret_ast.type;
|
|
293
310
|
let body_ast;
|
|
294
311
|
if (statements.length === 0) {
|
|
295
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
312
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
296
313
|
}
|
|
297
314
|
else if (statements.length === 1) {
|
|
298
315
|
body_ast = statements[0];
|
|
@@ -301,7 +318,7 @@ export function func(input_types, output_type, body) {
|
|
|
301
318
|
body_ast = {
|
|
302
319
|
ast_type: "Block",
|
|
303
320
|
type: statements[statements.length - 1].type,
|
|
304
|
-
location: get_location(
|
|
321
|
+
location: get_location(),
|
|
305
322
|
statements: statements,
|
|
306
323
|
};
|
|
307
324
|
}
|
|
@@ -311,7 +328,7 @@ export function func(input_types, output_type, body) {
|
|
|
311
328
|
const ast = {
|
|
312
329
|
ast_type: "Function",
|
|
313
330
|
type: FunctionType(input_types, ret_type),
|
|
314
|
-
location: get_location(
|
|
331
|
+
location: get_location(),
|
|
315
332
|
parameters: parameters,
|
|
316
333
|
body: body_ast,
|
|
317
334
|
};
|
|
@@ -326,7 +343,7 @@ export function func(input_types, output_type, body) {
|
|
|
326
343
|
}
|
|
327
344
|
let body_ast;
|
|
328
345
|
if (statements.length === 0) {
|
|
329
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
346
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
330
347
|
}
|
|
331
348
|
else if (statements.length === 1) {
|
|
332
349
|
body_ast = statements[0];
|
|
@@ -335,7 +352,7 @@ export function func(input_types, output_type, body) {
|
|
|
335
352
|
body_ast = {
|
|
336
353
|
ast_type: "Block",
|
|
337
354
|
type: statements[statements.length - 1].type,
|
|
338
|
-
location: get_location(
|
|
355
|
+
location: get_location(),
|
|
339
356
|
statements: statements,
|
|
340
357
|
};
|
|
341
358
|
}
|
|
@@ -346,7 +363,7 @@ export function func(input_types, output_type, body) {
|
|
|
346
363
|
const ast = {
|
|
347
364
|
ast_type: "Function",
|
|
348
365
|
type: FunctionType(input_types, output_type),
|
|
349
|
-
location: get_location(
|
|
366
|
+
location: get_location(),
|
|
350
367
|
parameters: parameters,
|
|
351
368
|
body: body_ast,
|
|
352
369
|
};
|
|
@@ -357,7 +374,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
357
374
|
const parameters = input_types.map(i => ({
|
|
358
375
|
ast_type: "Variable",
|
|
359
376
|
type: i,
|
|
360
|
-
location: get_location(
|
|
377
|
+
location: get_location(),
|
|
361
378
|
mutable: false,
|
|
362
379
|
}));
|
|
363
380
|
const $ = BlockBuilder(output_type ?? NeverType);
|
|
@@ -374,7 +391,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
374
391
|
const ret_type = ret_ast.type;
|
|
375
392
|
let body_ast;
|
|
376
393
|
if (statements.length === 0) {
|
|
377
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
394
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
378
395
|
}
|
|
379
396
|
else if (statements.length === 1) {
|
|
380
397
|
body_ast = statements[0];
|
|
@@ -383,7 +400,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
383
400
|
body_ast = {
|
|
384
401
|
ast_type: "Block",
|
|
385
402
|
type: statements[statements.length - 1].type,
|
|
386
|
-
location: get_location(
|
|
403
|
+
location: get_location(),
|
|
387
404
|
statements: statements,
|
|
388
405
|
};
|
|
389
406
|
}
|
|
@@ -393,7 +410,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
393
410
|
const ast = {
|
|
394
411
|
ast_type: "AsyncFunction",
|
|
395
412
|
type: AsyncFunctionType(input_types, ret_type),
|
|
396
|
-
location: get_location(
|
|
413
|
+
location: get_location(),
|
|
397
414
|
parameters: parameters,
|
|
398
415
|
body: body_ast,
|
|
399
416
|
};
|
|
@@ -408,7 +425,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
408
425
|
}
|
|
409
426
|
let body_ast;
|
|
410
427
|
if (statements.length === 0) {
|
|
411
|
-
body_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
428
|
+
body_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
412
429
|
}
|
|
413
430
|
else if (statements.length === 1) {
|
|
414
431
|
body_ast = statements[0];
|
|
@@ -417,7 +434,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
417
434
|
body_ast = {
|
|
418
435
|
ast_type: "Block",
|
|
419
436
|
type: statements[statements.length - 1].type,
|
|
420
|
-
location: get_location(
|
|
437
|
+
location: get_location(),
|
|
421
438
|
statements: statements,
|
|
422
439
|
};
|
|
423
440
|
}
|
|
@@ -428,7 +445,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
428
445
|
const ast = {
|
|
429
446
|
ast_type: "AsyncFunction",
|
|
430
447
|
type: AsyncFunctionType(input_types, output_type),
|
|
431
|
-
location: get_location(
|
|
448
|
+
location: get_location(),
|
|
432
449
|
parameters: parameters,
|
|
433
450
|
body: body_ast,
|
|
434
451
|
};
|
|
@@ -443,7 +460,7 @@ export function asyncFunction(input_types, output_type, body) {
|
|
|
443
460
|
* ```
|
|
444
461
|
*/
|
|
445
462
|
export function str(strings, ...expressions) {
|
|
446
|
-
const location = get_location(
|
|
463
|
+
const location = get_location();
|
|
447
464
|
// For simple strings, e.g: str`abc`
|
|
448
465
|
if (strings.length === 1) {
|
|
449
466
|
return fromAst({
|
|
@@ -559,7 +576,7 @@ export function str(strings, ...expressions) {
|
|
|
559
576
|
let ret = {
|
|
560
577
|
ast_type: "Value",
|
|
561
578
|
type: StringType,
|
|
562
|
-
location: get_location(
|
|
579
|
+
location: get_location(),
|
|
563
580
|
value: strings[0],
|
|
564
581
|
};
|
|
565
582
|
for (let i = 1; i < strings.length; i++) {
|
|
@@ -654,7 +671,7 @@ export function block(body) {
|
|
|
654
671
|
if (statements.length === 0) {
|
|
655
672
|
return fromAst({
|
|
656
673
|
ast_type: "Value",
|
|
657
|
-
location: get_location(
|
|
674
|
+
location: get_location(),
|
|
658
675
|
type: ret_type,
|
|
659
676
|
value: null,
|
|
660
677
|
});
|
|
@@ -665,7 +682,7 @@ export function block(body) {
|
|
|
665
682
|
else {
|
|
666
683
|
return fromAst({
|
|
667
684
|
ast_type: "Block",
|
|
668
|
-
location: get_location(
|
|
685
|
+
location: get_location(),
|
|
669
686
|
type: ret_type,
|
|
670
687
|
statements: statements,
|
|
671
688
|
});
|
|
@@ -674,7 +691,7 @@ export function block(body) {
|
|
|
674
691
|
/**
|
|
675
692
|
* Create an East error expression
|
|
676
693
|
*/
|
|
677
|
-
export function error(message, location = get_location(
|
|
694
|
+
export function error(message, location = get_location()) {
|
|
678
695
|
const messageAst = message instanceof Expr ? Expr.ast(message) : valueOrExprToAstTyped(message, StringType);
|
|
679
696
|
return fromAst({
|
|
680
697
|
ast_type: "Error",
|
|
@@ -695,7 +712,7 @@ export function matchExpr(variant, handlers) {
|
|
|
695
712
|
const data_variable = {
|
|
696
713
|
ast_type: "Variable",
|
|
697
714
|
type: t,
|
|
698
|
-
location: get_location(
|
|
715
|
+
location: get_location(),
|
|
699
716
|
mutable: false,
|
|
700
717
|
};
|
|
701
718
|
const ast = handler === undefined ? valueOrExprToAstTyped(null, NullType) : block($ => handler($, fromAst(data_variable)))[AstSymbol];
|
|
@@ -706,7 +723,7 @@ export function matchExpr(variant, handlers) {
|
|
|
706
723
|
return fromAst({
|
|
707
724
|
ast_type: "Match",
|
|
708
725
|
type: out_type,
|
|
709
|
-
location: get_location(
|
|
726
|
+
location: get_location(),
|
|
710
727
|
variant: Expr.ast(variant),
|
|
711
728
|
cases: cases_out,
|
|
712
729
|
});
|
|
@@ -720,13 +737,13 @@ export function tryCatch(try_body, catch_body) {
|
|
|
720
737
|
const message_variable = {
|
|
721
738
|
ast_type: "Variable",
|
|
722
739
|
type: StringType,
|
|
723
|
-
location: get_location(
|
|
740
|
+
location: get_location(),
|
|
724
741
|
mutable: false,
|
|
725
742
|
};
|
|
726
743
|
const stack_variable = {
|
|
727
744
|
ast_type: "Variable",
|
|
728
745
|
type: ArrayType(StructType({ filename: StringType, line: IntegerType, column: IntegerType })),
|
|
729
|
-
location: get_location(
|
|
746
|
+
location: get_location(),
|
|
730
747
|
mutable: false,
|
|
731
748
|
};
|
|
732
749
|
if (typeof catch_body !== "function") {
|
|
@@ -739,7 +756,7 @@ export function tryCatch(try_body, catch_body) {
|
|
|
739
756
|
return fromAst({
|
|
740
757
|
ast_type: "TryCatch",
|
|
741
758
|
type: ret_type,
|
|
742
|
-
location: get_location(
|
|
759
|
+
location: get_location(),
|
|
743
760
|
try_body: Expr.ast(try_body),
|
|
744
761
|
catch_body: catch_body_ast,
|
|
745
762
|
message: message_variable,
|
|
@@ -752,7 +769,7 @@ export function equal(left, right) {
|
|
|
752
769
|
return fromAst({
|
|
753
770
|
ast_type: "Builtin",
|
|
754
771
|
type: BooleanType,
|
|
755
|
-
location: get_location(
|
|
772
|
+
location: get_location(),
|
|
756
773
|
builtin: "Equal",
|
|
757
774
|
type_parameters: [Expr.type(left)],
|
|
758
775
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -764,7 +781,7 @@ export function notEqual(left, right) {
|
|
|
764
781
|
return fromAst({
|
|
765
782
|
ast_type: "Builtin",
|
|
766
783
|
type: BooleanType,
|
|
767
|
-
location: get_location(
|
|
784
|
+
location: get_location(),
|
|
768
785
|
builtin: "NotEqual",
|
|
769
786
|
type_parameters: [Expr.type(left)],
|
|
770
787
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -776,7 +793,7 @@ export function less(left, right) {
|
|
|
776
793
|
return fromAst({
|
|
777
794
|
ast_type: "Builtin",
|
|
778
795
|
type: BooleanType,
|
|
779
|
-
location: get_location(
|
|
796
|
+
location: get_location(),
|
|
780
797
|
builtin: "Less",
|
|
781
798
|
type_parameters: [Expr.type(left)],
|
|
782
799
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -788,7 +805,7 @@ export function lessEqual(left, right) {
|
|
|
788
805
|
return fromAst({
|
|
789
806
|
ast_type: "Builtin",
|
|
790
807
|
type: BooleanType,
|
|
791
|
-
location: get_location(
|
|
808
|
+
location: get_location(),
|
|
792
809
|
builtin: "LessEqual",
|
|
793
810
|
type_parameters: [Expr.type(left)],
|
|
794
811
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -800,7 +817,7 @@ export function greater(left, right) {
|
|
|
800
817
|
return fromAst({
|
|
801
818
|
ast_type: "Builtin",
|
|
802
819
|
type: BooleanType,
|
|
803
|
-
location: get_location(
|
|
820
|
+
location: get_location(),
|
|
804
821
|
builtin: "Greater",
|
|
805
822
|
type_parameters: [Expr.type(left)],
|
|
806
823
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -812,12 +829,43 @@ export function greaterEqual(left, right) {
|
|
|
812
829
|
return fromAst({
|
|
813
830
|
ast_type: "Builtin",
|
|
814
831
|
type: BooleanType,
|
|
815
|
-
location: get_location(
|
|
832
|
+
location: get_location(),
|
|
816
833
|
builtin: "GreaterEqual",
|
|
817
834
|
type_parameters: [Expr.type(left)],
|
|
818
835
|
arguments: [Expr.ast(left), rightAst],
|
|
819
836
|
});
|
|
820
837
|
}
|
|
838
|
+
// ============================================================================
|
|
839
|
+
// Aliases for standalone comparison functions
|
|
840
|
+
// ============================================================================
|
|
841
|
+
/** Alias for {@link equal} */
|
|
842
|
+
export const equals = equal;
|
|
843
|
+
/** Alias for {@link equal} */
|
|
844
|
+
export const eq = equal;
|
|
845
|
+
/** Alias for {@link notEqual} */
|
|
846
|
+
export const notEquals = notEqual;
|
|
847
|
+
/** Alias for {@link notEqual} */
|
|
848
|
+
export const ne = notEqual;
|
|
849
|
+
/** Alias for {@link less} */
|
|
850
|
+
export const lessThan = less;
|
|
851
|
+
/** Alias for {@link less} */
|
|
852
|
+
export const lt = less;
|
|
853
|
+
/** Alias for {@link lessEqual} */
|
|
854
|
+
export const lessThanOrEqual = lessEqual;
|
|
855
|
+
/** Alias for {@link lessEqual} */
|
|
856
|
+
export const lte = lessEqual;
|
|
857
|
+
/** Alias for {@link lessEqual} */
|
|
858
|
+
export const le = lessEqual;
|
|
859
|
+
/** Alias for {@link greater} */
|
|
860
|
+
export const greaterThan = greater;
|
|
861
|
+
/** Alias for {@link greater} */
|
|
862
|
+
export const gt = greater;
|
|
863
|
+
/** Alias for {@link greaterEqual} */
|
|
864
|
+
export const greaterThanOrEqual = greaterEqual;
|
|
865
|
+
/** Alias for {@link greaterEqual} */
|
|
866
|
+
export const gte = greaterEqual;
|
|
867
|
+
/** Alias for {@link greaterEqual} */
|
|
868
|
+
export const ge = greaterEqual;
|
|
821
869
|
/** Test if the first value is the same object the second.
|
|
822
870
|
* For mutable collections, such as arrays, this means that they are the same object in memory.
|
|
823
871
|
* For immutable data types, such as integers and strings, this is equivalent to equality.
|
|
@@ -827,7 +875,7 @@ export function is(left, right) {
|
|
|
827
875
|
return fromAst({
|
|
828
876
|
ast_type: "Builtin",
|
|
829
877
|
type: BooleanType,
|
|
830
|
-
location: get_location(
|
|
878
|
+
location: get_location(),
|
|
831
879
|
builtin: "Is",
|
|
832
880
|
type_parameters: [Expr.type(left)],
|
|
833
881
|
arguments: [Expr.ast(left), rightAst],
|
|
@@ -839,12 +887,83 @@ export function print(value) {
|
|
|
839
887
|
return fromAst({
|
|
840
888
|
ast_type: "Builtin",
|
|
841
889
|
type: StringType,
|
|
842
|
-
location: get_location(
|
|
890
|
+
location: get_location(),
|
|
843
891
|
builtin: "Print",
|
|
844
892
|
type_parameters: [valueAst.type],
|
|
845
893
|
arguments: [valueAst],
|
|
846
894
|
});
|
|
847
895
|
}
|
|
896
|
+
// ============================================================================
|
|
897
|
+
// Patch Operations
|
|
898
|
+
// ============================================================================
|
|
899
|
+
/** Compute the difference between two values of the same type.
|
|
900
|
+
* Returns a patch that, when applied to `before`, produces `after`.
|
|
901
|
+
*/
|
|
902
|
+
export function diff(before, after) {
|
|
903
|
+
const beforeAst = Expr.ast(before);
|
|
904
|
+
const afterAst = Expr.ast(after);
|
|
905
|
+
const valueType = beforeAst.type;
|
|
906
|
+
const patchType = PatchType(valueType);
|
|
907
|
+
return fromAst({
|
|
908
|
+
ast_type: "Builtin",
|
|
909
|
+
type: patchType,
|
|
910
|
+
location: get_location(),
|
|
911
|
+
builtin: "Diff",
|
|
912
|
+
type_parameters: [valueType, patchType],
|
|
913
|
+
arguments: [beforeAst, afterAst],
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
/** Apply a patch to a value, producing the modified value.
|
|
917
|
+
* @throws East runtime error if the patch conflicts with the value (e.g., deleting a non-existent key)
|
|
918
|
+
*/
|
|
919
|
+
export function applyPatch(value, patch) {
|
|
920
|
+
const valueAst = Expr.ast(value);
|
|
921
|
+
const patchAst = Expr.ast(patch);
|
|
922
|
+
const valueType = valueAst.type;
|
|
923
|
+
const patchType = patchAst.type;
|
|
924
|
+
return fromAst({
|
|
925
|
+
ast_type: "Builtin",
|
|
926
|
+
type: valueType,
|
|
927
|
+
location: get_location(),
|
|
928
|
+
builtin: "ApplyPatch",
|
|
929
|
+
type_parameters: [valueType, patchType],
|
|
930
|
+
arguments: [valueAst, patchAst],
|
|
931
|
+
});
|
|
932
|
+
}
|
|
933
|
+
/** Compose two patches into a single patch.
|
|
934
|
+
* The result is a patch that has the same effect as applying `first` then `second`.
|
|
935
|
+
* @throws East runtime error if the patches are incompatible (second expects different intermediate state)
|
|
936
|
+
*/
|
|
937
|
+
export function composePatch(first, second, type) {
|
|
938
|
+
const firstAst = Expr.ast(first);
|
|
939
|
+
const secondAst = Expr.ast(second);
|
|
940
|
+
const valueType = type;
|
|
941
|
+
const patchType = PatchType(valueType);
|
|
942
|
+
return fromAst({
|
|
943
|
+
ast_type: "Builtin",
|
|
944
|
+
type: patchType,
|
|
945
|
+
location: get_location(),
|
|
946
|
+
builtin: "ComposePatch",
|
|
947
|
+
type_parameters: [valueType, patchType],
|
|
948
|
+
arguments: [firstAst, secondAst],
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
/** Invert a patch, producing a patch that undoes the original.
|
|
952
|
+
* Applying the inverted patch to the "after" value produces the "before" value.
|
|
953
|
+
*/
|
|
954
|
+
export function invertPatch(patch, type) {
|
|
955
|
+
const patchAst = Expr.ast(patch);
|
|
956
|
+
const valueType = type;
|
|
957
|
+
const patchType = PatchType(valueType);
|
|
958
|
+
return fromAst({
|
|
959
|
+
ast_type: "Builtin",
|
|
960
|
+
type: patchType,
|
|
961
|
+
location: get_location(),
|
|
962
|
+
builtin: "InvertPatch",
|
|
963
|
+
type_parameters: [valueType, patchType],
|
|
964
|
+
arguments: [patchAst],
|
|
965
|
+
});
|
|
966
|
+
}
|
|
848
967
|
/** Create a callable helper to invoke a synchronous platform function.
|
|
849
968
|
*
|
|
850
969
|
* Platform functions provide access to external capabilities (logging, I/O, database access, etc.)
|
|
@@ -853,6 +972,7 @@ export function print(value) {
|
|
|
853
972
|
* @param name - The name of the platform function
|
|
854
973
|
* @param input_types - Array of input parameter types for the platform function
|
|
855
974
|
* @param output_type - The return type of the platform function
|
|
975
|
+
* @param options - Optional configuration for the platform function
|
|
856
976
|
* @returns A callable function that creates Platform AST nodes when invoked
|
|
857
977
|
*
|
|
858
978
|
* @see {@link asyncPlatform} for defining asynchronous platform functions (that return `Promise`s)
|
|
@@ -870,13 +990,23 @@ const myFunction = East.function([], NullType, ($) => {
|
|
|
870
990
|
|
|
871
991
|
// Provide the implementation when compiling
|
|
872
992
|
const platform = [
|
|
873
|
-
log.implement(
|
|
993
|
+
log.implement((message: string) => console.log(message)),
|
|
874
994
|
];
|
|
875
995
|
const compiled = myFunction.toIR().compile(platform);
|
|
876
996
|
compiled(); // Logs "Hello, world!" to the console
|
|
997
|
+
* ```
|
|
998
|
+
*
|
|
999
|
+
* @example
|
|
1000
|
+
* ```ts
|
|
1001
|
+
// Define an optional platform function that may not be available
|
|
1002
|
+
const analytics = East.platform("analytics", [StringType], NullType, { optional: true });
|
|
1003
|
+
|
|
1004
|
+
// This compiles even without providing an analytics implementation
|
|
1005
|
+
// If called at runtime without implementation, it throws an error
|
|
877
1006
|
* ```
|
|
878
1007
|
*/
|
|
879
|
-
export function platform(name, input_types, output_type) {
|
|
1008
|
+
export function platform(name, input_types, output_type, options = {}) {
|
|
1009
|
+
const isOptional = options.optional ?? false;
|
|
880
1010
|
const fn = (...args) => {
|
|
881
1011
|
if (args.length !== input_types.length) {
|
|
882
1012
|
throw new Error(`Platform function ${name} expected ${input_types.length} arguments, got ${args.length}`);
|
|
@@ -895,7 +1025,7 @@ export function platform(name, input_types, output_type) {
|
|
|
895
1025
|
ast = {
|
|
896
1026
|
ast_type: "As",
|
|
897
1027
|
type: expectedType,
|
|
898
|
-
location: get_location(
|
|
1028
|
+
location: get_location(),
|
|
899
1029
|
value: ast,
|
|
900
1030
|
};
|
|
901
1031
|
}
|
|
@@ -904,10 +1034,12 @@ export function platform(name, input_types, output_type) {
|
|
|
904
1034
|
return fromAst({
|
|
905
1035
|
ast_type: "Platform",
|
|
906
1036
|
type: output_type,
|
|
907
|
-
location: get_location(
|
|
1037
|
+
location: get_location(),
|
|
908
1038
|
name: name,
|
|
1039
|
+
type_parameters: [],
|
|
909
1040
|
arguments: argAsts,
|
|
910
1041
|
async: false,
|
|
1042
|
+
optional: isOptional,
|
|
911
1043
|
});
|
|
912
1044
|
};
|
|
913
1045
|
fn.implement = (fnImpl) => {
|
|
@@ -943,6 +1075,7 @@ export function platform(name, input_types, output_type) {
|
|
|
943
1075
|
* @param name - The name of the asynchronous platform function
|
|
944
1076
|
* @param input_types - Array of input parameter types for the platform function
|
|
945
1077
|
* @param output_type - The return type of the platform function
|
|
1078
|
+
* @param options - Optional configuration for the platform function
|
|
946
1079
|
* @returns A callable function that creates Platform AST nodes when invoked
|
|
947
1080
|
*
|
|
948
1081
|
* @see {@link platform} for defining synchronous platform functions
|
|
@@ -962,10 +1095,11 @@ const platform = [
|
|
|
962
1095
|
readFile.implement((filename: string) => fs.promises.readFile(filename, 'utf-8')),
|
|
963
1096
|
];
|
|
964
1097
|
const compiled = myFunction.toIR().compile(platform);
|
|
965
|
-
compiled(); //
|
|
1098
|
+
compiled(); // Returns file contents
|
|
966
1099
|
* ```
|
|
967
1100
|
*/
|
|
968
|
-
export function asyncPlatform(name, input_types, output_type) {
|
|
1101
|
+
export function asyncPlatform(name, input_types, output_type, options = {}) {
|
|
1102
|
+
const isOptional = options.optional ?? false;
|
|
969
1103
|
const fn = (...args) => {
|
|
970
1104
|
if (args.length !== input_types.length) {
|
|
971
1105
|
throw new Error(`Platform function ${name} expected ${input_types.length} arguments, got ${args.length}`);
|
|
@@ -984,7 +1118,7 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
984
1118
|
ast = {
|
|
985
1119
|
ast_type: "As",
|
|
986
1120
|
type: expectedType,
|
|
987
|
-
location: get_location(
|
|
1121
|
+
location: get_location(),
|
|
988
1122
|
value: ast,
|
|
989
1123
|
};
|
|
990
1124
|
}
|
|
@@ -993,10 +1127,12 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
993
1127
|
return fromAst({
|
|
994
1128
|
ast_type: "Platform",
|
|
995
1129
|
type: output_type,
|
|
996
|
-
location: get_location(
|
|
1130
|
+
location: get_location(),
|
|
997
1131
|
name: name,
|
|
1132
|
+
type_parameters: [],
|
|
998
1133
|
arguments: argAsts,
|
|
999
1134
|
async: true,
|
|
1135
|
+
optional: isOptional,
|
|
1000
1136
|
});
|
|
1001
1137
|
};
|
|
1002
1138
|
fn.implement = (fnImpl) => {
|
|
@@ -1024,12 +1160,356 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
1024
1160
|
};
|
|
1025
1161
|
return fn;
|
|
1026
1162
|
}
|
|
1163
|
+
// Runtime type substitution function
|
|
1164
|
+
function applyTypeArgs(typeArgs, t) {
|
|
1165
|
+
if (typeof t === 'string') {
|
|
1166
|
+
const ret = typeArgs[t];
|
|
1167
|
+
if (ret === undefined) {
|
|
1168
|
+
throw new Error(`Unexpected type argument ${t}`);
|
|
1169
|
+
}
|
|
1170
|
+
return ret;
|
|
1171
|
+
}
|
|
1172
|
+
else if (t.type === "Ref") {
|
|
1173
|
+
return { type: "Ref", value: applyTypeArgs(typeArgs, t.value) };
|
|
1174
|
+
}
|
|
1175
|
+
else if (t.type === "Array") {
|
|
1176
|
+
return { type: "Array", value: applyTypeArgs(typeArgs, t.value) };
|
|
1177
|
+
}
|
|
1178
|
+
else if (t.type === "Set") {
|
|
1179
|
+
return { type: "Set", key: applyTypeArgs(typeArgs, t.key) };
|
|
1180
|
+
}
|
|
1181
|
+
else if (t.type === "Dict") {
|
|
1182
|
+
return { type: "Dict", key: applyTypeArgs(typeArgs, t.key), value: applyTypeArgs(typeArgs, t.value) };
|
|
1183
|
+
}
|
|
1184
|
+
else if (t.type === "Struct") {
|
|
1185
|
+
const newFields = {};
|
|
1186
|
+
for (const k in t.fields) {
|
|
1187
|
+
newFields[k] = applyTypeArgs(typeArgs, t.fields[k]);
|
|
1188
|
+
}
|
|
1189
|
+
return { type: "Struct", fields: newFields };
|
|
1190
|
+
}
|
|
1191
|
+
else if (t.type === "Variant") {
|
|
1192
|
+
const newCases = {};
|
|
1193
|
+
for (const k in t.cases) {
|
|
1194
|
+
newCases[k] = applyTypeArgs(typeArgs, t.cases[k]);
|
|
1195
|
+
}
|
|
1196
|
+
return { type: "Variant", cases: newCases };
|
|
1197
|
+
}
|
|
1198
|
+
else if (t.type === "Function") {
|
|
1199
|
+
const newInputs = t.inputs.map((inputType) => applyTypeArgs(typeArgs, inputType));
|
|
1200
|
+
const newOutput = applyTypeArgs(typeArgs, t.output);
|
|
1201
|
+
return { type: "Function", inputs: newInputs, output: newOutput };
|
|
1202
|
+
}
|
|
1203
|
+
else if (t.type === "Recursive") {
|
|
1204
|
+
if (t.node === undefined) {
|
|
1205
|
+
// RecursiveTypeMarker (self-reference) - leave alone
|
|
1206
|
+
return t;
|
|
1207
|
+
}
|
|
1208
|
+
return { type: "Recursive", node: applyTypeArgs(typeArgs, t.node) };
|
|
1209
|
+
}
|
|
1210
|
+
else {
|
|
1211
|
+
return t;
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
/** Create a callable helper to invoke a generic (polymorphic) platform function.
|
|
1215
|
+
*
|
|
1216
|
+
* Generic platform functions allow you to define platform functions with type parameters,
|
|
1217
|
+
* similar to how builtins work. The type parameters are passed at call time and flow
|
|
1218
|
+
* through to the implementation.
|
|
1219
|
+
*
|
|
1220
|
+
* @param name - The name of the platform function
|
|
1221
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1222
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1223
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1224
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1225
|
+
*
|
|
1226
|
+
* @example
|
|
1227
|
+
* ```ts
|
|
1228
|
+
* // Define a generic log function
|
|
1229
|
+
* const log = East.genericPlatform(
|
|
1230
|
+
* "log",
|
|
1231
|
+
* ["T"],
|
|
1232
|
+
* ["T"], // Input is type parameter T
|
|
1233
|
+
* NullType
|
|
1234
|
+
* );
|
|
1235
|
+
*
|
|
1236
|
+
* // Use it in East code - type args as array, then value args
|
|
1237
|
+
* const myFunction = East.function([StringType], NullType, ($, s) => {
|
|
1238
|
+
* $(log([StringType], s));
|
|
1239
|
+
* });
|
|
1240
|
+
*
|
|
1241
|
+
* // Implementation receives type params as a factory
|
|
1242
|
+
* const platform = [
|
|
1243
|
+
* log.implement((T) => (value) => {
|
|
1244
|
+
* console.log(printFor(T)(value));
|
|
1245
|
+
* return null;
|
|
1246
|
+
* }),
|
|
1247
|
+
* ];
|
|
1248
|
+
* ```
|
|
1249
|
+
*
|
|
1250
|
+
* @example
|
|
1251
|
+
* ```ts
|
|
1252
|
+
* // Define a generic map function with 2 type parameters
|
|
1253
|
+
* const map = East.genericPlatform(
|
|
1254
|
+
* "map",
|
|
1255
|
+
* ["T", "U"],
|
|
1256
|
+
* ["T", FunctionType(["T"], "U")], // String placeholders in nested types
|
|
1257
|
+
* "U"
|
|
1258
|
+
* );
|
|
1259
|
+
*
|
|
1260
|
+
* // Call with type args array, then value arguments
|
|
1261
|
+
* map([StringType, IntegerType], myString, myMapperFn)
|
|
1262
|
+
* ```
|
|
1263
|
+
*/
|
|
1264
|
+
export function genericPlatform(name, typeParams, inputs, output, options = {}) {
|
|
1265
|
+
const numTypeParams = typeParams.length;
|
|
1266
|
+
const isOptional = options.optional ?? false;
|
|
1267
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1268
|
+
// Validate type args array
|
|
1269
|
+
if (!Array.isArray(type_args)) {
|
|
1270
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1271
|
+
`got ${typeof type_args}`);
|
|
1272
|
+
}
|
|
1273
|
+
// Validate type args count
|
|
1274
|
+
if (type_args.length !== numTypeParams) {
|
|
1275
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1276
|
+
`got ${type_args.length}`);
|
|
1277
|
+
}
|
|
1278
|
+
// Validate type args are EastTypes
|
|
1279
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1280
|
+
const typeArg = type_args[i];
|
|
1281
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1282
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1283
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
// Build type argument map
|
|
1287
|
+
const typeArgMap = {};
|
|
1288
|
+
typeParams.forEach((param, idx) => {
|
|
1289
|
+
typeArgMap[param] = type_args[idx];
|
|
1290
|
+
});
|
|
1291
|
+
// Apply type substitution to get concrete input/output types
|
|
1292
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1293
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1294
|
+
// Validate value args count
|
|
1295
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1296
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1297
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1298
|
+
}
|
|
1299
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1300
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1301
|
+
const expectedType = inputTypes[index];
|
|
1302
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1303
|
+
if (ast.type.type === "Never") {
|
|
1304
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1305
|
+
}
|
|
1306
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1307
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1308
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1309
|
+
}
|
|
1310
|
+
// Insert implicit cast
|
|
1311
|
+
ast = {
|
|
1312
|
+
ast_type: "As",
|
|
1313
|
+
type: expectedType,
|
|
1314
|
+
location: get_location(),
|
|
1315
|
+
value: ast,
|
|
1316
|
+
};
|
|
1317
|
+
}
|
|
1318
|
+
return ast;
|
|
1319
|
+
});
|
|
1320
|
+
// Create PlatformAST with type_parameters
|
|
1321
|
+
return fromAst({
|
|
1322
|
+
ast_type: "Platform",
|
|
1323
|
+
type: outputType,
|
|
1324
|
+
location: get_location(),
|
|
1325
|
+
name: name,
|
|
1326
|
+
type_parameters: type_args,
|
|
1327
|
+
arguments: argAsts,
|
|
1328
|
+
async: false,
|
|
1329
|
+
optional: isOptional,
|
|
1330
|
+
});
|
|
1331
|
+
};
|
|
1332
|
+
fn.implement = (factory) => {
|
|
1333
|
+
return {
|
|
1334
|
+
name,
|
|
1335
|
+
type_parameters: [...typeParams],
|
|
1336
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1337
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1338
|
+
inputsFn: (...tps) => {
|
|
1339
|
+
const typeArgMap = {};
|
|
1340
|
+
typeParams.forEach((param, idx) => {
|
|
1341
|
+
typeArgMap[param] = tps[idx];
|
|
1342
|
+
});
|
|
1343
|
+
return inputs.map(t => {
|
|
1344
|
+
if (typeof t === 'string')
|
|
1345
|
+
return typeArgMap[t];
|
|
1346
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1347
|
+
if (!isVariant(result))
|
|
1348
|
+
result = toEastTypeValue(result);
|
|
1349
|
+
return result;
|
|
1350
|
+
});
|
|
1351
|
+
},
|
|
1352
|
+
outputsFn: (...tps) => {
|
|
1353
|
+
const typeArgMap = {};
|
|
1354
|
+
typeParams.forEach((param, idx) => {
|
|
1355
|
+
typeArgMap[param] = tps[idx];
|
|
1356
|
+
});
|
|
1357
|
+
if (typeof output === 'string')
|
|
1358
|
+
return typeArgMap[output];
|
|
1359
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1360
|
+
if (!isVariant(result))
|
|
1361
|
+
result = toEastTypeValue(result);
|
|
1362
|
+
return result;
|
|
1363
|
+
},
|
|
1364
|
+
type: 'sync',
|
|
1365
|
+
fn: factory,
|
|
1366
|
+
};
|
|
1367
|
+
};
|
|
1368
|
+
return fn;
|
|
1369
|
+
}
|
|
1370
|
+
/** Create a callable helper to invoke an asynchronous generic (polymorphic) platform function.
|
|
1371
|
+
*
|
|
1372
|
+
* This is the async variant of `genericPlatform`. The implementation factory should return
|
|
1373
|
+
* an async function.
|
|
1374
|
+
*
|
|
1375
|
+
* @param name - The name of the platform function
|
|
1376
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1377
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1378
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1379
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1380
|
+
*
|
|
1381
|
+
* @see {@link genericPlatform} for synchronous generic platform functions
|
|
1382
|
+
*
|
|
1383
|
+
* @example
|
|
1384
|
+
* ```ts
|
|
1385
|
+
* // Define an async generic fetch function
|
|
1386
|
+
* const fetchAs = East.asyncGenericPlatform(
|
|
1387
|
+
* "fetchAs",
|
|
1388
|
+
* ["T"],
|
|
1389
|
+
* [StringType], // URL input
|
|
1390
|
+
* "T" // Returns parsed value of type T
|
|
1391
|
+
* );
|
|
1392
|
+
*
|
|
1393
|
+
* // Implementation receives type params and returns async function
|
|
1394
|
+
* const platform = [
|
|
1395
|
+
* fetchAs.implement((T) => async (url) => {
|
|
1396
|
+
* const response = await fetch(url);
|
|
1397
|
+
* return parseFor(T)(await response.text());
|
|
1398
|
+
* }),
|
|
1399
|
+
* ];
|
|
1400
|
+
* ```
|
|
1401
|
+
*/
|
|
1402
|
+
export function asyncGenericPlatform(name, typeParams, inputs, output, options = {}) {
|
|
1403
|
+
const numTypeParams = typeParams.length;
|
|
1404
|
+
const isOptional = options.optional ?? false;
|
|
1405
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1406
|
+
// Validate type args array
|
|
1407
|
+
if (!Array.isArray(type_args)) {
|
|
1408
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1409
|
+
`got ${typeof type_args}`);
|
|
1410
|
+
}
|
|
1411
|
+
// Validate type args count
|
|
1412
|
+
if (type_args.length !== numTypeParams) {
|
|
1413
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1414
|
+
`got ${type_args.length}`);
|
|
1415
|
+
}
|
|
1416
|
+
// Validate type args are EastTypes
|
|
1417
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1418
|
+
const typeArg = type_args[i];
|
|
1419
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1420
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1421
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
// Build type argument map
|
|
1425
|
+
const typeArgMap = {};
|
|
1426
|
+
typeParams.forEach((param, idx) => {
|
|
1427
|
+
typeArgMap[param] = type_args[idx];
|
|
1428
|
+
});
|
|
1429
|
+
// Apply type substitution to get concrete input/output types
|
|
1430
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1431
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1432
|
+
// Validate value args count
|
|
1433
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1434
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1435
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1436
|
+
}
|
|
1437
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1438
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1439
|
+
const expectedType = inputTypes[index];
|
|
1440
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1441
|
+
if (ast.type.type === "Never") {
|
|
1442
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1443
|
+
}
|
|
1444
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1445
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1446
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1447
|
+
}
|
|
1448
|
+
// Insert implicit cast
|
|
1449
|
+
ast = {
|
|
1450
|
+
ast_type: "As",
|
|
1451
|
+
type: expectedType,
|
|
1452
|
+
location: get_location(),
|
|
1453
|
+
value: ast,
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
return ast;
|
|
1457
|
+
});
|
|
1458
|
+
// Create PlatformAST with type_parameters and async: true
|
|
1459
|
+
return fromAst({
|
|
1460
|
+
ast_type: "Platform",
|
|
1461
|
+
type: outputType,
|
|
1462
|
+
location: get_location(),
|
|
1463
|
+
name: name,
|
|
1464
|
+
type_parameters: type_args,
|
|
1465
|
+
arguments: argAsts,
|
|
1466
|
+
async: true,
|
|
1467
|
+
optional: isOptional,
|
|
1468
|
+
});
|
|
1469
|
+
};
|
|
1470
|
+
fn.implement = (factory) => {
|
|
1471
|
+
return {
|
|
1472
|
+
name,
|
|
1473
|
+
type_parameters: [...typeParams],
|
|
1474
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1475
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1476
|
+
inputsFn: (...tps) => {
|
|
1477
|
+
const typeArgMap = {};
|
|
1478
|
+
typeParams.forEach((param, idx) => {
|
|
1479
|
+
typeArgMap[param] = tps[idx];
|
|
1480
|
+
});
|
|
1481
|
+
return inputs.map(t => {
|
|
1482
|
+
if (typeof t === 'string')
|
|
1483
|
+
return typeArgMap[t];
|
|
1484
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1485
|
+
if (!isVariant(result))
|
|
1486
|
+
result = toEastTypeValue(result);
|
|
1487
|
+
return result;
|
|
1488
|
+
});
|
|
1489
|
+
},
|
|
1490
|
+
outputsFn: (...tps) => {
|
|
1491
|
+
const typeArgMap = {};
|
|
1492
|
+
typeParams.forEach((param, idx) => {
|
|
1493
|
+
typeArgMap[param] = tps[idx];
|
|
1494
|
+
});
|
|
1495
|
+
if (typeof output === 'string')
|
|
1496
|
+
return typeArgMap[output];
|
|
1497
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1498
|
+
if (!isVariant(result))
|
|
1499
|
+
result = toEastTypeValue(result);
|
|
1500
|
+
return result;
|
|
1501
|
+
},
|
|
1502
|
+
type: 'async',
|
|
1503
|
+
fn: factory,
|
|
1504
|
+
};
|
|
1505
|
+
};
|
|
1506
|
+
return fn;
|
|
1507
|
+
}
|
|
1027
1508
|
export const BlockBuilder = (return_type) => {
|
|
1028
1509
|
const statements = [];
|
|
1029
1510
|
const $ = ((expr) => {
|
|
1030
1511
|
const ast = Expr.ast(expr);
|
|
1031
1512
|
statements.push(ast);
|
|
1032
|
-
return expr;
|
|
1033
1513
|
});
|
|
1034
1514
|
$.statements = statements;
|
|
1035
1515
|
$.type = () => {
|
|
@@ -1042,7 +1522,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1042
1522
|
};
|
|
1043
1523
|
$.const = ((value, type) => {
|
|
1044
1524
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1045
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1525
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1046
1526
|
}
|
|
1047
1527
|
let ast;
|
|
1048
1528
|
if (value instanceof Expr) {
|
|
@@ -1057,13 +1537,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1057
1537
|
const variable = {
|
|
1058
1538
|
ast_type: "Variable",
|
|
1059
1539
|
type: type ?? ast.type,
|
|
1060
|
-
location: get_location(
|
|
1540
|
+
location: get_location(),
|
|
1061
1541
|
mutable: false,
|
|
1062
1542
|
};
|
|
1063
1543
|
statements.push({
|
|
1064
1544
|
ast_type: "Let",
|
|
1065
1545
|
type: NullType,
|
|
1066
|
-
location: get_location(
|
|
1546
|
+
location: get_location(),
|
|
1067
1547
|
variable,
|
|
1068
1548
|
value: ast,
|
|
1069
1549
|
});
|
|
@@ -1071,7 +1551,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1071
1551
|
});
|
|
1072
1552
|
$.let = ((value, type) => {
|
|
1073
1553
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1074
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1554
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1075
1555
|
}
|
|
1076
1556
|
let ast;
|
|
1077
1557
|
if (value instanceof Expr) {
|
|
@@ -1086,13 +1566,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1086
1566
|
const variable = {
|
|
1087
1567
|
ast_type: "Variable",
|
|
1088
1568
|
type: type ?? ast.type,
|
|
1089
|
-
location: get_location(
|
|
1569
|
+
location: get_location(),
|
|
1090
1570
|
mutable: true,
|
|
1091
1571
|
};
|
|
1092
1572
|
statements.push({
|
|
1093
1573
|
ast_type: "Let",
|
|
1094
1574
|
type: NullType,
|
|
1095
|
-
location: get_location(
|
|
1575
|
+
location: get_location(),
|
|
1096
1576
|
variable,
|
|
1097
1577
|
value: ast,
|
|
1098
1578
|
});
|
|
@@ -1100,7 +1580,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1100
1580
|
});
|
|
1101
1581
|
$.assign = ((variable, value) => {
|
|
1102
1582
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1103
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1583
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1104
1584
|
}
|
|
1105
1585
|
let v = Expr.ast(variable);
|
|
1106
1586
|
// Handle RecursiveType variables which are auto-unwrapped by fromAst
|
|
@@ -1111,13 +1591,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1111
1591
|
throw new Error("Can only assign to a variable");
|
|
1112
1592
|
}
|
|
1113
1593
|
if (!v.mutable) {
|
|
1114
|
-
throw new Error(`Cannot assign to variable defined at ${
|
|
1594
|
+
throw new Error(`Cannot assign to variable defined at ${printLocations(v.location)} defined as const`);
|
|
1115
1595
|
}
|
|
1116
1596
|
const ast_value = value instanceof Expr ? Expr.ast(value) : valueOrExprToAstTyped(value, v.type);
|
|
1117
1597
|
const ast = {
|
|
1118
1598
|
ast_type: "Assign",
|
|
1119
1599
|
type: NullType,
|
|
1120
|
-
location: get_location(
|
|
1600
|
+
location: get_location(),
|
|
1121
1601
|
variable: v,
|
|
1122
1602
|
value: ast_value,
|
|
1123
1603
|
};
|
|
@@ -1127,16 +1607,22 @@ export const BlockBuilder = (return_type) => {
|
|
|
1127
1607
|
// TODO if/when we introduce recursion, can we somehow get benefit from the typing?
|
|
1128
1608
|
$.return = (expr) => {
|
|
1129
1609
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1130
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1610
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1131
1611
|
}
|
|
1132
1612
|
const expAst = expr instanceof Expr ? Expr.ast(expr) : valueOrExprToAst(expr);
|
|
1133
1613
|
if (!isSubtype(expAst.type, return_type)) {
|
|
1134
1614
|
throw new Error(`Return expected to have type ${printType(return_type)}, got ${printType(expAst.type)}`);
|
|
1135
1615
|
}
|
|
1616
|
+
// Deduplicate: if the expression is already the last statement (e.g., from $()),
|
|
1617
|
+
// don't push it again - just wrap it in the Return
|
|
1618
|
+
const exprAstRef = expr instanceof Expr ? Expr.ast(expr) : null;
|
|
1619
|
+
if (exprAstRef !== null && statements.length > 0 && statements[statements.length - 1] === exprAstRef) {
|
|
1620
|
+
statements.pop();
|
|
1621
|
+
}
|
|
1136
1622
|
const ast = {
|
|
1137
1623
|
ast_type: "Return",
|
|
1138
1624
|
type: NeverType,
|
|
1139
|
-
location: get_location(
|
|
1625
|
+
location: get_location(),
|
|
1140
1626
|
value: expAst
|
|
1141
1627
|
};
|
|
1142
1628
|
statements.push(ast);
|
|
@@ -1144,12 +1630,12 @@ export const BlockBuilder = (return_type) => {
|
|
|
1144
1630
|
};
|
|
1145
1631
|
$.break = (label) => {
|
|
1146
1632
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1147
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1633
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1148
1634
|
}
|
|
1149
1635
|
const ast = {
|
|
1150
1636
|
ast_type: "Break",
|
|
1151
1637
|
type: NeverType,
|
|
1152
|
-
location: get_location(
|
|
1638
|
+
location: get_location(),
|
|
1153
1639
|
label,
|
|
1154
1640
|
};
|
|
1155
1641
|
statements.push(ast);
|
|
@@ -1157,12 +1643,12 @@ export const BlockBuilder = (return_type) => {
|
|
|
1157
1643
|
};
|
|
1158
1644
|
$.continue = (label) => {
|
|
1159
1645
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1160
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1646
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1161
1647
|
}
|
|
1162
1648
|
const ast = {
|
|
1163
1649
|
ast_type: "Continue",
|
|
1164
1650
|
type: NeverType,
|
|
1165
|
-
location: get_location(
|
|
1651
|
+
location: get_location(),
|
|
1166
1652
|
label,
|
|
1167
1653
|
};
|
|
1168
1654
|
statements.push(ast);
|
|
@@ -1170,7 +1656,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1170
1656
|
};
|
|
1171
1657
|
$.if = (predicate, true_branch) => {
|
|
1172
1658
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1173
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1659
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1174
1660
|
}
|
|
1175
1661
|
const predicateAst = predicate instanceof Expr ? Expr.ast(predicate) : valueOrExprToAstTyped(predicate, BooleanType);
|
|
1176
1662
|
if (predicateAst.type.type !== "Boolean") {
|
|
@@ -1188,38 +1674,38 @@ export const BlockBuilder = (return_type) => {
|
|
|
1188
1674
|
}
|
|
1189
1675
|
let true_ast;
|
|
1190
1676
|
if (true_stmts.length === 0) {
|
|
1191
|
-
true_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
1677
|
+
true_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1192
1678
|
}
|
|
1193
1679
|
else if (true_stmts.length === 1 && isSubtype(true_stmts[0].type, NullType)) {
|
|
1194
1680
|
true_ast = true_stmts[0];
|
|
1195
1681
|
}
|
|
1196
1682
|
else {
|
|
1197
1683
|
if (!isSubtype(true_stmts[true_stmts.length - 1].type, NullType)) {
|
|
1198
|
-
true_stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1684
|
+
true_stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1199
1685
|
}
|
|
1200
1686
|
true_ast = {
|
|
1201
1687
|
ast_type: "Block",
|
|
1202
1688
|
type: true_stmts[true_stmts.length - 1].type,
|
|
1203
|
-
location: get_location(
|
|
1689
|
+
location: get_location(),
|
|
1204
1690
|
statements: true_stmts,
|
|
1205
1691
|
};
|
|
1206
1692
|
}
|
|
1207
1693
|
const if_else_ast = {
|
|
1208
1694
|
ast_type: "IfElse",
|
|
1209
1695
|
type: NullType,
|
|
1210
|
-
location: get_location(
|
|
1696
|
+
location: get_location(),
|
|
1211
1697
|
ifs: [{
|
|
1212
1698
|
predicate: Expr.ast(predicate),
|
|
1213
1699
|
body: true_ast,
|
|
1214
1700
|
}],
|
|
1215
|
-
else_body: { ast_type: "Value", type: NullType, location: get_location(
|
|
1701
|
+
else_body: { ast_type: "Value", type: NullType, location: get_location(), value: null },
|
|
1216
1702
|
};
|
|
1217
1703
|
statements.push(if_else_ast);
|
|
1218
1704
|
return new IfElseExpr(if_else_ast, return_type);
|
|
1219
1705
|
};
|
|
1220
1706
|
$.match = (variant, cases) => {
|
|
1221
1707
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1222
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1708
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1223
1709
|
}
|
|
1224
1710
|
if (Expr.type(variant).type !== "Variant") {
|
|
1225
1711
|
throw new Error(`match not defined over ${printType(Expr.type(variant))}`);
|
|
@@ -1231,11 +1717,11 @@ export const BlockBuilder = (return_type) => {
|
|
|
1231
1717
|
const data_variable = {
|
|
1232
1718
|
ast_type: "Variable",
|
|
1233
1719
|
type: t,
|
|
1234
|
-
location: get_location(
|
|
1720
|
+
location: get_location(),
|
|
1235
1721
|
mutable: false,
|
|
1236
1722
|
};
|
|
1237
1723
|
if (f === undefined) {
|
|
1238
|
-
cases_out[k] = { variable: data_variable, body: { ast_type: "Value", type: NullType, location: get_location(
|
|
1724
|
+
cases_out[k] = { variable: data_variable, body: { ast_type: "Value", type: NullType, location: get_location(), value: null } };
|
|
1239
1725
|
}
|
|
1240
1726
|
else {
|
|
1241
1727
|
const data = fromAst(data_variable);
|
|
@@ -1250,19 +1736,19 @@ export const BlockBuilder = (return_type) => {
|
|
|
1250
1736
|
}
|
|
1251
1737
|
let expr;
|
|
1252
1738
|
if (stmts.length === 0) {
|
|
1253
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1739
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1254
1740
|
}
|
|
1255
1741
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1256
1742
|
expr = stmts[0];
|
|
1257
1743
|
}
|
|
1258
1744
|
else {
|
|
1259
1745
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1260
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1746
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1261
1747
|
}
|
|
1262
1748
|
expr = {
|
|
1263
1749
|
ast_type: "Block",
|
|
1264
1750
|
type: stmts[stmts.length - 1].type,
|
|
1265
|
-
location: get_location(
|
|
1751
|
+
location: get_location(),
|
|
1266
1752
|
statements: stmts,
|
|
1267
1753
|
};
|
|
1268
1754
|
}
|
|
@@ -1273,7 +1759,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1273
1759
|
const ast = {
|
|
1274
1760
|
ast_type: "Match",
|
|
1275
1761
|
type: out_type,
|
|
1276
|
-
location: get_location(
|
|
1762
|
+
location: get_location(),
|
|
1277
1763
|
variant: Expr.ast(variant),
|
|
1278
1764
|
cases: cases_out,
|
|
1279
1765
|
};
|
|
@@ -1282,13 +1768,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1282
1768
|
};
|
|
1283
1769
|
$.while = (predicate, body) => {
|
|
1284
1770
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1285
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1771
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1286
1772
|
}
|
|
1287
1773
|
const predicateAst = predicate instanceof Expr ? Expr.ast(predicate) : valueOrExprToAstTyped(predicate, BooleanType);
|
|
1288
1774
|
if (predicateAst.type.type !== "Boolean") {
|
|
1289
1775
|
throw new Error(`while predicate expected to have type Boolean, got ${printType(predicateAst.type)}`);
|
|
1290
1776
|
}
|
|
1291
|
-
const label = { location: get_location(
|
|
1777
|
+
const label = { location: get_location() };
|
|
1292
1778
|
const $_body = BlockBuilder(return_type);
|
|
1293
1779
|
const ret = body($_body, label);
|
|
1294
1780
|
const stmts = $_body.statements;
|
|
@@ -1300,19 +1786,19 @@ export const BlockBuilder = (return_type) => {
|
|
|
1300
1786
|
}
|
|
1301
1787
|
let expr;
|
|
1302
1788
|
if (stmts.length === 0) {
|
|
1303
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1789
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1304
1790
|
}
|
|
1305
1791
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1306
1792
|
expr = stmts[0];
|
|
1307
1793
|
}
|
|
1308
1794
|
else {
|
|
1309
1795
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1310
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1796
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1311
1797
|
}
|
|
1312
1798
|
expr = {
|
|
1313
1799
|
ast_type: "Block",
|
|
1314
1800
|
type: stmts[stmts.length - 1].type,
|
|
1315
|
-
location: get_location(
|
|
1801
|
+
location: get_location(),
|
|
1316
1802
|
statements: stmts,
|
|
1317
1803
|
};
|
|
1318
1804
|
}
|
|
@@ -1322,7 +1808,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1322
1808
|
const ast = {
|
|
1323
1809
|
ast_type: "While",
|
|
1324
1810
|
type: NullType,
|
|
1325
|
-
location: get_location(
|
|
1811
|
+
location: get_location(),
|
|
1326
1812
|
predicate: predicateAst,
|
|
1327
1813
|
label,
|
|
1328
1814
|
body: expr,
|
|
@@ -1332,24 +1818,24 @@ export const BlockBuilder = (return_type) => {
|
|
|
1332
1818
|
};
|
|
1333
1819
|
$.for = ((collection, body) => {
|
|
1334
1820
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1335
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1821
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1336
1822
|
}
|
|
1337
1823
|
if (collection instanceof ArrayExpr) {
|
|
1338
1824
|
const value_variable = {
|
|
1339
1825
|
ast_type: "Variable",
|
|
1340
1826
|
type: Expr.type(collection).value,
|
|
1341
|
-
location: get_location(
|
|
1827
|
+
location: get_location(),
|
|
1342
1828
|
mutable: false,
|
|
1343
1829
|
};
|
|
1344
1830
|
const value = fromAst(value_variable);
|
|
1345
1831
|
const key_variable = {
|
|
1346
1832
|
ast_type: "Variable",
|
|
1347
1833
|
type: IntegerType,
|
|
1348
|
-
location: get_location(
|
|
1834
|
+
location: get_location(),
|
|
1349
1835
|
mutable: false,
|
|
1350
1836
|
};
|
|
1351
1837
|
const key = fromAst(key_variable);
|
|
1352
|
-
const label = { location: get_location(
|
|
1838
|
+
const label = { location: get_location() };
|
|
1353
1839
|
const $ = BlockBuilder(return_type);
|
|
1354
1840
|
const ret = body($, value, key, label);
|
|
1355
1841
|
const stmts = $.statements;
|
|
@@ -1361,26 +1847,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1361
1847
|
}
|
|
1362
1848
|
let expr;
|
|
1363
1849
|
if (stmts.length === 0) {
|
|
1364
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1850
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1365
1851
|
}
|
|
1366
1852
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1367
1853
|
expr = stmts[0];
|
|
1368
1854
|
}
|
|
1369
1855
|
else {
|
|
1370
1856
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1371
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1857
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1372
1858
|
}
|
|
1373
1859
|
expr = {
|
|
1374
1860
|
ast_type: "Block",
|
|
1375
1861
|
type: stmts[stmts.length - 1].type,
|
|
1376
|
-
location: get_location(
|
|
1862
|
+
location: get_location(),
|
|
1377
1863
|
statements: stmts,
|
|
1378
1864
|
};
|
|
1379
1865
|
}
|
|
1380
1866
|
const ast = {
|
|
1381
1867
|
ast_type: "ForArray",
|
|
1382
1868
|
type: NullType,
|
|
1383
|
-
location: get_location(
|
|
1869
|
+
location: get_location(),
|
|
1384
1870
|
label,
|
|
1385
1871
|
array: Expr.ast(collection),
|
|
1386
1872
|
key: key_variable,
|
|
@@ -1394,11 +1880,11 @@ export const BlockBuilder = (return_type) => {
|
|
|
1394
1880
|
const key_variable = {
|
|
1395
1881
|
ast_type: "Variable",
|
|
1396
1882
|
type: Expr.type(collection).key,
|
|
1397
|
-
location: get_location(
|
|
1883
|
+
location: get_location(),
|
|
1398
1884
|
mutable: false,
|
|
1399
1885
|
};
|
|
1400
1886
|
const key = fromAst(key_variable);
|
|
1401
|
-
const label = { location: get_location(
|
|
1887
|
+
const label = { location: get_location() };
|
|
1402
1888
|
const $ = BlockBuilder(return_type);
|
|
1403
1889
|
const ret = body($, key, label);
|
|
1404
1890
|
const stmts = $.statements;
|
|
@@ -1410,26 +1896,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1410
1896
|
}
|
|
1411
1897
|
let expr;
|
|
1412
1898
|
if (stmts.length === 0) {
|
|
1413
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1899
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1414
1900
|
}
|
|
1415
1901
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1416
1902
|
expr = stmts[0];
|
|
1417
1903
|
}
|
|
1418
1904
|
else {
|
|
1419
1905
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1420
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1906
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1421
1907
|
}
|
|
1422
1908
|
expr = {
|
|
1423
1909
|
ast_type: "Block",
|
|
1424
1910
|
type: stmts[stmts.length - 1].type,
|
|
1425
|
-
location: get_location(
|
|
1911
|
+
location: get_location(),
|
|
1426
1912
|
statements: stmts,
|
|
1427
1913
|
};
|
|
1428
1914
|
}
|
|
1429
1915
|
const ast = {
|
|
1430
1916
|
ast_type: "ForSet",
|
|
1431
1917
|
type: NullType,
|
|
1432
|
-
location: get_location(
|
|
1918
|
+
location: get_location(),
|
|
1433
1919
|
label,
|
|
1434
1920
|
set: Expr.ast(collection),
|
|
1435
1921
|
key: key_variable,
|
|
@@ -1442,18 +1928,18 @@ export const BlockBuilder = (return_type) => {
|
|
|
1442
1928
|
const value_variable = {
|
|
1443
1929
|
ast_type: "Variable",
|
|
1444
1930
|
type: Expr.type(collection).value,
|
|
1445
|
-
location: get_location(
|
|
1931
|
+
location: get_location(),
|
|
1446
1932
|
mutable: false,
|
|
1447
1933
|
};
|
|
1448
1934
|
const value = fromAst(value_variable);
|
|
1449
1935
|
const key_variable = {
|
|
1450
1936
|
ast_type: "Variable",
|
|
1451
1937
|
type: Expr.type(collection).key,
|
|
1452
|
-
location: get_location(
|
|
1938
|
+
location: get_location(),
|
|
1453
1939
|
mutable: false,
|
|
1454
1940
|
};
|
|
1455
1941
|
const key = fromAst(key_variable);
|
|
1456
|
-
const label = { location: get_location(
|
|
1942
|
+
const label = { location: get_location() };
|
|
1457
1943
|
const $ = BlockBuilder(return_type);
|
|
1458
1944
|
const ret = body($, value, key, label);
|
|
1459
1945
|
const stmts = $.statements;
|
|
@@ -1465,26 +1951,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1465
1951
|
}
|
|
1466
1952
|
let expr;
|
|
1467
1953
|
if (stmts.length === 0) {
|
|
1468
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1954
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1469
1955
|
}
|
|
1470
1956
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1471
1957
|
expr = stmts[0];
|
|
1472
1958
|
}
|
|
1473
1959
|
else {
|
|
1474
1960
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1475
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1961
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1476
1962
|
}
|
|
1477
1963
|
expr = {
|
|
1478
1964
|
ast_type: "Block",
|
|
1479
1965
|
type: stmts[stmts.length - 1].type,
|
|
1480
|
-
location: get_location(
|
|
1966
|
+
location: get_location(),
|
|
1481
1967
|
statements: stmts,
|
|
1482
1968
|
};
|
|
1483
1969
|
}
|
|
1484
1970
|
const ast = {
|
|
1485
1971
|
ast_type: "ForDict",
|
|
1486
1972
|
type: NullType,
|
|
1487
|
-
location: get_location(
|
|
1973
|
+
location: get_location(),
|
|
1488
1974
|
label,
|
|
1489
1975
|
dict: Expr.ast(collection),
|
|
1490
1976
|
key: key_variable,
|
|
@@ -1500,10 +1986,10 @@ export const BlockBuilder = (return_type) => {
|
|
|
1500
1986
|
});
|
|
1501
1987
|
$.error = (message, location) => {
|
|
1502
1988
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1503
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1989
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1504
1990
|
}
|
|
1505
1991
|
if (location === undefined) {
|
|
1506
|
-
location = get_location(
|
|
1992
|
+
location = get_location();
|
|
1507
1993
|
}
|
|
1508
1994
|
const ast = {
|
|
1509
1995
|
ast_type: "Error",
|
|
@@ -1516,7 +2002,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1516
2002
|
};
|
|
1517
2003
|
$.try = (body) => {
|
|
1518
2004
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1519
|
-
throw new Error(`Unreachable statement detected at ${
|
|
2005
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1520
2006
|
}
|
|
1521
2007
|
const $try = BlockBuilder(return_type);
|
|
1522
2008
|
const ret = body($try);
|
|
@@ -1528,7 +2014,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1528
2014
|
}
|
|
1529
2015
|
}
|
|
1530
2016
|
if (try_stmts.length === 0 || !isSubtype(try_stmts[try_stmts.length - 1].type, NullType)) {
|
|
1531
|
-
try_stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2017
|
+
try_stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1532
2018
|
}
|
|
1533
2019
|
let try_expr;
|
|
1534
2020
|
if (try_stmts.length === 1) {
|
|
@@ -1538,7 +2024,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1538
2024
|
try_expr = {
|
|
1539
2025
|
ast_type: "Block",
|
|
1540
2026
|
type: try_stmts[try_stmts.length - 1].type,
|
|
1541
|
-
location: get_location(
|
|
2027
|
+
location: get_location(),
|
|
1542
2028
|
statements: try_stmts,
|
|
1543
2029
|
};
|
|
1544
2030
|
}
|
|
@@ -1546,21 +2032,21 @@ export const BlockBuilder = (return_type) => {
|
|
|
1546
2032
|
const message_variable = {
|
|
1547
2033
|
ast_type: "Variable",
|
|
1548
2034
|
type: StringType,
|
|
1549
|
-
location: get_location(
|
|
2035
|
+
location: get_location(),
|
|
1550
2036
|
mutable: false,
|
|
1551
2037
|
};
|
|
1552
2038
|
const stack_variable = {
|
|
1553
2039
|
ast_type: "Variable",
|
|
1554
2040
|
type: ArrayType(StructType({ filename: StringType, line: IntegerType, column: IntegerType })),
|
|
1555
|
-
location: get_location(
|
|
2041
|
+
location: get_location(),
|
|
1556
2042
|
mutable: false,
|
|
1557
2043
|
};
|
|
1558
2044
|
const try_catch_ast = {
|
|
1559
2045
|
ast_type: "TryCatch",
|
|
1560
2046
|
type: NullType,
|
|
1561
|
-
location: get_location(
|
|
2047
|
+
location: get_location(),
|
|
1562
2048
|
try_body: try_expr,
|
|
1563
|
-
catch_body: { ast_type: "Value", type: NullType, location: get_location(
|
|
2049
|
+
catch_body: { ast_type: "Value", type: NullType, location: get_location(), value: null }, // will be updated later
|
|
1564
2050
|
message: message_variable,
|
|
1565
2051
|
stack: stack_variable,
|
|
1566
2052
|
};
|
|
@@ -1591,12 +2077,12 @@ class IfElseExpr extends NullExpr {
|
|
|
1591
2077
|
}
|
|
1592
2078
|
}
|
|
1593
2079
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1594
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2080
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1595
2081
|
}
|
|
1596
2082
|
this[AstSymbol].else_body = stmts.length === 1 ? stmts[0] : {
|
|
1597
2083
|
ast_type: "Block",
|
|
1598
2084
|
type: stmts[stmts.length - 1].type,
|
|
1599
|
-
location: get_location(
|
|
2085
|
+
location: get_location(),
|
|
1600
2086
|
statements: stmts,
|
|
1601
2087
|
};
|
|
1602
2088
|
// propagate unreachable information
|
|
@@ -1637,14 +2123,14 @@ class IfElseExpr extends NullExpr {
|
|
|
1637
2123
|
}
|
|
1638
2124
|
}
|
|
1639
2125
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1640
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2126
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1641
2127
|
}
|
|
1642
2128
|
this[AstSymbol].ifs.push({
|
|
1643
2129
|
predicate: Expr.ast(predicate),
|
|
1644
2130
|
body: stmts.length === 1 ? stmts[0] : {
|
|
1645
2131
|
ast_type: "Block",
|
|
1646
2132
|
type: stmts[stmts.length - 1].type,
|
|
1647
|
-
location: get_location(
|
|
2133
|
+
location: get_location(),
|
|
1648
2134
|
statements: stmts,
|
|
1649
2135
|
},
|
|
1650
2136
|
});
|
|
@@ -1669,7 +2155,7 @@ class TryCatchExpr extends NullExpr {
|
|
|
1669
2155
|
/** Define the logic to follow when an error is caught. The error message and stack trace is provided. */
|
|
1670
2156
|
catch(body) {
|
|
1671
2157
|
if (this.catchCalled) {
|
|
1672
|
-
throw new Error(`Cannot call .catch() more than once on the same try block at ${
|
|
2158
|
+
throw new Error(`Cannot call .catch() more than once on the same try block at ${printLocations(get_location())}`);
|
|
1673
2159
|
}
|
|
1674
2160
|
this.catchCalled = true;
|
|
1675
2161
|
const $ = BlockBuilder(this.return_type);
|
|
@@ -1682,12 +2168,12 @@ class TryCatchExpr extends NullExpr {
|
|
|
1682
2168
|
}
|
|
1683
2169
|
}
|
|
1684
2170
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1685
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2171
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1686
2172
|
}
|
|
1687
2173
|
this[AstSymbol].catch_body = stmts.length === 1 ? stmts[0] : {
|
|
1688
2174
|
ast_type: "Block",
|
|
1689
2175
|
type: stmts[stmts.length - 1].type,
|
|
1690
|
-
location: get_location(
|
|
2176
|
+
location: get_location(),
|
|
1691
2177
|
statements: stmts,
|
|
1692
2178
|
};
|
|
1693
2179
|
// Propagate unreachable information
|
|
@@ -1708,12 +2194,12 @@ class TryCatchExpr extends NullExpr {
|
|
|
1708
2194
|
}
|
|
1709
2195
|
}
|
|
1710
2196
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1711
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2197
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1712
2198
|
}
|
|
1713
2199
|
this[AstSymbol].finally_body = stmts.length === 1 ? stmts[0] : {
|
|
1714
2200
|
ast_type: "Block",
|
|
1715
2201
|
type: stmts[stmts.length - 1].type,
|
|
1716
|
-
location: get_location(
|
|
2202
|
+
location: get_location(),
|
|
1717
2203
|
statements: stmts,
|
|
1718
2204
|
};
|
|
1719
2205
|
}
|
|
@@ -1737,6 +2223,26 @@ Object.assign(Expr, {
|
|
|
1737
2223
|
greater,
|
|
1738
2224
|
greaterEqual,
|
|
1739
2225
|
is,
|
|
1740
|
-
match: matchExpr
|
|
2226
|
+
match: matchExpr,
|
|
2227
|
+
// Comparison aliases
|
|
2228
|
+
equals,
|
|
2229
|
+
eq,
|
|
2230
|
+
notEquals,
|
|
2231
|
+
ne,
|
|
2232
|
+
lessThan,
|
|
2233
|
+
lt,
|
|
2234
|
+
lessThanOrEqual,
|
|
2235
|
+
lte,
|
|
2236
|
+
le,
|
|
2237
|
+
greaterThan,
|
|
2238
|
+
gt,
|
|
2239
|
+
greaterThanOrEqual,
|
|
2240
|
+
gte,
|
|
2241
|
+
ge,
|
|
2242
|
+
// Patch operations
|
|
2243
|
+
diff,
|
|
2244
|
+
applyPatch,
|
|
2245
|
+
composePatch,
|
|
2246
|
+
invertPatch,
|
|
1741
2247
|
});
|
|
1742
2248
|
//# sourceMappingURL=block.js.map
|