@elaraai/east 0.0.1-beta.1 → 0.0.1-beta.3

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.
Files changed (101) hide show
  1. package/README.md +4 -0
  2. package/dist/src/analyze.d.ts +4 -4
  3. package/dist/src/analyze.d.ts.map +1 -1
  4. package/dist/src/analyze.js +142 -44
  5. package/dist/src/analyze.js.map +1 -1
  6. package/dist/src/ast.d.ts +18 -7
  7. package/dist/src/ast.d.ts.map +1 -1
  8. package/dist/src/ast.js +1 -146
  9. package/dist/src/ast.js.map +1 -1
  10. package/dist/src/ast_to_ir.d.ts +1 -0
  11. package/dist/src/ast_to_ir.d.ts.map +1 -1
  12. package/dist/src/ast_to_ir.js +71 -10
  13. package/dist/src/ast_to_ir.js.map +1 -1
  14. package/dist/src/builtins.d.ts.map +1 -1
  15. package/dist/src/builtins.js +79 -64
  16. package/dist/src/builtins.js.map +1 -1
  17. package/dist/src/comparison.d.ts.map +1 -1
  18. package/dist/src/comparison.js +9 -0
  19. package/dist/src/comparison.js.map +1 -1
  20. package/dist/src/compile.d.ts.map +1 -1
  21. package/dist/src/compile.js +114 -220
  22. package/dist/src/compile.js.map +1 -1
  23. package/dist/src/default.d.ts.map +1 -1
  24. package/dist/src/default.js +2 -0
  25. package/dist/src/default.js.map +1 -1
  26. package/dist/src/eastir.d.ts +12 -10
  27. package/dist/src/eastir.d.ts.map +1 -1
  28. package/dist/src/eastir.js +20 -19
  29. package/dist/src/eastir.js.map +1 -1
  30. package/dist/src/expr/array.js +51 -51
  31. package/dist/src/expr/array.js.map +1 -1
  32. package/dist/src/expr/ast.d.ts.map +1 -1
  33. package/dist/src/expr/ast.js +6 -0
  34. package/dist/src/expr/ast.js.map +1 -1
  35. package/dist/src/expr/asyncfunction.d.ts +49 -0
  36. package/dist/src/expr/asyncfunction.d.ts.map +1 -0
  37. package/dist/src/expr/asyncfunction.js +60 -0
  38. package/dist/src/expr/asyncfunction.js.map +1 -0
  39. package/dist/src/expr/block.d.ts +60 -6
  40. package/dist/src/expr/block.d.ts.map +1 -1
  41. package/dist/src/expr/block.js +251 -14
  42. package/dist/src/expr/block.js.map +1 -1
  43. package/dist/src/expr/dict.js +47 -47
  44. package/dist/src/expr/dict.js.map +1 -1
  45. package/dist/src/expr/expr.d.ts +9 -0
  46. package/dist/src/expr/expr.d.ts.map +1 -1
  47. package/dist/src/expr/expr.js +5 -1
  48. package/dist/src/expr/expr.js.map +1 -1
  49. package/dist/src/expr/index.d.ts +73 -2
  50. package/dist/src/expr/index.d.ts.map +1 -1
  51. package/dist/src/expr/index.js +72 -8
  52. package/dist/src/expr/index.js.map +1 -1
  53. package/dist/src/expr/libs/array.js +1 -1
  54. package/dist/src/expr/libs/array.js.map +1 -1
  55. package/dist/src/expr/libs/dict.js +3 -3
  56. package/dist/src/expr/libs/dict.js.map +1 -1
  57. package/dist/src/expr/libs/set.js +2 -2
  58. package/dist/src/expr/libs/set.js.map +1 -1
  59. package/dist/src/expr/ref.js +1 -1
  60. package/dist/src/expr/ref.js.map +1 -1
  61. package/dist/src/expr/set.js +38 -38
  62. package/dist/src/expr/set.js.map +1 -1
  63. package/dist/src/expr/struct.d.ts +2 -0
  64. package/dist/src/expr/struct.d.ts.map +1 -1
  65. package/dist/src/expr/types.d.ts +8 -5
  66. package/dist/src/expr/types.d.ts.map +1 -1
  67. package/dist/src/fuzz.d.ts.map +1 -1
  68. package/dist/src/fuzz.js +5 -0
  69. package/dist/src/fuzz.js.map +1 -1
  70. package/dist/src/internal.d.ts +1 -0
  71. package/dist/src/internal.d.ts.map +1 -1
  72. package/dist/src/internal.js +1 -0
  73. package/dist/src/internal.js.map +1 -1
  74. package/dist/src/ir.d.ts +231 -33
  75. package/dist/src/ir.d.ts.map +1 -1
  76. package/dist/src/ir.js +3 -1
  77. package/dist/src/ir.js.map +1 -1
  78. package/dist/src/serialization/beast.d.ts.map +1 -1
  79. package/dist/src/serialization/beast.js +6 -0
  80. package/dist/src/serialization/beast.js.map +1 -1
  81. package/dist/src/serialization/beast2-stream.d.ts.map +1 -1
  82. package/dist/src/serialization/beast2-stream.js +5 -0
  83. package/dist/src/serialization/beast2-stream.js.map +1 -1
  84. package/dist/src/serialization/beast2.d.ts.map +1 -1
  85. package/dist/src/serialization/beast2.js +6 -0
  86. package/dist/src/serialization/beast2.js.map +1 -1
  87. package/dist/src/serialization/east.d.ts.map +1 -1
  88. package/dist/src/serialization/east.js +9 -1
  89. package/dist/src/serialization/east.js.map +1 -1
  90. package/dist/src/serialization/json.d.ts.map +1 -1
  91. package/dist/src/serialization/json.js +8 -2
  92. package/dist/src/serialization/json.js.map +1 -1
  93. package/dist/src/type_of_type.d.ts +9 -3
  94. package/dist/src/type_of_type.d.ts.map +1 -1
  95. package/dist/src/type_of_type.js +40 -13
  96. package/dist/src/type_of_type.js.map +1 -1
  97. package/dist/src/types.d.ts +59 -16
  98. package/dist/src/types.d.ts.map +1 -1
  99. package/dist/src/types.js +141 -91
  100. package/dist/src/types.js.map +1 -1
  101. package/package.json +1 -1
