@elaraai/east 0.0.1-beta.3 → 0.0.1-beta.30
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 +52 -13
- package/dist/src/analyze.js.map +1 -1
- package/dist/src/ast.d.ts +34 -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 +134 -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 +374 -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.map +1 -1
- package/dist/src/eastir.js +21 -5
- 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 +206 -8
- package/dist/src/expr/block.d.ts.map +1 -1
- package/dist/src/expr/block.js +623 -136
- 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 +1547 -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.)
|
|
@@ -895,7 +1014,7 @@ export function platform(name, input_types, output_type) {
|
|
|
895
1014
|
ast = {
|
|
896
1015
|
ast_type: "As",
|
|
897
1016
|
type: expectedType,
|
|
898
|
-
location: get_location(
|
|
1017
|
+
location: get_location(),
|
|
899
1018
|
value: ast,
|
|
900
1019
|
};
|
|
901
1020
|
}
|
|
@@ -904,8 +1023,9 @@ export function platform(name, input_types, output_type) {
|
|
|
904
1023
|
return fromAst({
|
|
905
1024
|
ast_type: "Platform",
|
|
906
1025
|
type: output_type,
|
|
907
|
-
location: get_location(
|
|
1026
|
+
location: get_location(),
|
|
908
1027
|
name: name,
|
|
1028
|
+
type_parameters: [],
|
|
909
1029
|
arguments: argAsts,
|
|
910
1030
|
async: false,
|
|
911
1031
|
});
|
|
@@ -984,7 +1104,7 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
984
1104
|
ast = {
|
|
985
1105
|
ast_type: "As",
|
|
986
1106
|
type: expectedType,
|
|
987
|
-
location: get_location(
|
|
1107
|
+
location: get_location(),
|
|
988
1108
|
value: ast,
|
|
989
1109
|
};
|
|
990
1110
|
}
|
|
@@ -993,8 +1113,9 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
993
1113
|
return fromAst({
|
|
994
1114
|
ast_type: "Platform",
|
|
995
1115
|
type: output_type,
|
|
996
|
-
location: get_location(
|
|
1116
|
+
location: get_location(),
|
|
997
1117
|
name: name,
|
|
1118
|
+
type_parameters: [],
|
|
998
1119
|
arguments: argAsts,
|
|
999
1120
|
async: true,
|
|
1000
1121
|
});
|
|
@@ -1024,12 +1145,352 @@ export function asyncPlatform(name, input_types, output_type) {
|
|
|
1024
1145
|
};
|
|
1025
1146
|
return fn;
|
|
1026
1147
|
}
|
|
1148
|
+
// Runtime type substitution function
|
|
1149
|
+
function applyTypeArgs(typeArgs, t) {
|
|
1150
|
+
if (typeof t === 'string') {
|
|
1151
|
+
const ret = typeArgs[t];
|
|
1152
|
+
if (ret === undefined) {
|
|
1153
|
+
throw new Error(`Unexpected type argument ${t}`);
|
|
1154
|
+
}
|
|
1155
|
+
return ret;
|
|
1156
|
+
}
|
|
1157
|
+
else if (t.type === "Ref") {
|
|
1158
|
+
return { type: "Ref", value: applyTypeArgs(typeArgs, t.value) };
|
|
1159
|
+
}
|
|
1160
|
+
else if (t.type === "Array") {
|
|
1161
|
+
return { type: "Array", value: applyTypeArgs(typeArgs, t.value) };
|
|
1162
|
+
}
|
|
1163
|
+
else if (t.type === "Set") {
|
|
1164
|
+
return { type: "Set", key: applyTypeArgs(typeArgs, t.key) };
|
|
1165
|
+
}
|
|
1166
|
+
else if (t.type === "Dict") {
|
|
1167
|
+
return { type: "Dict", key: applyTypeArgs(typeArgs, t.key), value: applyTypeArgs(typeArgs, t.value) };
|
|
1168
|
+
}
|
|
1169
|
+
else if (t.type === "Struct") {
|
|
1170
|
+
const newFields = {};
|
|
1171
|
+
for (const k in t.fields) {
|
|
1172
|
+
newFields[k] = applyTypeArgs(typeArgs, t.fields[k]);
|
|
1173
|
+
}
|
|
1174
|
+
return { type: "Struct", fields: newFields };
|
|
1175
|
+
}
|
|
1176
|
+
else if (t.type === "Variant") {
|
|
1177
|
+
const newCases = {};
|
|
1178
|
+
for (const k in t.cases) {
|
|
1179
|
+
newCases[k] = applyTypeArgs(typeArgs, t.cases[k]);
|
|
1180
|
+
}
|
|
1181
|
+
return { type: "Variant", cases: newCases };
|
|
1182
|
+
}
|
|
1183
|
+
else if (t.type === "Function") {
|
|
1184
|
+
const newInputs = t.inputs.map((inputType) => applyTypeArgs(typeArgs, inputType));
|
|
1185
|
+
const newOutput = applyTypeArgs(typeArgs, t.output);
|
|
1186
|
+
return { type: "Function", inputs: newInputs, output: newOutput };
|
|
1187
|
+
}
|
|
1188
|
+
else if (t.type === "Recursive") {
|
|
1189
|
+
if (t.node === undefined) {
|
|
1190
|
+
// RecursiveTypeMarker (self-reference) - leave alone
|
|
1191
|
+
return t;
|
|
1192
|
+
}
|
|
1193
|
+
return { type: "Recursive", node: applyTypeArgs(typeArgs, t.node) };
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
return t;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
/** Create a callable helper to invoke a generic (polymorphic) platform function.
|
|
1200
|
+
*
|
|
1201
|
+
* Generic platform functions allow you to define platform functions with type parameters,
|
|
1202
|
+
* similar to how builtins work. The type parameters are passed at call time and flow
|
|
1203
|
+
* through to the implementation.
|
|
1204
|
+
*
|
|
1205
|
+
* @param name - The name of the platform function
|
|
1206
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1207
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1208
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1209
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* ```ts
|
|
1213
|
+
* // Define a generic log function
|
|
1214
|
+
* const log = East.genericPlatform(
|
|
1215
|
+
* "log",
|
|
1216
|
+
* ["T"],
|
|
1217
|
+
* ["T"], // Input is type parameter T
|
|
1218
|
+
* NullType
|
|
1219
|
+
* );
|
|
1220
|
+
*
|
|
1221
|
+
* // Use it in East code - type args as array, then value args
|
|
1222
|
+
* const myFunction = East.function([StringType], NullType, ($, s) => {
|
|
1223
|
+
* $(log([StringType], s));
|
|
1224
|
+
* });
|
|
1225
|
+
*
|
|
1226
|
+
* // Implementation receives type params as a factory
|
|
1227
|
+
* const platform = [
|
|
1228
|
+
* log.implement((T) => (value) => {
|
|
1229
|
+
* console.log(printFor(T)(value));
|
|
1230
|
+
* return null;
|
|
1231
|
+
* }),
|
|
1232
|
+
* ];
|
|
1233
|
+
* ```
|
|
1234
|
+
*
|
|
1235
|
+
* @example
|
|
1236
|
+
* ```ts
|
|
1237
|
+
* // Define a generic map function with 2 type parameters
|
|
1238
|
+
* const map = East.genericPlatform(
|
|
1239
|
+
* "map",
|
|
1240
|
+
* ["T", "U"],
|
|
1241
|
+
* ["T", FunctionType(["T"], "U")], // String placeholders in nested types
|
|
1242
|
+
* "U"
|
|
1243
|
+
* );
|
|
1244
|
+
*
|
|
1245
|
+
* // Call with type args array, then value arguments
|
|
1246
|
+
* map([StringType, IntegerType], myString, myMapperFn)
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
export function genericPlatform(name, typeParams, inputs, output) {
|
|
1250
|
+
const numTypeParams = typeParams.length;
|
|
1251
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1252
|
+
// Validate type args array
|
|
1253
|
+
if (!Array.isArray(type_args)) {
|
|
1254
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1255
|
+
`got ${typeof type_args}`);
|
|
1256
|
+
}
|
|
1257
|
+
// Validate type args count
|
|
1258
|
+
if (type_args.length !== numTypeParams) {
|
|
1259
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1260
|
+
`got ${type_args.length}`);
|
|
1261
|
+
}
|
|
1262
|
+
// Validate type args are EastTypes
|
|
1263
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1264
|
+
const typeArg = type_args[i];
|
|
1265
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1266
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1267
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
// Build type argument map
|
|
1271
|
+
const typeArgMap = {};
|
|
1272
|
+
typeParams.forEach((param, idx) => {
|
|
1273
|
+
typeArgMap[param] = type_args[idx];
|
|
1274
|
+
});
|
|
1275
|
+
// Apply type substitution to get concrete input/output types
|
|
1276
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1277
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1278
|
+
// Validate value args count
|
|
1279
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1280
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1281
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1282
|
+
}
|
|
1283
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1284
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1285
|
+
const expectedType = inputTypes[index];
|
|
1286
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1287
|
+
if (ast.type.type === "Never") {
|
|
1288
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1289
|
+
}
|
|
1290
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1291
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1292
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1293
|
+
}
|
|
1294
|
+
// Insert implicit cast
|
|
1295
|
+
ast = {
|
|
1296
|
+
ast_type: "As",
|
|
1297
|
+
type: expectedType,
|
|
1298
|
+
location: get_location(),
|
|
1299
|
+
value: ast,
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
1302
|
+
return ast;
|
|
1303
|
+
});
|
|
1304
|
+
// Create PlatformAST with type_parameters
|
|
1305
|
+
return fromAst({
|
|
1306
|
+
ast_type: "Platform",
|
|
1307
|
+
type: outputType,
|
|
1308
|
+
location: get_location(),
|
|
1309
|
+
name: name,
|
|
1310
|
+
type_parameters: type_args,
|
|
1311
|
+
arguments: argAsts,
|
|
1312
|
+
async: false,
|
|
1313
|
+
});
|
|
1314
|
+
};
|
|
1315
|
+
fn.implement = (factory) => {
|
|
1316
|
+
return {
|
|
1317
|
+
name,
|
|
1318
|
+
type_parameters: [...typeParams],
|
|
1319
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1320
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1321
|
+
inputsFn: (...tps) => {
|
|
1322
|
+
const typeArgMap = {};
|
|
1323
|
+
typeParams.forEach((param, idx) => {
|
|
1324
|
+
typeArgMap[param] = tps[idx];
|
|
1325
|
+
});
|
|
1326
|
+
return inputs.map(t => {
|
|
1327
|
+
if (typeof t === 'string')
|
|
1328
|
+
return typeArgMap[t];
|
|
1329
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1330
|
+
if (!isVariant(result))
|
|
1331
|
+
result = toEastTypeValue(result);
|
|
1332
|
+
return result;
|
|
1333
|
+
});
|
|
1334
|
+
},
|
|
1335
|
+
outputsFn: (...tps) => {
|
|
1336
|
+
const typeArgMap = {};
|
|
1337
|
+
typeParams.forEach((param, idx) => {
|
|
1338
|
+
typeArgMap[param] = tps[idx];
|
|
1339
|
+
});
|
|
1340
|
+
if (typeof output === 'string')
|
|
1341
|
+
return typeArgMap[output];
|
|
1342
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1343
|
+
if (!isVariant(result))
|
|
1344
|
+
result = toEastTypeValue(result);
|
|
1345
|
+
return result;
|
|
1346
|
+
},
|
|
1347
|
+
type: 'sync',
|
|
1348
|
+
fn: factory,
|
|
1349
|
+
};
|
|
1350
|
+
};
|
|
1351
|
+
return fn;
|
|
1352
|
+
}
|
|
1353
|
+
/** Create a callable helper to invoke an asynchronous generic (polymorphic) platform function.
|
|
1354
|
+
*
|
|
1355
|
+
* This is the async variant of `genericPlatform`. The implementation factory should return
|
|
1356
|
+
* an async function.
|
|
1357
|
+
*
|
|
1358
|
+
* @param name - The name of the platform function
|
|
1359
|
+
* @param typeParams - Array of type parameter names (e.g., `["T", "U"]`)
|
|
1360
|
+
* @param inputs - Array of input types, can contain string placeholders like `"T"`
|
|
1361
|
+
* @param output - Output type, can be a string placeholder like `"T"`
|
|
1362
|
+
* @returns A callable function that creates Platform AST nodes when invoked
|
|
1363
|
+
*
|
|
1364
|
+
* @see {@link genericPlatform} for synchronous generic platform functions
|
|
1365
|
+
*
|
|
1366
|
+
* @example
|
|
1367
|
+
* ```ts
|
|
1368
|
+
* // Define an async generic fetch function
|
|
1369
|
+
* const fetchAs = East.asyncGenericPlatform(
|
|
1370
|
+
* "fetchAs",
|
|
1371
|
+
* ["T"],
|
|
1372
|
+
* [StringType], // URL input
|
|
1373
|
+
* "T" // Returns parsed value of type T
|
|
1374
|
+
* );
|
|
1375
|
+
*
|
|
1376
|
+
* // Implementation receives type params and returns async function
|
|
1377
|
+
* const platform = [
|
|
1378
|
+
* fetchAs.implement((T) => async (url) => {
|
|
1379
|
+
* const response = await fetch(url);
|
|
1380
|
+
* return parseFor(T)(await response.text());
|
|
1381
|
+
* }),
|
|
1382
|
+
* ];
|
|
1383
|
+
* ```
|
|
1384
|
+
*/
|
|
1385
|
+
export function asyncGenericPlatform(name, typeParams, inputs, output) {
|
|
1386
|
+
const numTypeParams = typeParams.length;
|
|
1387
|
+
const fn = (type_args, ...valueArgs) => {
|
|
1388
|
+
// Validate type args array
|
|
1389
|
+
if (!Array.isArray(type_args)) {
|
|
1390
|
+
throw new Error(`Generic platform function '${name}' expects type arguments as an array, ` +
|
|
1391
|
+
`got ${typeof type_args}`);
|
|
1392
|
+
}
|
|
1393
|
+
// Validate type args count
|
|
1394
|
+
if (type_args.length !== numTypeParams) {
|
|
1395
|
+
throw new Error(`Generic platform function '${name}' expects ${numTypeParams} type parameters, ` +
|
|
1396
|
+
`got ${type_args.length}`);
|
|
1397
|
+
}
|
|
1398
|
+
// Validate type args are EastTypes
|
|
1399
|
+
for (let i = 0; i < numTypeParams; i++) {
|
|
1400
|
+
const typeArg = type_args[i];
|
|
1401
|
+
if (!typeArg || typeof typeArg !== 'object' || !('type' in typeArg)) {
|
|
1402
|
+
throw new Error(`Generic platform function '${name}' expects type parameter ${i + 1} ` +
|
|
1403
|
+
`(${typeParams[i]}) to be an EastType`);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
// Build type argument map
|
|
1407
|
+
const typeArgMap = {};
|
|
1408
|
+
typeParams.forEach((param, idx) => {
|
|
1409
|
+
typeArgMap[param] = type_args[idx];
|
|
1410
|
+
});
|
|
1411
|
+
// Apply type substitution to get concrete input/output types
|
|
1412
|
+
const inputTypes = inputs.map(t => applyTypeArgs(typeArgMap, t));
|
|
1413
|
+
const outputType = applyTypeArgs(typeArgMap, output);
|
|
1414
|
+
// Validate value args count
|
|
1415
|
+
if (valueArgs.length !== inputTypes.length) {
|
|
1416
|
+
throw new Error(`Generic platform function '${name}' expects ${inputTypes.length} ` +
|
|
1417
|
+
`value arguments, got ${valueArgs.length}`);
|
|
1418
|
+
}
|
|
1419
|
+
// Convert value args to AST with type validation and implicit casts
|
|
1420
|
+
const argAsts = valueArgs.map((arg, index) => {
|
|
1421
|
+
const expectedType = inputTypes[index];
|
|
1422
|
+
let ast = valueOrExprToAstTyped(arg, expectedType);
|
|
1423
|
+
if (ast.type.type === "Never") {
|
|
1424
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got Never type`);
|
|
1425
|
+
}
|
|
1426
|
+
if (!isTypeEqual(ast.type, expectedType)) {
|
|
1427
|
+
if (!isSubtype(ast.type, expectedType)) {
|
|
1428
|
+
throw new Error(`Generic platform function ${name} argument ${index + 1} expected type ${printType(expectedType)}, got ${printType(ast.type)}`);
|
|
1429
|
+
}
|
|
1430
|
+
// Insert implicit cast
|
|
1431
|
+
ast = {
|
|
1432
|
+
ast_type: "As",
|
|
1433
|
+
type: expectedType,
|
|
1434
|
+
location: get_location(),
|
|
1435
|
+
value: ast,
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
return ast;
|
|
1439
|
+
});
|
|
1440
|
+
// Create PlatformAST with type_parameters and async: true
|
|
1441
|
+
return fromAst({
|
|
1442
|
+
ast_type: "Platform",
|
|
1443
|
+
type: outputType,
|
|
1444
|
+
location: get_location(),
|
|
1445
|
+
name: name,
|
|
1446
|
+
type_parameters: type_args,
|
|
1447
|
+
arguments: argAsts,
|
|
1448
|
+
async: true,
|
|
1449
|
+
});
|
|
1450
|
+
};
|
|
1451
|
+
fn.implement = (factory) => {
|
|
1452
|
+
return {
|
|
1453
|
+
name,
|
|
1454
|
+
type_parameters: [...typeParams],
|
|
1455
|
+
inputs: [], // Computed at call time via inputsFn
|
|
1456
|
+
output: toEastTypeValue(NullType), // Placeholder
|
|
1457
|
+
inputsFn: (...tps) => {
|
|
1458
|
+
const typeArgMap = {};
|
|
1459
|
+
typeParams.forEach((param, idx) => {
|
|
1460
|
+
typeArgMap[param] = tps[idx];
|
|
1461
|
+
});
|
|
1462
|
+
return inputs.map(t => {
|
|
1463
|
+
if (typeof t === 'string')
|
|
1464
|
+
return typeArgMap[t];
|
|
1465
|
+
let result = applyTypeArgs(typeArgMap, t);
|
|
1466
|
+
if (!isVariant(result))
|
|
1467
|
+
result = toEastTypeValue(result);
|
|
1468
|
+
return result;
|
|
1469
|
+
});
|
|
1470
|
+
},
|
|
1471
|
+
outputsFn: (...tps) => {
|
|
1472
|
+
const typeArgMap = {};
|
|
1473
|
+
typeParams.forEach((param, idx) => {
|
|
1474
|
+
typeArgMap[param] = tps[idx];
|
|
1475
|
+
});
|
|
1476
|
+
if (typeof output === 'string')
|
|
1477
|
+
return typeArgMap[output];
|
|
1478
|
+
let result = applyTypeArgs(typeArgMap, output);
|
|
1479
|
+
if (!isVariant(result))
|
|
1480
|
+
result = toEastTypeValue(result);
|
|
1481
|
+
return result;
|
|
1482
|
+
},
|
|
1483
|
+
type: 'async',
|
|
1484
|
+
fn: factory,
|
|
1485
|
+
};
|
|
1486
|
+
};
|
|
1487
|
+
return fn;
|
|
1488
|
+
}
|
|
1027
1489
|
export const BlockBuilder = (return_type) => {
|
|
1028
1490
|
const statements = [];
|
|
1029
1491
|
const $ = ((expr) => {
|
|
1030
1492
|
const ast = Expr.ast(expr);
|
|
1031
1493
|
statements.push(ast);
|
|
1032
|
-
return expr;
|
|
1033
1494
|
});
|
|
1034
1495
|
$.statements = statements;
|
|
1035
1496
|
$.type = () => {
|
|
@@ -1042,7 +1503,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1042
1503
|
};
|
|
1043
1504
|
$.const = ((value, type) => {
|
|
1044
1505
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1045
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1506
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1046
1507
|
}
|
|
1047
1508
|
let ast;
|
|
1048
1509
|
if (value instanceof Expr) {
|
|
@@ -1057,13 +1518,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1057
1518
|
const variable = {
|
|
1058
1519
|
ast_type: "Variable",
|
|
1059
1520
|
type: type ?? ast.type,
|
|
1060
|
-
location: get_location(
|
|
1521
|
+
location: get_location(),
|
|
1061
1522
|
mutable: false,
|
|
1062
1523
|
};
|
|
1063
1524
|
statements.push({
|
|
1064
1525
|
ast_type: "Let",
|
|
1065
1526
|
type: NullType,
|
|
1066
|
-
location: get_location(
|
|
1527
|
+
location: get_location(),
|
|
1067
1528
|
variable,
|
|
1068
1529
|
value: ast,
|
|
1069
1530
|
});
|
|
@@ -1071,7 +1532,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1071
1532
|
});
|
|
1072
1533
|
$.let = ((value, type) => {
|
|
1073
1534
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1074
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1535
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1075
1536
|
}
|
|
1076
1537
|
let ast;
|
|
1077
1538
|
if (value instanceof Expr) {
|
|
@@ -1086,13 +1547,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1086
1547
|
const variable = {
|
|
1087
1548
|
ast_type: "Variable",
|
|
1088
1549
|
type: type ?? ast.type,
|
|
1089
|
-
location: get_location(
|
|
1550
|
+
location: get_location(),
|
|
1090
1551
|
mutable: true,
|
|
1091
1552
|
};
|
|
1092
1553
|
statements.push({
|
|
1093
1554
|
ast_type: "Let",
|
|
1094
1555
|
type: NullType,
|
|
1095
|
-
location: get_location(
|
|
1556
|
+
location: get_location(),
|
|
1096
1557
|
variable,
|
|
1097
1558
|
value: ast,
|
|
1098
1559
|
});
|
|
@@ -1100,7 +1561,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1100
1561
|
});
|
|
1101
1562
|
$.assign = ((variable, value) => {
|
|
1102
1563
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1103
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1564
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1104
1565
|
}
|
|
1105
1566
|
let v = Expr.ast(variable);
|
|
1106
1567
|
// Handle RecursiveType variables which are auto-unwrapped by fromAst
|
|
@@ -1111,13 +1572,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1111
1572
|
throw new Error("Can only assign to a variable");
|
|
1112
1573
|
}
|
|
1113
1574
|
if (!v.mutable) {
|
|
1114
|
-
throw new Error(`Cannot assign to variable defined at ${
|
|
1575
|
+
throw new Error(`Cannot assign to variable defined at ${printLocations(v.location)} defined as const`);
|
|
1115
1576
|
}
|
|
1116
1577
|
const ast_value = value instanceof Expr ? Expr.ast(value) : valueOrExprToAstTyped(value, v.type);
|
|
1117
1578
|
const ast = {
|
|
1118
1579
|
ast_type: "Assign",
|
|
1119
1580
|
type: NullType,
|
|
1120
|
-
location: get_location(
|
|
1581
|
+
location: get_location(),
|
|
1121
1582
|
variable: v,
|
|
1122
1583
|
value: ast_value,
|
|
1123
1584
|
};
|
|
@@ -1127,16 +1588,22 @@ export const BlockBuilder = (return_type) => {
|
|
|
1127
1588
|
// TODO if/when we introduce recursion, can we somehow get benefit from the typing?
|
|
1128
1589
|
$.return = (expr) => {
|
|
1129
1590
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1130
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1591
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1131
1592
|
}
|
|
1132
1593
|
const expAst = expr instanceof Expr ? Expr.ast(expr) : valueOrExprToAst(expr);
|
|
1133
1594
|
if (!isSubtype(expAst.type, return_type)) {
|
|
1134
1595
|
throw new Error(`Return expected to have type ${printType(return_type)}, got ${printType(expAst.type)}`);
|
|
1135
1596
|
}
|
|
1597
|
+
// Deduplicate: if the expression is already the last statement (e.g., from $()),
|
|
1598
|
+
// don't push it again - just wrap it in the Return
|
|
1599
|
+
const exprAstRef = expr instanceof Expr ? Expr.ast(expr) : null;
|
|
1600
|
+
if (exprAstRef !== null && statements.length > 0 && statements[statements.length - 1] === exprAstRef) {
|
|
1601
|
+
statements.pop();
|
|
1602
|
+
}
|
|
1136
1603
|
const ast = {
|
|
1137
1604
|
ast_type: "Return",
|
|
1138
1605
|
type: NeverType,
|
|
1139
|
-
location: get_location(
|
|
1606
|
+
location: get_location(),
|
|
1140
1607
|
value: expAst
|
|
1141
1608
|
};
|
|
1142
1609
|
statements.push(ast);
|
|
@@ -1144,12 +1611,12 @@ export const BlockBuilder = (return_type) => {
|
|
|
1144
1611
|
};
|
|
1145
1612
|
$.break = (label) => {
|
|
1146
1613
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1147
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1614
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1148
1615
|
}
|
|
1149
1616
|
const ast = {
|
|
1150
1617
|
ast_type: "Break",
|
|
1151
1618
|
type: NeverType,
|
|
1152
|
-
location: get_location(
|
|
1619
|
+
location: get_location(),
|
|
1153
1620
|
label,
|
|
1154
1621
|
};
|
|
1155
1622
|
statements.push(ast);
|
|
@@ -1157,12 +1624,12 @@ export const BlockBuilder = (return_type) => {
|
|
|
1157
1624
|
};
|
|
1158
1625
|
$.continue = (label) => {
|
|
1159
1626
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1160
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1627
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1161
1628
|
}
|
|
1162
1629
|
const ast = {
|
|
1163
1630
|
ast_type: "Continue",
|
|
1164
1631
|
type: NeverType,
|
|
1165
|
-
location: get_location(
|
|
1632
|
+
location: get_location(),
|
|
1166
1633
|
label,
|
|
1167
1634
|
};
|
|
1168
1635
|
statements.push(ast);
|
|
@@ -1170,7 +1637,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1170
1637
|
};
|
|
1171
1638
|
$.if = (predicate, true_branch) => {
|
|
1172
1639
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1173
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1640
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1174
1641
|
}
|
|
1175
1642
|
const predicateAst = predicate instanceof Expr ? Expr.ast(predicate) : valueOrExprToAstTyped(predicate, BooleanType);
|
|
1176
1643
|
if (predicateAst.type.type !== "Boolean") {
|
|
@@ -1188,38 +1655,38 @@ export const BlockBuilder = (return_type) => {
|
|
|
1188
1655
|
}
|
|
1189
1656
|
let true_ast;
|
|
1190
1657
|
if (true_stmts.length === 0) {
|
|
1191
|
-
true_ast = { ast_type: "Value", type: NullType, location: get_location(
|
|
1658
|
+
true_ast = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1192
1659
|
}
|
|
1193
1660
|
else if (true_stmts.length === 1 && isSubtype(true_stmts[0].type, NullType)) {
|
|
1194
1661
|
true_ast = true_stmts[0];
|
|
1195
1662
|
}
|
|
1196
1663
|
else {
|
|
1197
1664
|
if (!isSubtype(true_stmts[true_stmts.length - 1].type, NullType)) {
|
|
1198
|
-
true_stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1665
|
+
true_stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1199
1666
|
}
|
|
1200
1667
|
true_ast = {
|
|
1201
1668
|
ast_type: "Block",
|
|
1202
1669
|
type: true_stmts[true_stmts.length - 1].type,
|
|
1203
|
-
location: get_location(
|
|
1670
|
+
location: get_location(),
|
|
1204
1671
|
statements: true_stmts,
|
|
1205
1672
|
};
|
|
1206
1673
|
}
|
|
1207
1674
|
const if_else_ast = {
|
|
1208
1675
|
ast_type: "IfElse",
|
|
1209
1676
|
type: NullType,
|
|
1210
|
-
location: get_location(
|
|
1677
|
+
location: get_location(),
|
|
1211
1678
|
ifs: [{
|
|
1212
1679
|
predicate: Expr.ast(predicate),
|
|
1213
1680
|
body: true_ast,
|
|
1214
1681
|
}],
|
|
1215
|
-
else_body: { ast_type: "Value", type: NullType, location: get_location(
|
|
1682
|
+
else_body: { ast_type: "Value", type: NullType, location: get_location(), value: null },
|
|
1216
1683
|
};
|
|
1217
1684
|
statements.push(if_else_ast);
|
|
1218
1685
|
return new IfElseExpr(if_else_ast, return_type);
|
|
1219
1686
|
};
|
|
1220
1687
|
$.match = (variant, cases) => {
|
|
1221
1688
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1222
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1689
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1223
1690
|
}
|
|
1224
1691
|
if (Expr.type(variant).type !== "Variant") {
|
|
1225
1692
|
throw new Error(`match not defined over ${printType(Expr.type(variant))}`);
|
|
@@ -1231,11 +1698,11 @@ export const BlockBuilder = (return_type) => {
|
|
|
1231
1698
|
const data_variable = {
|
|
1232
1699
|
ast_type: "Variable",
|
|
1233
1700
|
type: t,
|
|
1234
|
-
location: get_location(
|
|
1701
|
+
location: get_location(),
|
|
1235
1702
|
mutable: false,
|
|
1236
1703
|
};
|
|
1237
1704
|
if (f === undefined) {
|
|
1238
|
-
cases_out[k] = { variable: data_variable, body: { ast_type: "Value", type: NullType, location: get_location(
|
|
1705
|
+
cases_out[k] = { variable: data_variable, body: { ast_type: "Value", type: NullType, location: get_location(), value: null } };
|
|
1239
1706
|
}
|
|
1240
1707
|
else {
|
|
1241
1708
|
const data = fromAst(data_variable);
|
|
@@ -1250,19 +1717,19 @@ export const BlockBuilder = (return_type) => {
|
|
|
1250
1717
|
}
|
|
1251
1718
|
let expr;
|
|
1252
1719
|
if (stmts.length === 0) {
|
|
1253
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1720
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1254
1721
|
}
|
|
1255
1722
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1256
1723
|
expr = stmts[0];
|
|
1257
1724
|
}
|
|
1258
1725
|
else {
|
|
1259
1726
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1260
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1727
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1261
1728
|
}
|
|
1262
1729
|
expr = {
|
|
1263
1730
|
ast_type: "Block",
|
|
1264
1731
|
type: stmts[stmts.length - 1].type,
|
|
1265
|
-
location: get_location(
|
|
1732
|
+
location: get_location(),
|
|
1266
1733
|
statements: stmts,
|
|
1267
1734
|
};
|
|
1268
1735
|
}
|
|
@@ -1273,7 +1740,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1273
1740
|
const ast = {
|
|
1274
1741
|
ast_type: "Match",
|
|
1275
1742
|
type: out_type,
|
|
1276
|
-
location: get_location(
|
|
1743
|
+
location: get_location(),
|
|
1277
1744
|
variant: Expr.ast(variant),
|
|
1278
1745
|
cases: cases_out,
|
|
1279
1746
|
};
|
|
@@ -1282,13 +1749,13 @@ export const BlockBuilder = (return_type) => {
|
|
|
1282
1749
|
};
|
|
1283
1750
|
$.while = (predicate, body) => {
|
|
1284
1751
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1285
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1752
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1286
1753
|
}
|
|
1287
1754
|
const predicateAst = predicate instanceof Expr ? Expr.ast(predicate) : valueOrExprToAstTyped(predicate, BooleanType);
|
|
1288
1755
|
if (predicateAst.type.type !== "Boolean") {
|
|
1289
1756
|
throw new Error(`while predicate expected to have type Boolean, got ${printType(predicateAst.type)}`);
|
|
1290
1757
|
}
|
|
1291
|
-
const label = { location: get_location(
|
|
1758
|
+
const label = { location: get_location() };
|
|
1292
1759
|
const $_body = BlockBuilder(return_type);
|
|
1293
1760
|
const ret = body($_body, label);
|
|
1294
1761
|
const stmts = $_body.statements;
|
|
@@ -1300,19 +1767,19 @@ export const BlockBuilder = (return_type) => {
|
|
|
1300
1767
|
}
|
|
1301
1768
|
let expr;
|
|
1302
1769
|
if (stmts.length === 0) {
|
|
1303
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1770
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1304
1771
|
}
|
|
1305
1772
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1306
1773
|
expr = stmts[0];
|
|
1307
1774
|
}
|
|
1308
1775
|
else {
|
|
1309
1776
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1310
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1777
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1311
1778
|
}
|
|
1312
1779
|
expr = {
|
|
1313
1780
|
ast_type: "Block",
|
|
1314
1781
|
type: stmts[stmts.length - 1].type,
|
|
1315
|
-
location: get_location(
|
|
1782
|
+
location: get_location(),
|
|
1316
1783
|
statements: stmts,
|
|
1317
1784
|
};
|
|
1318
1785
|
}
|
|
@@ -1322,7 +1789,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1322
1789
|
const ast = {
|
|
1323
1790
|
ast_type: "While",
|
|
1324
1791
|
type: NullType,
|
|
1325
|
-
location: get_location(
|
|
1792
|
+
location: get_location(),
|
|
1326
1793
|
predicate: predicateAst,
|
|
1327
1794
|
label,
|
|
1328
1795
|
body: expr,
|
|
@@ -1332,24 +1799,24 @@ export const BlockBuilder = (return_type) => {
|
|
|
1332
1799
|
};
|
|
1333
1800
|
$.for = ((collection, body) => {
|
|
1334
1801
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1335
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1802
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1336
1803
|
}
|
|
1337
1804
|
if (collection instanceof ArrayExpr) {
|
|
1338
1805
|
const value_variable = {
|
|
1339
1806
|
ast_type: "Variable",
|
|
1340
1807
|
type: Expr.type(collection).value,
|
|
1341
|
-
location: get_location(
|
|
1808
|
+
location: get_location(),
|
|
1342
1809
|
mutable: false,
|
|
1343
1810
|
};
|
|
1344
1811
|
const value = fromAst(value_variable);
|
|
1345
1812
|
const key_variable = {
|
|
1346
1813
|
ast_type: "Variable",
|
|
1347
1814
|
type: IntegerType,
|
|
1348
|
-
location: get_location(
|
|
1815
|
+
location: get_location(),
|
|
1349
1816
|
mutable: false,
|
|
1350
1817
|
};
|
|
1351
1818
|
const key = fromAst(key_variable);
|
|
1352
|
-
const label = { location: get_location(
|
|
1819
|
+
const label = { location: get_location() };
|
|
1353
1820
|
const $ = BlockBuilder(return_type);
|
|
1354
1821
|
const ret = body($, value, key, label);
|
|
1355
1822
|
const stmts = $.statements;
|
|
@@ -1361,26 +1828,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1361
1828
|
}
|
|
1362
1829
|
let expr;
|
|
1363
1830
|
if (stmts.length === 0) {
|
|
1364
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1831
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1365
1832
|
}
|
|
1366
1833
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1367
1834
|
expr = stmts[0];
|
|
1368
1835
|
}
|
|
1369
1836
|
else {
|
|
1370
1837
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1371
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1838
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1372
1839
|
}
|
|
1373
1840
|
expr = {
|
|
1374
1841
|
ast_type: "Block",
|
|
1375
1842
|
type: stmts[stmts.length - 1].type,
|
|
1376
|
-
location: get_location(
|
|
1843
|
+
location: get_location(),
|
|
1377
1844
|
statements: stmts,
|
|
1378
1845
|
};
|
|
1379
1846
|
}
|
|
1380
1847
|
const ast = {
|
|
1381
1848
|
ast_type: "ForArray",
|
|
1382
1849
|
type: NullType,
|
|
1383
|
-
location: get_location(
|
|
1850
|
+
location: get_location(),
|
|
1384
1851
|
label,
|
|
1385
1852
|
array: Expr.ast(collection),
|
|
1386
1853
|
key: key_variable,
|
|
@@ -1394,11 +1861,11 @@ export const BlockBuilder = (return_type) => {
|
|
|
1394
1861
|
const key_variable = {
|
|
1395
1862
|
ast_type: "Variable",
|
|
1396
1863
|
type: Expr.type(collection).key,
|
|
1397
|
-
location: get_location(
|
|
1864
|
+
location: get_location(),
|
|
1398
1865
|
mutable: false,
|
|
1399
1866
|
};
|
|
1400
1867
|
const key = fromAst(key_variable);
|
|
1401
|
-
const label = { location: get_location(
|
|
1868
|
+
const label = { location: get_location() };
|
|
1402
1869
|
const $ = BlockBuilder(return_type);
|
|
1403
1870
|
const ret = body($, key, label);
|
|
1404
1871
|
const stmts = $.statements;
|
|
@@ -1410,26 +1877,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1410
1877
|
}
|
|
1411
1878
|
let expr;
|
|
1412
1879
|
if (stmts.length === 0) {
|
|
1413
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1880
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1414
1881
|
}
|
|
1415
1882
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1416
1883
|
expr = stmts[0];
|
|
1417
1884
|
}
|
|
1418
1885
|
else {
|
|
1419
1886
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1420
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1887
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1421
1888
|
}
|
|
1422
1889
|
expr = {
|
|
1423
1890
|
ast_type: "Block",
|
|
1424
1891
|
type: stmts[stmts.length - 1].type,
|
|
1425
|
-
location: get_location(
|
|
1892
|
+
location: get_location(),
|
|
1426
1893
|
statements: stmts,
|
|
1427
1894
|
};
|
|
1428
1895
|
}
|
|
1429
1896
|
const ast = {
|
|
1430
1897
|
ast_type: "ForSet",
|
|
1431
1898
|
type: NullType,
|
|
1432
|
-
location: get_location(
|
|
1899
|
+
location: get_location(),
|
|
1433
1900
|
label,
|
|
1434
1901
|
set: Expr.ast(collection),
|
|
1435
1902
|
key: key_variable,
|
|
@@ -1442,18 +1909,18 @@ export const BlockBuilder = (return_type) => {
|
|
|
1442
1909
|
const value_variable = {
|
|
1443
1910
|
ast_type: "Variable",
|
|
1444
1911
|
type: Expr.type(collection).value,
|
|
1445
|
-
location: get_location(
|
|
1912
|
+
location: get_location(),
|
|
1446
1913
|
mutable: false,
|
|
1447
1914
|
};
|
|
1448
1915
|
const value = fromAst(value_variable);
|
|
1449
1916
|
const key_variable = {
|
|
1450
1917
|
ast_type: "Variable",
|
|
1451
1918
|
type: Expr.type(collection).key,
|
|
1452
|
-
location: get_location(
|
|
1919
|
+
location: get_location(),
|
|
1453
1920
|
mutable: false,
|
|
1454
1921
|
};
|
|
1455
1922
|
const key = fromAst(key_variable);
|
|
1456
|
-
const label = { location: get_location(
|
|
1923
|
+
const label = { location: get_location() };
|
|
1457
1924
|
const $ = BlockBuilder(return_type);
|
|
1458
1925
|
const ret = body($, value, key, label);
|
|
1459
1926
|
const stmts = $.statements;
|
|
@@ -1465,26 +1932,26 @@ export const BlockBuilder = (return_type) => {
|
|
|
1465
1932
|
}
|
|
1466
1933
|
let expr;
|
|
1467
1934
|
if (stmts.length === 0) {
|
|
1468
|
-
expr = { ast_type: "Value", type: NullType, location: get_location(
|
|
1935
|
+
expr = { ast_type: "Value", type: NullType, location: get_location(), value: null };
|
|
1469
1936
|
}
|
|
1470
1937
|
else if (stmts.length === 1 && isSubtype(stmts[0].type, NullType)) {
|
|
1471
1938
|
expr = stmts[0];
|
|
1472
1939
|
}
|
|
1473
1940
|
else {
|
|
1474
1941
|
if (!isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1475
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
1942
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1476
1943
|
}
|
|
1477
1944
|
expr = {
|
|
1478
1945
|
ast_type: "Block",
|
|
1479
1946
|
type: stmts[stmts.length - 1].type,
|
|
1480
|
-
location: get_location(
|
|
1947
|
+
location: get_location(),
|
|
1481
1948
|
statements: stmts,
|
|
1482
1949
|
};
|
|
1483
1950
|
}
|
|
1484
1951
|
const ast = {
|
|
1485
1952
|
ast_type: "ForDict",
|
|
1486
1953
|
type: NullType,
|
|
1487
|
-
location: get_location(
|
|
1954
|
+
location: get_location(),
|
|
1488
1955
|
label,
|
|
1489
1956
|
dict: Expr.ast(collection),
|
|
1490
1957
|
key: key_variable,
|
|
@@ -1500,10 +1967,10 @@ export const BlockBuilder = (return_type) => {
|
|
|
1500
1967
|
});
|
|
1501
1968
|
$.error = (message, location) => {
|
|
1502
1969
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1503
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1970
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1504
1971
|
}
|
|
1505
1972
|
if (location === undefined) {
|
|
1506
|
-
location = get_location(
|
|
1973
|
+
location = get_location();
|
|
1507
1974
|
}
|
|
1508
1975
|
const ast = {
|
|
1509
1976
|
ast_type: "Error",
|
|
@@ -1516,7 +1983,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1516
1983
|
};
|
|
1517
1984
|
$.try = (body) => {
|
|
1518
1985
|
if (isTypeEqual($.type(), NeverType)) {
|
|
1519
|
-
throw new Error(`Unreachable statement detected at ${
|
|
1986
|
+
throw new Error(`Unreachable statement detected at ${printLocations(get_location())}`);
|
|
1520
1987
|
}
|
|
1521
1988
|
const $try = BlockBuilder(return_type);
|
|
1522
1989
|
const ret = body($try);
|
|
@@ -1528,7 +1995,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1528
1995
|
}
|
|
1529
1996
|
}
|
|
1530
1997
|
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(
|
|
1998
|
+
try_stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1532
1999
|
}
|
|
1533
2000
|
let try_expr;
|
|
1534
2001
|
if (try_stmts.length === 1) {
|
|
@@ -1538,7 +2005,7 @@ export const BlockBuilder = (return_type) => {
|
|
|
1538
2005
|
try_expr = {
|
|
1539
2006
|
ast_type: "Block",
|
|
1540
2007
|
type: try_stmts[try_stmts.length - 1].type,
|
|
1541
|
-
location: get_location(
|
|
2008
|
+
location: get_location(),
|
|
1542
2009
|
statements: try_stmts,
|
|
1543
2010
|
};
|
|
1544
2011
|
}
|
|
@@ -1546,21 +2013,21 @@ export const BlockBuilder = (return_type) => {
|
|
|
1546
2013
|
const message_variable = {
|
|
1547
2014
|
ast_type: "Variable",
|
|
1548
2015
|
type: StringType,
|
|
1549
|
-
location: get_location(
|
|
2016
|
+
location: get_location(),
|
|
1550
2017
|
mutable: false,
|
|
1551
2018
|
};
|
|
1552
2019
|
const stack_variable = {
|
|
1553
2020
|
ast_type: "Variable",
|
|
1554
2021
|
type: ArrayType(StructType({ filename: StringType, line: IntegerType, column: IntegerType })),
|
|
1555
|
-
location: get_location(
|
|
2022
|
+
location: get_location(),
|
|
1556
2023
|
mutable: false,
|
|
1557
2024
|
};
|
|
1558
2025
|
const try_catch_ast = {
|
|
1559
2026
|
ast_type: "TryCatch",
|
|
1560
2027
|
type: NullType,
|
|
1561
|
-
location: get_location(
|
|
2028
|
+
location: get_location(),
|
|
1562
2029
|
try_body: try_expr,
|
|
1563
|
-
catch_body: { ast_type: "Value", type: NullType, location: get_location(
|
|
2030
|
+
catch_body: { ast_type: "Value", type: NullType, location: get_location(), value: null }, // will be updated later
|
|
1564
2031
|
message: message_variable,
|
|
1565
2032
|
stack: stack_variable,
|
|
1566
2033
|
};
|
|
@@ -1591,12 +2058,12 @@ class IfElseExpr extends NullExpr {
|
|
|
1591
2058
|
}
|
|
1592
2059
|
}
|
|
1593
2060
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1594
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2061
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1595
2062
|
}
|
|
1596
2063
|
this[AstSymbol].else_body = stmts.length === 1 ? stmts[0] : {
|
|
1597
2064
|
ast_type: "Block",
|
|
1598
2065
|
type: stmts[stmts.length - 1].type,
|
|
1599
|
-
location: get_location(
|
|
2066
|
+
location: get_location(),
|
|
1600
2067
|
statements: stmts,
|
|
1601
2068
|
};
|
|
1602
2069
|
// propagate unreachable information
|
|
@@ -1637,14 +2104,14 @@ class IfElseExpr extends NullExpr {
|
|
|
1637
2104
|
}
|
|
1638
2105
|
}
|
|
1639
2106
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1640
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2107
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1641
2108
|
}
|
|
1642
2109
|
this[AstSymbol].ifs.push({
|
|
1643
2110
|
predicate: Expr.ast(predicate),
|
|
1644
2111
|
body: stmts.length === 1 ? stmts[0] : {
|
|
1645
2112
|
ast_type: "Block",
|
|
1646
2113
|
type: stmts[stmts.length - 1].type,
|
|
1647
|
-
location: get_location(
|
|
2114
|
+
location: get_location(),
|
|
1648
2115
|
statements: stmts,
|
|
1649
2116
|
},
|
|
1650
2117
|
});
|
|
@@ -1669,7 +2136,7 @@ class TryCatchExpr extends NullExpr {
|
|
|
1669
2136
|
/** Define the logic to follow when an error is caught. The error message and stack trace is provided. */
|
|
1670
2137
|
catch(body) {
|
|
1671
2138
|
if (this.catchCalled) {
|
|
1672
|
-
throw new Error(`Cannot call .catch() more than once on the same try block at ${
|
|
2139
|
+
throw new Error(`Cannot call .catch() more than once on the same try block at ${printLocations(get_location())}`);
|
|
1673
2140
|
}
|
|
1674
2141
|
this.catchCalled = true;
|
|
1675
2142
|
const $ = BlockBuilder(this.return_type);
|
|
@@ -1682,12 +2149,12 @@ class TryCatchExpr extends NullExpr {
|
|
|
1682
2149
|
}
|
|
1683
2150
|
}
|
|
1684
2151
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1685
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2152
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1686
2153
|
}
|
|
1687
2154
|
this[AstSymbol].catch_body = stmts.length === 1 ? stmts[0] : {
|
|
1688
2155
|
ast_type: "Block",
|
|
1689
2156
|
type: stmts[stmts.length - 1].type,
|
|
1690
|
-
location: get_location(
|
|
2157
|
+
location: get_location(),
|
|
1691
2158
|
statements: stmts,
|
|
1692
2159
|
};
|
|
1693
2160
|
// Propagate unreachable information
|
|
@@ -1708,12 +2175,12 @@ class TryCatchExpr extends NullExpr {
|
|
|
1708
2175
|
}
|
|
1709
2176
|
}
|
|
1710
2177
|
if (stmts.length === 0 || !isSubtype(stmts[stmts.length - 1].type, NullType)) {
|
|
1711
|
-
stmts.push({ ast_type: "Value", type: NullType, location: get_location(
|
|
2178
|
+
stmts.push({ ast_type: "Value", type: NullType, location: get_location(), value: null });
|
|
1712
2179
|
}
|
|
1713
2180
|
this[AstSymbol].finally_body = stmts.length === 1 ? stmts[0] : {
|
|
1714
2181
|
ast_type: "Block",
|
|
1715
2182
|
type: stmts[stmts.length - 1].type,
|
|
1716
|
-
location: get_location(
|
|
2183
|
+
location: get_location(),
|
|
1717
2184
|
statements: stmts,
|
|
1718
2185
|
};
|
|
1719
2186
|
}
|
|
@@ -1737,6 +2204,26 @@ Object.assign(Expr, {
|
|
|
1737
2204
|
greater,
|
|
1738
2205
|
greaterEqual,
|
|
1739
2206
|
is,
|
|
1740
|
-
match: matchExpr
|
|
2207
|
+
match: matchExpr,
|
|
2208
|
+
// Comparison aliases
|
|
2209
|
+
equals,
|
|
2210
|
+
eq,
|
|
2211
|
+
notEquals,
|
|
2212
|
+
ne,
|
|
2213
|
+
lessThan,
|
|
2214
|
+
lt,
|
|
2215
|
+
lessThanOrEqual,
|
|
2216
|
+
lte,
|
|
2217
|
+
le,
|
|
2218
|
+
greaterThan,
|
|
2219
|
+
gt,
|
|
2220
|
+
greaterThanOrEqual,
|
|
2221
|
+
gte,
|
|
2222
|
+
ge,
|
|
2223
|
+
// Patch operations
|
|
2224
|
+
diff,
|
|
2225
|
+
applyPatch,
|
|
2226
|
+
composePatch,
|
|
2227
|
+
invertPatch,
|
|
1741
2228
|
});
|
|
1742
2229
|
//# sourceMappingURL=block.js.map
|