package/dist/src/types.js CHANGED
@@ -48,9 +48,6 @@ export const BlobType = { type: "Blob" };
48
48
  * @throws When the element type contains functions
49
49
  */
50
50
  export function RefType(type) {
51
- if (typeof type !== "string" && !isDataType(type)) {
52
- throw new Error(`Ref value type must be a (non-function) data type, got ${printType(type)}`);
53
- }
54
51
  return { type: "Ref", value: type };
55
52
  }
56
53
  ;
@@ -63,9 +60,6 @@ export function RefType(type) {
63
60
  * @throws When the element type contains functions
64
61
  */
65
62
  export function ArrayType(type) {
66
- if (typeof type !== "string" && !isDataType(type)) {
67
- throw new Error(`Array value type must be a (non-function) data type, got ${printType(type)}`);
68
- }
69
63
  return { type: "Array", value: type };
70
64
  }
71
65
  ;
@@ -98,9 +92,6 @@ export function DictType(key, value) {
98
92
  if (typeof key !== "string" && !isImmutableType(key)) {
99
93
  throw new Error(`Dict key type must be an immutable type, got ${printType(key)}`);
100
94
  }
101
- if (typeof value !== "string" && !isDataType(value)) {
102
- throw new Error(`Dict value type must be a (non-function) data type, got ${printType(value)}`);
103
- }
104
95
  return { type: "Dict", key, value };
105
96
  }
106
97
  ;
@@ -112,12 +103,6 @@ export function DictType(key, value) {
112
103
  * @returns A Struct type
113
104
  */
114
105
  export function StructType(field_types) {
115
- // Validate all field types are data types (no functions)
116
- for (const [field_name, field_type] of Object.entries(field_types)) {
117
- if (typeof field_type !== "string" && !isDataType(field_type)) {
118
- throw new Error(`Struct field ${field_name} must be a (non-function) data type, got ${printType(field_type)}`);
119
- }
120
- }
121
106
  return { type: "Struct", fields: field_types };
122
107
  }
123
108
  ;
@@ -129,12 +114,6 @@ export function StructType(field_types) {
129
114
  * @returns A Variant type with cases sorted alphabetically
130
115
  */
131
116
  export function VariantType(case_types) {
132
- // Validate all case types are data types (no functions)
133
- for (const [case_name, case_type] of Object.entries(case_types)) {
134
- if (typeof case_type !== "string" && !isDataType(case_type)) {
135
- throw new Error(`Variant case ${case_name} must be a (non-function) data type, got ${printType(case_type)}`);
136
- }
137
- }
138
117
  // Cases are sorted alphabetically by their name
139
118
  const cases_sorted = Object.fromEntries(Object.entries(case_types).sort((x, y) => x[0] < y[0] ? -1 : x[0] === y[0] ? 0 : 1));
140
119
  return { type: "Variant", cases: cases_sorted };
@@ -154,7 +133,7 @@ export function VariantType(case_types) {
154
133
  */
155
134
  function validateNotMutuallyRecursive(type, allowedMarker) {
156
135
  const visited = new Set();
157
- function check(t) {
136
+ function check(t, allowed) {
158
137
  // Skip string placeholders (used for generic builtins)
159
138
  if (typeof t === "string")
160
139
  return;
@@ -167,8 +146,12 @@ function validateNotMutuallyRecursive(type, allowedMarker) {
167
146
  throw new Error(`Invalid type encountered during recursion validation: ${t}${allowedMarkerString === null ? "" : ` (allowed marker: ${allowedMarkerString})`}`);
168
147
  }
169
148
  // Skip allowedMarker
170
- if (t === allowedMarker)
149
+ if (t === allowedMarker) {
150
+ if (!allowed) {
151
+ throw new Error("RecursiveType cannot pass into set keys, dictionary keys, or function input/output types");
152
+ }
171
153
  return;
154
+ }
172
155
  // Avoid infinite loops
173
156
  if (visited.has(t))
174
157
  return;
@@ -185,31 +168,38 @@ function validateNotMutuallyRecursive(type, allowedMarker) {
185
168
  }
186
169
  else if (t.type === "Struct") {
187
170
  for (const [_, field_type] of Object.entries(t.fields)) {
188
- check(field_type);
171
+ check(field_type, allowed);
189
172
  }
190
173
  }
191
174
  else if (t.type === "Variant") {
192
175
  for (const [_, case_type] of Object.entries(t.cases)) {
193
- check(case_type);
176
+ check(case_type, allowed);
194
177
  }
195
178
  }
179
+ else if (t.type === "Ref") {
180
+ check(t.value, allowed);
181
+ }
196
182
  else if (t.type === "Array") {
197
- check(t.value);
183
+ check(t.value, allowed);
198
184
  }
199
185
  else if (t.type === "Set") {
200
- check(t.key);
186
+ check(t.key, false);
201
187
  }
202
188
  else if (t.type === "Dict") {
203
- check(t.key);
204
- check(t.value);
189
+ check(t.key, false);
190
+ check(t.value, allowed);
205
191
  }
206
192
  else if (t.type === "Function") {
207
- t.inputs.forEach(check);
208
- check(t.output);
193
+ t.inputs.forEach(input => check(input, false));
194
+ check(t.output, false);
195
+ }
196
+ else if (t.type === "AsyncFunction") {
197
+ t.inputs.forEach(input => check(input, false));
198
+ check(t.output, false);
209
199
  }
210
200
  // Primitive types don't need recursion
211
201
  }
212
- check(type);
202
+ check(type, true);
213
203
  }
214
204
  /**
215
205
  * Constructs a recursive type with the specified node structure.
@@ -252,25 +242,33 @@ export function RecursiveType(f) {
252
242
  ret.node = type;
253
243
  // Validate SCC size 1 (no nested RecursiveTypes with cross-references)
254
244
  validateNotMutuallyRecursive(type, ret);
255
- if (typeof type !== "string" && !isDataType(type)) {
256
- throw new Error(`Recursive node type must be a (non-function) data type, got ${printType(type)}`);
257
- }
258
245
  return ret;
259
246
  }
260
247
  ;
261
248
  /**
262
249
  * Constructs a Function type with the specified input and output types.
263
250
  *
264
- * @typeParam I - Tuple type of input parameter types
265
- * @typeParam O - The output/return type
266
251
  * @param inputs - Array of {@link EastType} instances for each parameter
267
252
  * @param output - The {@link EastType} of the return value
268
253
  * @returns A Function type
254
+ *
255
+ * @see {@link AsyncFunctionType} for asynchronous functions.
256
+ */
257
+ export function FunctionType(inputs, output) {
258
+ return { type: "Function", inputs, output };
259
+ }
260
+ ;
261
+ /**
262
+ * Constructs an AsyncFunction type with the specified input and output types.
263
+ *
264
+ * @param inputs - Array of {@link EastType} instances for each parameter
265
+ * @param output - The {@link EastType} of the return value
266
+ * @returns An AsyncFunction type
267
+ *
268
+ * @see {@link AsyncFunctionType} for asynchronous functions.
269
269
  */
270
- export function FunctionType(inputs, output, platforms) {
271
- // TODO - for the moment we default function types to being pure, meaning users may need to annotate their higher-order functions.
272
- // In future we may want to track side-effects more precisely.
273
- return { type: "Function", inputs, output, platforms };
270
+ export function AsyncFunctionType(inputs, output) {
271
+ return { type: "AsyncFunction", inputs, output };
274
272
  }
275
273
  ;
276
274
  /**
@@ -281,8 +279,7 @@ export function FunctionType(inputs, output, platforms) {
281
279
  * @returns `true` if the type is a pure data type, `false` if it contains functions
282
280
  *
283
281
  * @remarks
284
- * Data types can be fully serialized and transmitted between runtimes.
285
- * This recursively checks {@link StructType}, {@link VariantType}, and {@link RecursiveType} fields.
282
+ * Data types have a total ordering, can be fully serialized and transmitted between runtimes.
286
283
  */
287
284
  export function isDataType(type, recursive_type) {
288
285
  // Avoid infinite loops
@@ -290,20 +287,18 @@ export function isDataType(type, recursive_type) {
290
287
  return true;
291
288
  }
292
289
  if (type.type === "Ref") {
293
- // Ref constructors check their value type are data types
294
- return true;
290
+ return isDataType(type.value, recursive_type);
295
291
  }
296
292
  else if (type.type === "Array") {
297
- // Array constructors check their value type are data types
298
- return true;
293
+ return isDataType(type.value, recursive_type);
299
294
  }
300
295
  else if (type.type === "Set") {
301
- // Set constructors check their value type are (immutable) data types
296
+ // Set constructors check their key type is an (immutable) data type
302
297
  return true;
303
298
  }
304
299
  else if (type.type === "Dict") {
305
- // Dict constructors check their key and value types are data types
306
- return true;
300
+ // Dict constructors check their key type is an (immutable) data type
301
+ return isDataType(type.value, recursive_type);
307
302
  }
308
303
  else if (type.type === "Struct") {
309
304
  for (const field_type of Object.values(type.fields)) {
@@ -327,6 +322,9 @@ export function isDataType(type, recursive_type) {
327
322
  else if (type.type === "Function") {
328
323
  return false;
329
324
  }
325
+ else if (type.type === "AsyncFunction") {
326
+ return false;
327
+ }
330
328
  else {
331
329
  // Primitive types are data types
332
330
  return true;
@@ -340,8 +338,7 @@ export function isDataType(type, recursive_type) {
340
338
  * @returns `true` if the type is immutable, `false` if it contains mutable collections or functions
341
339
  *
342
340
  * @remarks
343
- * Immutable types exclude {@link ArrayType}, {@link SetType}, {@link DictType}, and {@link FunctionType}.
344
- * This recursively checks {@link StructType}, {@link VariantType}, and {@link RecursiveType} fields.
341
+ * Immutable types exclude {@link ArrayType}, {@link SetType}, {@link DictType}, {@link FunctionType} and {@link AsyncFunctionType}.
345
342
  */
346
343
  export function isImmutableType(type, recursive_type) {
347
344
  // Avoid infinite loops
@@ -387,6 +384,10 @@ export function isImmutableType(type, recursive_type) {
387
384
  // Functions are not data types, and "immutable data" is a subset of "data"
388
385
  return false;
389
386
  }
387
+ else if (type.type === "AsyncFunction") {
388
+ // Functions are not data types, and "immutable data" is a subset of "data"
389
+ return false;
390
+ }
390
391
  else {
391
392
  // Primitive types are immutable
392
393
  return true;
@@ -634,21 +635,25 @@ function isTypeEqualImpl(t1, t2, r1, r2) {
634
635
  if (!isTypeEqual(t1.output, t2.output, r1, r2)) {
635
636
  return false;
636
637
  }
637
- // Check platform requirements match
638
- if (t1.platforms === null && t2.platforms === null) {
639
- return true;
640
- }
641
- if (t1.platforms === null || t2.platforms === null) {
638
+ return true;
639
+ }
640
+ else if (t1.type === "AsyncFunction") {
641
+ if (t2.type !== "AsyncFunction") {
642
642
  return false;
643
643
  }
644
- if (t1.platforms.length !== t2.platforms.length) {
644
+ // Check input types match
645
+ if (t1.inputs.length !== t2.inputs.length) {
645
646
  return false;
646
647
  }
647
- for (let i = 0; i < t1.platforms.length; i++) {
648
- if (t1.platforms[i] !== t2.platforms[i]) {
648
+ for (let i = 0; i < t1.inputs.length; i++) {
649
+ if (!isTypeEqual(t1.inputs[i], t2.inputs[i], r1, r2)) {
649
650
  return false;
650
651
  }
651
652
  }
653
+ // Check output type matches
654
+ if (!isTypeEqual(t1.output, t2.output, r1, r2)) {
655
+ return false;
656
+ }
652
657
  return true;
653
658
  }
654
659
  else {
@@ -777,6 +782,9 @@ export function isValueOf(value, type, node_type, nodes_visited) {
777
782
  else if (type.type === "Function") {
778
783
  throw new Error('Javascript functions cannot be converted to East functions');
779
784
  }
785
+ else if (type.type === "AsyncFunction") {
786
+ throw new Error('Javascript functions cannot be converted to East async functions');
787
+ }
780
788
  else {
781
789
  throw new Error(`Unknown type encountered during value type check: ${type.type}`);
782
790
  }
@@ -870,7 +878,14 @@ export function printType(type, stack = []) {
870
878
  else if (type.type === "Function") {
871
879
  // Note: functions can't be inside recursive types
872
880
  stack.push(type);
873
- const ret = `.Function (inputs=[${type.inputs.map(t => printType(t, stack)).join(", ")}], output=${printType(type.output, stack)}, platforms=${type.platforms === null ? "null" : `[${type.platforms.map(p => JSON.stringify(p)).join(", ")}]`})`;
881
+ const ret = `.Function (inputs=[${type.inputs.map(t => printType(t, stack)).join(", ")}], output=${printType(type.output, stack)})`;
882
+ stack.pop();
883
+ return ret;
884
+ }
885
+ else if (type.type === "AsyncFunction") {
886
+ // Note: functions can't be inside recursive types
887
+ stack.push(type);
888
+ const ret = `.AsyncFunction (inputs=[${type.inputs.map(t => printType(t, stack)).join(", ")}], output=${printType(type.output, stack)})`;
874
889
  stack.pop();
875
890
  return ret;
876
891
  }
@@ -1025,7 +1040,15 @@ function isSubtypeImpl(t1, t2) {
1025
1040
  }
1026
1041
  }
1027
1042
  else if (t1.type === "Function") {
1028
- if (t2.type === "Function") {
1043
+ if (t2.type === "Function" || t2.type === "AsyncFunction") {
1044
+ return t1.inputs.length === t2.inputs.length && t1.inputs.every((t, i) => isSubtype(t2.inputs[i], t)) && isSubtype(t1.output, t2.output); // contravariant inputs and covariant output
1045
+ }
1046
+ else {
1047
+ return false;
1048
+ }
1049
+ }
1050
+ else if (t1.type === "AsyncFunction") {
1051
+ if (t2.type === "AsyncFunction") {
1029
1052
  return t1.inputs.length === t2.inputs.length && t1.inputs.every((t, i) => isSubtype(t2.inputs[i], t)) && isSubtype(t1.output, t2.output); // contravariant inputs and covariant output
1030
1053
  }
1031
1054
  else {
@@ -1162,17 +1185,30 @@ export function TypeUnion(t1, t2) {
1162
1185
  if (t1.inputs.length !== t2.inputs.length) {
1163
1186
  throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1164
1187
  }
1165
- let platforms;
1166
- if (t1.platforms === null) {
1167
- platforms = null;
1188
+ return FunctionType(t1.inputs.map((t, i) => TypeIntersect(t, t2.inputs[i])), TypeUnion(t1.output, t2.output));
1189
+ }
1190
+ else if (t2.type === "AsyncFunction") {
1191
+ if (t1.inputs.length !== t2.inputs.length) {
1192
+ throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1168
1193
  }
1169
- else if (t2.platforms === null) {
1170
- platforms = null;
1194
+ return AsyncFunctionType(t1.inputs.map((t, i) => TypeIntersect(t, t2.inputs[i])), TypeUnion(t1.output, t2.output));
1195
+ }
1196
+ else {
1197
+ throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: incompatible types`);
1198
+ }
1199
+ }
1200
+ else if (t1.type === "AsyncFunction") {
1201
+ if (t2.type === "Function") {
1202
+ if (t1.inputs.length !== t2.inputs.length) {
1203
+ throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1171
1204
  }
1172
- else {
1173
- platforms = [...new Set([...t1.platforms, ...t2.platforms])].sort();
1205
+ return AsyncFunctionType(t1.inputs.map((t, i) => TypeIntersect(t, t2.inputs[i])), TypeUnion(t1.output, t2.output));
1206
+ }
1207
+ else if (t2.type === "AsyncFunction") {
1208
+ if (t1.inputs.length !== t2.inputs.length) {
1209
+ throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1174
1210
  }
1175
- return FunctionType(t1.inputs.map((t, i) => TypeIntersect(t, t2.inputs[i])), TypeUnion(t1.output, t2.output), platforms);
1211
+ return AsyncFunctionType(t1.inputs.map((t, i) => TypeIntersect(t, t2.inputs[i])), TypeUnion(t1.output, t2.output));
1176
1212
  }
1177
1213
  else {
1178
1214
  throw new TypeMismatchError(`Cannot union ${printType(t1)} with ${printType(t2)}: incompatible types`);
@@ -1315,17 +1351,30 @@ export function TypeIntersect(t1, t2) {
1315
1351
  if (t1.inputs.length !== t2.inputs.length) {
1316
1352
  throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1317
1353
  }
1318
- let platforms;
1319
- if (t1.platforms === null) {
1320
- platforms = t2.platforms;
1354
+ return FunctionType(t1.inputs.map((t, i) => TypeUnion(t, t2.inputs[i])), TypeIntersect(t1.output, t2.output));
1355
+ }
1356
+ else if (t2.type === "AsyncFunction") {
1357
+ if (t1.inputs.length !== t2.inputs.length) {
1358
+ throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1321
1359
  }
1322
- else if (t2.platforms === null) {
1323
- platforms = t1.platforms;
1360
+ return FunctionType(t1.inputs.map((t, i) => TypeUnion(t, t2.inputs[i])), TypeIntersect(t1.output, t2.output));
1361
+ }
1362
+ else {
1363
+ throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: incompatible types`);
1364
+ }
1365
+ }
1366
+ else if (t1.type === "AsyncFunction") {
1367
+ if (t2.type === "Function") {
1368
+ if (t1.inputs.length !== t2.inputs.length) {
1369
+ throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1324
1370
  }
1325
- else {
1326
- platforms = t1.platforms.filter(p => t2.platforms.includes(p));
1371
+ return FunctionType(t1.inputs.map((t, i) => TypeUnion(t, t2.inputs[i])), TypeIntersect(t1.output, t2.output));
1372
+ }
1373
+ else if (t2.type === "AsyncFunction") {
1374
+ if (t1.inputs.length !== t2.inputs.length) {
1375
+ throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: functions take different number of arguments`);
1327
1376
  }
1328
- return FunctionType(t1.inputs.map((t, i) => TypeUnion(t, t2.inputs[i])), TypeIntersect(t1.output, t2.output), platforms);
1377
+ return AsyncFunctionType(t1.inputs.map((t, i) => TypeUnion(t, t2.inputs[i])), TypeIntersect(t1.output, t2.output));
1329
1378
  }
1330
1379
  else {
1331
1380
  throw new TypeMismatchError(`Cannot intersect ${printType(t1)} with ${printType(t2)}: incompatible types`);
@@ -1473,20 +1522,18 @@ export function TypeEqual(t1, t2, r1 = t1, r2 = t2) {
1473
1522
  if (t1.inputs.length !== t2.inputs.length) {
1474
1523
  throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: functions take different number of arguments`);
1475
1524
  }
1476
- if (t1.platforms === null) {
1477
- if (t2.platforms !== null) {
1478
- throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: functions have different platform effects`);
1479
- }
1480
- }
1481
- else if (t2.platforms === null) {
1482
- throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: functions have different platform effects`);
1483
- }
1484
- else {
1485
- if (t1.platforms.length !== t2.platforms.length || !t1.platforms.every((p, i) => p === t2.platforms[i])) {
1486
- throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: functions have different platform effects`);
1487
- }
1525
+ return FunctionType(t1.inputs.map((t, i) => TypeEqual(t, t2.inputs[i], r1, r2)), TypeEqual(t1.output, t2.output, r1, r2));
1526
+ }
1527
+ else {
1528
+ throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: incompatible types`);
1529
+ }
1530
+ }
1531
+ else if (t1.type === "AsyncFunction") {
1532
+ if (t2.type === "AsyncFunction") {
1533
+ if (t1.inputs.length !== t2.inputs.length) {
1534
+ throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: functions take different number of arguments`);
1488
1535
  }
1489
- return FunctionType(t1.inputs.map((t, i) => TypeEqual(t, t2.inputs[i], r1, r2)), TypeEqual(t1.output, t2.output, r1, r2), t1.platforms);
1536
+ return AsyncFunctionType(t1.inputs.map((t, i) => TypeEqual(t, t2.inputs[i], r1, r2)), TypeEqual(t1.output, t2.output, r1, r2));
1490
1537
  }
1491
1538
  else {
1492
1539
  throw new TypeMismatchError(`${printType(t1)} is not equal to ${printType(t2)}: incompatible types`);
@@ -1615,6 +1662,9 @@ export function TypeWiden(t1, t2) {
1615
1662
  else if (t1.type === "Function") {
1616
1663
  throw new TypeMismatchError(`Cannot widen ${printType(t1)} with ${printType(t2)}: functions not supported`);
1617
1664
  }
1665
+ else if (t1.type === "AsyncFunction") {
1666
+ throw new TypeMismatchError(`Cannot widen ${printType(t1)} with ${printType(t2)}: functions not supported`);
1667
+ }
1618
1668
  else {
1619
1669
  if (t1.type === t2.type) {
1620
1670
  return t1;