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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/LICENSE.md +15 -666
  2. package/README.md +30 -8
  3. package/dist/src/analyze.d.ts +3 -0
  4. package/dist/src/analyze.d.ts.map +1 -1
  5. package/dist/src/analyze.js +76 -15
  6. package/dist/src/analyze.js.map +1 -1
  7. package/dist/src/ast.d.ts +37 -33
  8. package/dist/src/ast.d.ts.map +1 -1
  9. package/dist/src/ast_to_ir.d.ts +6 -0
  10. package/dist/src/ast_to_ir.d.ts.map +1 -1
  11. package/dist/src/ast_to_ir.js +135 -101
  12. package/dist/src/ast_to_ir.js.map +1 -1
  13. package/dist/src/builtins.d.ts +1 -1
  14. package/dist/src/builtins.d.ts.map +1 -1
  15. package/dist/src/builtins.js +32 -0
  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 +12 -4
  19. package/dist/src/comparison.js.map +1 -1
  20. package/dist/src/compile.d.ts +26 -1
  21. package/dist/src/compile.d.ts.map +1 -1
  22. package/dist/src/compile.js +388 -257
  23. package/dist/src/compile.js.map +1 -1
  24. package/dist/src/datetime_format/types.d.ts +23 -23
  25. package/dist/src/eastir.d.ts +4 -0
  26. package/dist/src/eastir.d.ts.map +1 -1
  27. package/dist/src/eastir.js +27 -7
  28. package/dist/src/eastir.js.map +1 -1
  29. package/dist/src/error.d.ts +12 -1
  30. package/dist/src/error.d.ts.map +1 -1
  31. package/dist/src/error.js +31 -1
  32. package/dist/src/error.js.map +1 -1
  33. package/dist/src/expr/array.d.ts +109 -1
  34. package/dist/src/expr/array.d.ts.map +1 -1
  35. package/dist/src/expr/array.js +204 -44
  36. package/dist/src/expr/array.js.map +1 -1
  37. package/dist/src/expr/ast.d.ts +1 -1
  38. package/dist/src/expr/ast.d.ts.map +1 -1
  39. package/dist/src/expr/ast.js +16 -28
  40. package/dist/src/expr/ast.js.map +1 -1
  41. package/dist/src/expr/asyncfunction.js +1 -1
  42. package/dist/src/expr/asyncfunction.js.map +1 -1
  43. package/dist/src/expr/blob.d.ts +73 -1
  44. package/dist/src/expr/blob.d.ts.map +1 -1
  45. package/dist/src/expr/blob.js +97 -7
  46. package/dist/src/expr/blob.js.map +1 -1
  47. package/dist/src/expr/block.d.ts +232 -12
  48. package/dist/src/expr/block.d.ts.map +1 -1
  49. package/dist/src/expr/block.js +646 -140
  50. package/dist/src/expr/block.js.map +1 -1
  51. package/dist/src/expr/boolean.d.ts +44 -0
  52. package/dist/src/expr/boolean.d.ts.map +1 -1
  53. package/dist/src/expr/boolean.js +57 -5
  54. package/dist/src/expr/boolean.js.map +1 -1
  55. package/dist/src/expr/datetime.d.ts +135 -0
  56. package/dist/src/expr/datetime.d.ts.map +1 -1
  57. package/dist/src/expr/datetime.js +183 -33
  58. package/dist/src/expr/datetime.js.map +1 -1
  59. package/dist/src/expr/dict.d.ts +42 -0
  60. package/dist/src/expr/dict.d.ts.map +1 -1
  61. package/dist/src/expr/dict.js +105 -55
  62. package/dist/src/expr/dict.js.map +1 -1
  63. package/dist/src/expr/expr.d.ts +1 -1
  64. package/dist/src/expr/expr.d.ts.map +1 -1
  65. package/dist/src/expr/expr.js.map +1 -1
  66. package/dist/src/expr/float.d.ts +153 -0
  67. package/dist/src/expr/float.d.ts.map +1 -1
  68. package/dist/src/expr/float.js +190 -16
  69. package/dist/src/expr/float.js.map +1 -1
  70. package/dist/src/expr/function.d.ts +7 -2
  71. package/dist/src/expr/function.d.ts.map +1 -1
  72. package/dist/src/expr/function.js +1 -1
  73. package/dist/src/expr/function.js.map +1 -1
  74. package/dist/src/expr/index.d.ts +202 -2
  75. package/dist/src/expr/index.d.ts.map +1 -1
  76. package/dist/src/expr/index.js +207 -2
  77. package/dist/src/expr/index.js.map +1 -1
  78. package/dist/src/expr/integer.d.ts +180 -0
  79. package/dist/src/expr/integer.d.ts.map +1 -1
  80. package/dist/src/expr/integer.js +188 -17
  81. package/dist/src/expr/integer.js.map +1 -1
  82. package/dist/src/expr/libs/blob.js +2 -2
  83. package/dist/src/expr/libs/blob.js.map +1 -1
  84. package/dist/src/expr/libs/integer.d.ts +19 -0
  85. package/dist/src/expr/libs/integer.d.ts.map +1 -1
  86. package/dist/src/expr/libs/integer.js +47 -0
  87. package/dist/src/expr/libs/integer.js.map +1 -1
  88. package/dist/src/expr/libs/string.js +1 -1
  89. package/dist/src/expr/libs/string.js.map +1 -1
  90. package/dist/src/expr/recursive.d.ts +83 -0
  91. package/dist/src/expr/recursive.d.ts.map +1 -0
  92. package/dist/src/expr/recursive.js +99 -0
  93. package/dist/src/expr/recursive.js.map +1 -0
  94. package/dist/src/expr/ref.js +3 -3
  95. package/dist/src/expr/ref.js.map +1 -1
  96. package/dist/src/expr/set.d.ts +44 -2
  97. package/dist/src/expr/set.d.ts.map +1 -1
  98. package/dist/src/expr/set.js +97 -47
  99. package/dist/src/expr/set.js.map +1 -1
  100. package/dist/src/expr/string.d.ts +134 -0
  101. package/dist/src/expr/string.d.ts.map +1 -1
  102. package/dist/src/expr/string.js +172 -22
  103. package/dist/src/expr/string.js.map +1 -1
  104. package/dist/src/expr/struct.d.ts +1 -1
  105. package/dist/src/expr/struct.d.ts.map +1 -1
  106. package/dist/src/expr/struct.js +1 -1
  107. package/dist/src/expr/struct.js.map +1 -1
  108. package/dist/src/expr/types.d.ts +7 -6
  109. package/dist/src/expr/types.d.ts.map +1 -1
  110. package/dist/src/expr/variant.d.ts +123 -1
  111. package/dist/src/expr/variant.d.ts.map +1 -1
  112. package/dist/src/expr/variant.js +66 -2
  113. package/dist/src/expr/variant.js.map +1 -1
  114. package/dist/src/fuzz.d.ts +36 -2
  115. package/dist/src/fuzz.d.ts.map +1 -1
  116. package/dist/src/fuzz.js +344 -77
  117. package/dist/src/fuzz.js.map +1 -1
  118. package/dist/src/index.d.ts +1 -0
  119. package/dist/src/index.d.ts.map +1 -1
  120. package/dist/src/index.js +1 -0
  121. package/dist/src/index.js.map +1 -1
  122. package/dist/src/internal.d.ts +12 -0
  123. package/dist/src/internal.d.ts.map +1 -1
  124. package/dist/src/internal.js +13 -0
  125. package/dist/src/internal.js.map +1 -1
  126. package/dist/src/ir.d.ts +1551 -1505
  127. package/dist/src/ir.d.ts.map +1 -1
  128. package/dist/src/ir.js +49 -34
  129. package/dist/src/ir.js.map +1 -1
  130. package/dist/src/location.d.ts +30 -10
  131. package/dist/src/location.d.ts.map +1 -1
  132. package/dist/src/location.js +70 -28
  133. package/dist/src/location.js.map +1 -1
  134. package/dist/src/patch/apply.d.ts +15 -0
  135. package/dist/src/patch/apply.d.ts.map +1 -0
  136. package/dist/src/patch/apply.js +380 -0
  137. package/dist/src/patch/apply.js.map +1 -0
  138. package/dist/src/patch/compose.d.ts +15 -0
  139. package/dist/src/patch/compose.d.ts.map +1 -0
  140. package/dist/src/patch/compose.js +480 -0
  141. package/dist/src/patch/compose.js.map +1 -0
  142. package/dist/src/patch/diff.d.ts +15 -0
  143. package/dist/src/patch/diff.d.ts.map +1 -0
  144. package/dist/src/patch/diff.js +328 -0
  145. package/dist/src/patch/diff.js.map +1 -0
  146. package/dist/src/patch/fuzz.d.ts +73 -0
  147. package/dist/src/patch/fuzz.d.ts.map +1 -0
  148. package/dist/src/patch/fuzz.js +159 -0
  149. package/dist/src/patch/fuzz.js.map +1 -0
  150. package/dist/src/patch/index.d.ts +18 -0
  151. package/dist/src/patch/index.d.ts.map +1 -0
  152. package/dist/src/patch/index.js +20 -0
  153. package/dist/src/patch/index.js.map +1 -0
  154. package/dist/src/patch/invert.d.ts +15 -0
  155. package/dist/src/patch/invert.d.ts.map +1 -0
  156. package/dist/src/patch/invert.js +302 -0
  157. package/dist/src/patch/invert.js.map +1 -0
  158. package/dist/src/patch/type_of_patch.d.ts +17 -0
  159. package/dist/src/patch/type_of_patch.d.ts.map +1 -0
  160. package/dist/src/patch/type_of_patch.js +143 -0
  161. package/dist/src/patch/type_of_patch.js.map +1 -0
  162. package/dist/src/patch/types.d.ts +166 -0
  163. package/dist/src/patch/types.d.ts.map +1 -0
  164. package/dist/src/patch/types.js +69 -0
  165. package/dist/src/patch/types.js.map +1 -0
  166. package/dist/src/platform.d.ts +6 -0
  167. package/dist/src/platform.d.ts.map +1 -1
  168. package/dist/src/serialization/beast.d.ts.map +1 -1
  169. package/dist/src/serialization/beast.js +53 -18
  170. package/dist/src/serialization/beast.js.map +1 -1
  171. package/dist/src/serialization/beast2.d.ts +39 -3
  172. package/dist/src/serialization/beast2.d.ts.map +1 -1
  173. package/dist/src/serialization/beast2.js +241 -18
  174. package/dist/src/serialization/beast2.js.map +1 -1
  175. package/dist/src/serialization/csv.d.ts +139 -0
  176. package/dist/src/serialization/csv.d.ts.map +1 -0
  177. package/dist/src/serialization/csv.js +615 -0
  178. package/dist/src/serialization/csv.js.map +1 -0
  179. package/dist/src/serialization/index.d.ts +2 -1
  180. package/dist/src/serialization/index.d.ts.map +1 -1
  181. package/dist/src/serialization/index.js +2 -1
  182. package/dist/src/serialization/index.js.map +1 -1
  183. package/dist/src/type_of_type.d.ts +45 -34
  184. package/dist/src/type_of_type.d.ts.map +1 -1
  185. package/dist/src/type_of_type.js +62 -1
  186. package/dist/src/type_of_type.js.map +1 -1
  187. package/dist/src/types.d.ts +8 -8
  188. package/dist/src/types.d.ts.map +1 -1
  189. package/dist/src/types.js +4 -4
  190. package/dist/src/types.js.map +1 -1
  191. package/package.json +4 -5
@@ -1,16 +1,24 @@
1
1
  import { printLocationValue } from "./ir.js";
2
- import { printLocation } from "./location.js";
2
+ import { printLocations } from "./location.js";
3
3
  import { toEastTypeValue } from "./type_of_type.js";
4
4
  import { ArrayType, DictType, FunctionType, isSubtype, isTypeEqual, NeverType, NullType, printType, RefType, SetType, StructType, VariantType } from "./types.js";
5
5
  import { variant } from "./containers/variant.js";
6
6
  import { applyTypeParameters, Builtins } from "./builtins.js";
7
+ /** @internal An exception throw for the purpose of early loop continue */
8
+ export class OutOfScopeException extends Error {
9
+ definedLocation;
10
+ constructor(definedLocation) {
11
+ super(`Variable defined at ${printLocations(definedLocation)} is out of scope here`);
12
+ this.definedLocation = definedLocation;
13
+ }
14
+ }
7
15
  // TODO we should probably redo type checking exhaustively here?
8
- function toLocationValue(location) {
9
- return {
10
- filename: location.filename,
11
- line: BigInt(location.line),
12
- column: BigInt(location.column),
13
- };
16
+ function toLocationValues(locations) {
17
+ return locations.map(loc => ({
18
+ filename: loc.filename,
19
+ line: BigInt(loc.line),
20
+ column: BigInt(loc.column),
21
+ }));
14
22
  }
15
23
  /** Perform scope resolution and type checking on `AST`, produce `IR` ready for serialization, compilation or evaluation.
16
24
  *
@@ -29,7 +37,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
29
37
  return ir;
30
38
  }
31
39
  else {
32
- throw new Error(`Variable defined at ${printLocation(ast.location)} not in scope`);
40
+ throw new OutOfScopeException(ast.location);
33
41
  }
34
42
  }
35
43
  }
@@ -39,7 +47,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
39
47
  const variable = variant("Variable", {
40
48
  type: toEastTypeValue(ast.variable.type),
41
49
  name: `_${ctx.n_vars}`,
42
- location: toLocationValue(ast.variable.location),
50
+ location: toLocationValues(ast.variable.location),
43
51
  mutable: ast.variable.mutable,
44
52
  captured: false,
45
53
  });
@@ -50,19 +58,19 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
50
58
  // This catches type errors early at AST level
51
59
  if (!isSubtype(ast.value.type, ast.variable.type)) {
52
60
  throw new Error(`Cannot initialize variable of type ${printType(ast.variable.type)} ` +
53
- `with value of type ${printType(ast.value.type)} at ${printLocation(ast.location)}`);
61
+ `with value of type ${printType(ast.value.type)} at ${printLocations(ast.location)}`);
54
62
  }
55
63
  value = variant("As", {
56
64
  type: toEastTypeValue(ast.variable.type),
57
65
  value,
58
- location: toLocationValue(ast.location),
66
+ location: toLocationValues(ast.location),
59
67
  });
60
68
  }
61
69
  ctx.n_vars += 1;
62
70
  ctx.local_ctx.set(ast.variable, variable);
63
71
  return variant("Let", {
64
72
  type: toEastTypeValue(ast.type),
65
- location: toLocationValue(ast.location),
73
+ location: toLocationValues(ast.location),
66
74
  variable,
67
75
  value,
68
76
  });
@@ -71,7 +79,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
71
79
  // Fetch the variable from context
72
80
  const variable = ast_to_ir(ast.variable, ctx);
73
81
  if (!variable.value.mutable) {
74
- throw new Error(`Variable defined const at ${printLocationValue(variable.value.location)} is being reassigned at ${printLocation(ast.location)}`);
82
+ throw new Error(`Variable defined const at ${printLocationValue(variable.value.location)} is being reassigned at ${printLocations(ast.location)}`);
75
83
  }
76
84
  let value = ast_to_ir(ast.value, ctx);
77
85
  // Get the variable's type from the IR node
@@ -82,17 +90,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
82
90
  // Validate subtype relationship before inserting As node
83
91
  if (!isSubtype(ast.value.type, ast.variable.type)) {
84
92
  throw new Error(`Cannot assign value of type ${printType(ast.value.type)} ` +
85
- `to variable of type ${printType(ast.variable.type)} at ${printLocation(ast.location)}`);
93
+ `to variable of type ${printType(ast.variable.type)} at ${printLocations(ast.location)}`);
86
94
  }
87
95
  value = variant("As", {
88
96
  type: variableType,
89
97
  value,
90
- location: toLocationValue(ast.location),
98
+ location: toLocationValues(ast.location),
91
99
  });
92
100
  }
93
101
  return variant("Assign", {
94
102
  type: toEastTypeValue(ast.type),
95
- location: toLocationValue(ast.location),
103
+ location: toLocationValues(ast.location),
96
104
  variable,
97
105
  value,
98
106
  });
@@ -105,7 +113,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
105
113
  ctx.n_loops = ctx2.n_loops;
106
114
  return variant("Block", {
107
115
  type: toEastTypeValue(ast.type),
108
- location: toLocationValue(ast.location),
116
+ location: toLocationValues(ast.location),
109
117
  statements,
110
118
  });
111
119
  }
@@ -114,18 +122,18 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
114
122
  const builtin_name = ast.builtin;
115
123
  const builtin_def = Builtins[builtin_name];
116
124
  if (!builtin_def) {
117
- throw new Error(`Unknown builtin function '${builtin_name}' at ${printLocation(ast.location)}`);
125
+ throw new Error(`Unknown builtin function '${builtin_name}' at ${printLocations(ast.location)}`);
118
126
  }
119
127
  if (builtin_def.type_parameters.length !== ast.type_parameters.length) {
120
- throw new Error(`Builtin function '${builtin_name}' expected ${builtin_def.type_parameters.length} type parameters, got ${ast.type_parameters.length} at ${printLocation(ast.location)}`);
128
+ throw new Error(`Builtin function '${builtin_name}' expected ${builtin_def.type_parameters.length} type parameters, got ${ast.type_parameters.length} at ${printLocations(ast.location)}`);
121
129
  }
122
130
  const type_map = new Map(builtin_def.type_parameters.map((name, i) => [name, ast.type_parameters[i]]));
123
131
  if (ast.arguments.length !== builtin_def.inputs.length) {
124
- throw new Error(`Builtin function '${builtin_name}' expected ${builtin_def.inputs.length} arguments, got ${ast.arguments.length} at ${printLocation(ast.location)}`);
132
+ throw new Error(`Builtin function '${builtin_name}' expected ${builtin_def.inputs.length} arguments, got ${ast.arguments.length} at ${printLocations(ast.location)}`);
125
133
  }
126
134
  return variant("Builtin", {
127
135
  type: toEastTypeValue(ast.type),
128
- location: toLocationValue(ast.location),
136
+ location: toLocationValues(ast.location),
129
137
  builtin: ast.builtin,
130
138
  type_parameters: ast.type_parameters.map(tp => toEastTypeValue(tp)),
131
139
  arguments: ast.arguments.map((arg, i) => {
@@ -134,12 +142,12 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
134
142
  // Now check type compatibility
135
143
  if (arg.type.type !== "Never" && !isTypeEqual(arg.type, expectedType)) {
136
144
  if (!isSubtype(arg.type, expectedType)) {
137
- throw new Error(`Builtin ${builtin_name} with type parameters [${ast.type_parameters.map(tp => printType(tp)).join(", ")}] argument ${i} of type ${printType(arg.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocation(ast.location)}`);
145
+ throw new Error(`Builtin ${builtin_name} with type parameters [${ast.type_parameters.map(tp => printType(tp)).join(", ")}] argument ${i} of type ${printType(arg.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocations(ast.location)}`);
138
146
  }
139
147
  arg_ir = variant("As", {
140
- type: toEastTypeValue(arg.type),
148
+ type: toEastTypeValue(expectedType),
141
149
  value: arg_ir,
142
- location: toLocationValue(ast.location),
150
+ location: toLocationValues(ast.location),
143
151
  });
144
152
  }
145
153
  return arg_ir;
@@ -148,37 +156,39 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
148
156
  }
149
157
  else if (ast.ast_type === "Platform") {
150
158
  if (ctx.async === false && ast.async === true) {
151
- throw new Error(`Async platform call not allowed outside async function at ${printLocation(ast.location)}`);
159
+ throw new Error(`Async platform call not allowed outside async function at ${printLocations(ast.location)}`);
152
160
  }
153
161
  return variant("Platform", {
154
162
  type: toEastTypeValue(ast.type),
155
- location: toLocationValue(ast.location),
163
+ location: toLocationValues(ast.location),
156
164
  name: ast.name,
165
+ type_parameters: ast.type_parameters.map(tp => toEastTypeValue(tp)),
157
166
  arguments: ast.arguments.map(ast => ast_to_ir(ast, ctx)), // type equality handled at Expr/AST level
158
167
  async: ast.async,
168
+ optional: ast.optional,
159
169
  });
160
170
  }
161
171
  else if (ast.ast_type === "Struct") {
162
172
  return variant("Struct", {
163
173
  type: toEastTypeValue(ast.type),
164
- location: toLocationValue(ast.location),
174
+ location: toLocationValues(ast.location),
165
175
  fields: Object.entries(ast.fields).map(([name, fieldAst]) => {
166
176
  let value = ast_to_ir(fieldAst, ctx);
167
177
  const expectedType = ast.type.fields[name];
168
178
  if (!expectedType) {
169
- throw new Error(`Struct type does not have field '${name}' at ${printLocation(ast.location)}`);
179
+ throw new Error(`Struct type does not have field '${name}' at ${printLocations(ast.location)}`);
170
180
  }
171
181
  if (!isTypeEqual(fieldAst.type, expectedType)) {
172
182
  if (isSubtype(fieldAst.type, expectedType)) {
173
183
  value = variant("As", {
174
184
  type: toEastTypeValue(expectedType),
175
185
  value,
176
- location: toLocationValue(ast.location),
186
+ location: toLocationValues(ast.location),
177
187
  });
178
188
  }
179
189
  else {
180
190
  throw new Error(`Cannot assign field '${name}' of type ${printType(ast.type.fields[name])} ` +
181
- `with value of type ${printType(fieldAst.type)} at ${printLocation(ast.location)}`);
191
+ `with value of type ${printType(fieldAst.type)} at ${printLocations(ast.location)}`);
182
192
  }
183
193
  }
184
194
  return { name, value };
@@ -188,7 +198,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
188
198
  else if (ast.ast_type === "GetField") {
189
199
  return variant("GetField", {
190
200
  type: toEastTypeValue(ast.type),
191
- location: toLocationValue(ast.location),
201
+ location: toLocationValues(ast.location),
192
202
  struct: ast_to_ir(ast.struct, ctx),
193
203
  field: ast.field,
194
204
  });
@@ -201,17 +211,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
201
211
  value = variant("As", {
202
212
  type: toEastTypeValue(expectedType),
203
213
  value,
204
- location: toLocationValue(ast.location),
214
+ location: toLocationValues(ast.location),
205
215
  });
206
216
  }
207
217
  else {
208
218
  throw new Error(`Cannot assign case '${ast.case}' of type ${printType(expectedType)} ` +
209
- `with value of type ${printType(ast.value.type)} at ${printLocation(ast.location)}`);
219
+ `with value of type ${printType(ast.value.type)} at ${printLocations(ast.location)}`);
210
220
  }
211
221
  }
212
222
  return variant("Variant", {
213
223
  type: toEastTypeValue(ast.type),
214
- location: toLocationValue(ast.location),
224
+ location: toLocationValues(ast.location),
215
225
  case: ast.case,
216
226
  value,
217
227
  });
@@ -221,7 +231,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
221
231
  const param = variant("Variable", {
222
232
  type: toEastTypeValue(parameter.type),
223
233
  name: `_${ctx.n_vars}`,
224
- location: toLocationValue(parameter.location),
234
+ location: toLocationValues(parameter.location),
225
235
  mutable: parameter.mutable, // false...
226
236
  captured: false,
227
237
  });
@@ -235,9 +245,21 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
235
245
  const body = ast_to_ir(ast.body, ctx2);
236
246
  ctx.n_vars = ctx2.n_vars;
237
247
  ctx.n_loops = ctx2.n_loops;
248
+ // Propagate captures: if this function captured something from ctx.parent_ctx,
249
+ // then the enclosing function also needs to capture it
250
+ for (const capturedVar of captures) {
251
+ // Check if this variable came from our parent context (not defined locally in enclosing function)
252
+ for (const [_astVar, ir] of ctx.parent_ctx) {
253
+ if (ir === capturedVar) {
254
+ // This capture came from an outer scope, so enclosing function must also capture it
255
+ ctx.captures.add(capturedVar);
256
+ break;
257
+ }
258
+ }
259
+ }
238
260
  return variant("Function", {
239
261
  type: toEastTypeValue(ast.type),
240
- location: toLocationValue(ast.location),
262
+ location: toLocationValues(ast.location),
241
263
  parameters,
242
264
  captures: [...captures],
243
265
  body,
@@ -248,7 +270,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
248
270
  const param = variant("Variable", {
249
271
  type: toEastTypeValue(parameter.type),
250
272
  name: `_${ctx.n_vars}`,
251
- location: toLocationValue(parameter.location),
273
+ location: toLocationValues(parameter.location),
252
274
  mutable: parameter.mutable, // false...
253
275
  captured: false,
254
276
  });
@@ -262,9 +284,21 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
262
284
  const body = ast_to_ir(ast.body, ctx2);
263
285
  ctx.n_vars = ctx2.n_vars;
264
286
  ctx.n_loops = ctx2.n_loops;
287
+ // Propagate captures: if this function captured something from ctx.parent_ctx,
288
+ // then the enclosing function also needs to capture it
289
+ for (const capturedVar of captures) {
290
+ // Check if this variable came from our parent context (not defined locally in enclosing function)
291
+ for (const [_astVar, ir] of ctx.parent_ctx) {
292
+ if (ir === capturedVar) {
293
+ // This capture came from an outer scope, so enclosing function must also capture it
294
+ ctx.captures.add(capturedVar);
295
+ break;
296
+ }
297
+ }
298
+ }
265
299
  return variant("AsyncFunction", {
266
300
  type: toEastTypeValue(ast.type),
267
- location: toLocationValue(ast.location),
301
+ location: toLocationValues(ast.location),
268
302
  parameters,
269
303
  captures: [...captures],
270
304
  body,
@@ -275,19 +309,19 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
275
309
  // TODO - what about widening the result with As?
276
310
  return variant("Call", {
277
311
  type: toEastTypeValue(ast.type),
278
- location: toLocationValue(ast.location),
312
+ location: toLocationValues(ast.location),
279
313
  function: ast_to_ir(ast.function, ctx),
280
314
  arguments: ast.arguments.map((argument, i) => {
281
315
  let arg = ast_to_ir(argument, ctx);
282
316
  const expectedType = ast.function.type.inputs[i];
283
317
  if (!isTypeEqual(argument.type, expectedType)) {
284
318
  if (!isSubtype(argument.type, expectedType)) {
285
- throw new Error(`Argument ${i} of type ${printType(argument.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocation(ast.location)}`);
319
+ throw new Error(`Argument ${i} of type ${printType(argument.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocations(ast.location)}`);
286
320
  }
287
321
  arg = variant("As", {
288
322
  type: toEastTypeValue(expectedType),
289
323
  value: arg,
290
- location: toLocationValue(ast.location),
324
+ location: toLocationValues(ast.location),
291
325
  });
292
326
  }
293
327
  return arg;
@@ -296,25 +330,25 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
296
330
  }
297
331
  else if (ast.ast_type === "CallAsync") {
298
332
  if (ctx.async === false) {
299
- throw new Error(`Async function call not allowed outside async function at ${printLocation(ast.location)}`);
333
+ throw new Error(`Async function call not allowed outside async function at ${printLocations(ast.location)}`);
300
334
  }
301
335
  // TODO - type equality could have been handled at Expr/AST level instead
302
336
  // TODO - what about widening the result with As?
303
337
  return variant("CallAsync", {
304
338
  type: toEastTypeValue(ast.type),
305
- location: toLocationValue(ast.location),
339
+ location: toLocationValues(ast.location),
306
340
  function: ast_to_ir(ast.function, ctx),
307
341
  arguments: ast.arguments.map((argument, i) => {
308
342
  let arg = ast_to_ir(argument, ctx);
309
343
  const expectedType = ast.function.type.inputs[i];
310
344
  if (!isTypeEqual(argument.type, expectedType)) {
311
345
  if (!isSubtype(argument.type, expectedType)) {
312
- throw new Error(`Argument ${i} of type ${printType(argument.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocation(ast.location)}`);
346
+ throw new Error(`Argument ${i} of type ${printType(argument.type)} is not compatible with expected type ${printType(expectedType)} at ${printLocations(ast.location)}`);
313
347
  }
314
348
  arg = variant("As", {
315
349
  type: toEastTypeValue(expectedType),
316
350
  value: arg,
317
- location: toLocationValue(ast.location),
351
+ location: toLocationValues(ast.location),
318
352
  });
319
353
  }
320
354
  return arg;
@@ -326,17 +360,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
326
360
  let value = ast_to_ir(ast.value, ctx);
327
361
  if (!isTypeEqual(ast.value.type, valueType)) {
328
362
  if (!isSubtype(ast.value.type, valueType)) {
329
- throw new Error(`Ref value of type ${printType(ast.value.type)} is not compatible with expected type ${printType(valueType)} at ${printLocation(ast.location)}`);
363
+ throw new Error(`Ref value of type ${printType(ast.value.type)} is not compatible with expected type ${printType(valueType)} at ${printLocations(ast.location)}`);
330
364
  }
331
365
  value = variant("As", {
332
366
  type: toEastTypeValue(valueType),
333
367
  value,
334
- location: toLocationValue(ast.location),
368
+ location: toLocationValues(ast.location),
335
369
  });
336
370
  }
337
371
  return variant("NewRef", {
338
372
  type: toEastTypeValue(ast.type),
339
- location: toLocationValue(ast.location),
373
+ location: toLocationValues(ast.location),
340
374
  value,
341
375
  });
342
376
  }
@@ -344,17 +378,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
344
378
  const valueType = ast.type.value;
345
379
  return variant("NewArray", {
346
380
  type: toEastTypeValue(ast.type),
347
- location: toLocationValue(ast.location),
381
+ location: toLocationValues(ast.location),
348
382
  values: ast.values.map((v, i) => {
349
383
  let value = ast_to_ir(v, ctx);
350
384
  if (!isTypeEqual(v.type, valueType)) {
351
385
  if (!isSubtype(v.type, valueType)) {
352
- throw new Error(`Array value at entry ${i} of type ${printType(v.type)} is not compatible with expected type ${printType(valueType)} at ${printLocation(ast.location)}`);
386
+ throw new Error(`Array value at entry ${i} of type ${printType(v.type)} is not compatible with expected type ${printType(valueType)} at ${printLocations(ast.location)}`);
353
387
  }
354
388
  value = variant("As", {
355
389
  type: toEastTypeValue(valueType),
356
390
  value,
357
- location: toLocationValue(ast.location),
391
+ location: toLocationValues(ast.location),
358
392
  });
359
393
  }
360
394
  return value;
@@ -365,17 +399,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
365
399
  const keyType = ast.type.key;
366
400
  return variant("NewSet", {
367
401
  type: toEastTypeValue(ast.type),
368
- location: toLocationValue(ast.location),
402
+ location: toLocationValues(ast.location),
369
403
  values: ast.values.map((k, i) => {
370
404
  let key = ast_to_ir(k, ctx);
371
405
  if (!isTypeEqual(k.type, keyType)) {
372
406
  if (!isSubtype(k.type, keyType)) {
373
- throw new Error(`Set key at entry ${i} of type ${printType(k.type)} is not compatible with expected type ${printType(keyType)} at ${printLocation(ast.location)}`);
407
+ throw new Error(`Set key at entry ${i} of type ${printType(k.type)} is not compatible with expected type ${printType(keyType)} at ${printLocations(ast.location)}`);
374
408
  }
375
409
  key = variant("As", {
376
410
  type: toEastTypeValue(keyType),
377
411
  value: key,
378
- location: toLocationValue(ast.location),
412
+ location: toLocationValues(ast.location),
379
413
  });
380
414
  }
381
415
  return key;
@@ -387,28 +421,28 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
387
421
  const valueType = ast.type.value;
388
422
  return variant("NewDict", {
389
423
  type: toEastTypeValue(ast.type),
390
- location: toLocationValue(ast.location),
424
+ location: toLocationValues(ast.location),
391
425
  values: ast.values.map(([k, v], i) => {
392
426
  let key = ast_to_ir(k, ctx);
393
427
  if (!isTypeEqual(k.type, keyType)) {
394
428
  if (!isSubtype(k.type, keyType)) {
395
- throw new Error(`Dict key at entry ${i} of type ${printType(k.type)} is not compatible with expected type ${printType(keyType)} at ${printLocation(ast.location)}`);
429
+ throw new Error(`Dict key at entry ${i} of type ${printType(k.type)} is not compatible with expected type ${printType(keyType)} at ${printLocations(ast.location)}`);
396
430
  }
397
431
  key = variant("As", {
398
432
  type: toEastTypeValue(keyType),
399
433
  value: key,
400
- location: toLocationValue(ast.location),
434
+ location: toLocationValues(ast.location),
401
435
  });
402
436
  }
403
437
  let value = ast_to_ir(v, ctx);
404
438
  if (!isTypeEqual(v.type, valueType)) {
405
439
  if (!isSubtype(v.type, valueType)) {
406
- throw new Error(`Dict value at entry ${i} of type ${printType(v.type)} is not compatible with expected type ${printType(valueType)} at ${printLocation(ast.location)}`);
440
+ throw new Error(`Dict value at entry ${i} of type ${printType(v.type)} is not compatible with expected type ${printType(valueType)} at ${printLocations(ast.location)}`);
407
441
  }
408
442
  value = variant("As", {
409
443
  type: toEastTypeValue(valueType),
410
444
  value,
411
- location: toLocationValue(ast.location),
445
+ location: toLocationValues(ast.location),
412
446
  });
413
447
  }
414
448
  ;
@@ -435,12 +469,12 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
435
469
  ctx.n_loops = ctx_branch.n_loops;
436
470
  if (branch.body.type.type !== "Never" && !isTypeEqual(branch.body.type, ast.type)) {
437
471
  if (!isSubtype(branch.body.type, ast.type)) {
438
- throw new Error(`If branch body of type ${printType(branch.body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocation(ast.location)}`);
472
+ throw new Error(`If branch body of type ${printType(branch.body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocations(ast.location)}`);
439
473
  }
440
474
  branch_body = variant("As", {
441
475
  type: toEastTypeValue(ast.type),
442
476
  value: branch_body,
443
- location: toLocationValue(ast.location),
477
+ location: toLocationValues(ast.location),
444
478
  });
445
479
  }
446
480
  return { predicate, body: branch_body };
@@ -461,17 +495,17 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
461
495
  ctx.n_loops = ctx_else.n_loops;
462
496
  if (ast.else_body.type.type !== "Never" && !isTypeEqual(ast.else_body.type, ast.type)) {
463
497
  if (!isSubtype(ast.else_body.type, ast.type)) {
464
- throw new Error(`Else branch body of type ${printType(ast.else_body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocation(ast.location)}`);
498
+ throw new Error(`Else branch body of type ${printType(ast.else_body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocations(ast.location)}`);
465
499
  }
466
500
  else_body = variant("As", {
467
501
  type: toEastTypeValue(ast.type),
468
502
  value: else_body,
469
- location: toLocationValue(ast.location),
503
+ location: toLocationValues(ast.location),
470
504
  });
471
505
  }
472
506
  return variant("IfElse", {
473
507
  type: toEastTypeValue(ast.type),
474
- location: toLocationValue(ast.location),
508
+ location: toLocationValues(ast.location),
475
509
  ifs,
476
510
  else_body,
477
511
  });
@@ -479,7 +513,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
479
513
  else if (ast.ast_type === "Error") {
480
514
  return variant("Error", {
481
515
  type: variant("Never", null),
482
- location: toLocationValue(ast.location),
516
+ location: toLocationValues(ast.location),
483
517
  message: ast_to_ir(ast.message, ctx),
484
518
  });
485
519
  }
@@ -502,7 +536,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
502
536
  const message = variant("Variable", {
503
537
  type: toEastTypeValue(ast.message.type),
504
538
  name: `_${ctx.n_vars}`,
505
- location: toLocationValue(ast.message.location),
539
+ location: toLocationValues(ast.message.location),
506
540
  mutable: ast.message.mutable, // false...
507
541
  captured: false,
508
542
  });
@@ -510,7 +544,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
510
544
  const stack = variant("Variable", {
511
545
  type: toEastTypeValue(ast.stack.type),
512
546
  name: `_${ctx.n_vars}`,
513
- location: toLocationValue(ast.stack.location),
547
+ location: toLocationValues(ast.stack.location),
514
548
  mutable: ast.stack.mutable, // false...
515
549
  captured: false,
516
550
  });
@@ -550,13 +584,13 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
550
584
  else {
551
585
  finally_body = variant("Value", {
552
586
  type: toEastTypeValue(NullType),
553
- location: toLocationValue(ast.location),
587
+ location: toLocationValues(ast.location),
554
588
  value: variant("Null", null),
555
589
  });
556
590
  }
557
591
  return variant("TryCatch", {
558
592
  type: toEastTypeValue(ast.type),
559
- location: toLocationValue(ast.location),
593
+ location: toLocationValues(ast.location),
560
594
  try_body,
561
595
  catch_body,
562
596
  message,
@@ -592,18 +626,18 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
592
626
  throw new Error(`Unsupported literal value type: ${typeof ast.value} (expected ${printType(ast.type)})`);
593
627
  }
594
628
  if (type.type !== value.type) {
595
- throw new Error(`Literal value type mismatch at ${printLocation(ast.location)}: expected .${type.type} but got .${value.type}`);
629
+ throw new Error(`Literal value type mismatch at ${printLocations(ast.location)}: expected .${type.type} but got .${value.type}`);
596
630
  }
597
631
  return variant("Value", {
598
632
  type,
599
- location: toLocationValue(ast.location),
633
+ location: toLocationValues(ast.location),
600
634
  value,
601
635
  });
602
636
  }
603
637
  else if (ast.ast_type === "As") {
604
638
  return variant("As", {
605
639
  type: toEastTypeValue(ast.type),
606
- location: toLocationValue(ast.location),
640
+ location: toLocationValues(ast.location),
607
641
  value: ast_to_ir(ast.value, ctx),
608
642
  });
609
643
  }
@@ -611,7 +645,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
611
645
  const predicate = ast_to_ir(ast.predicate, ctx);
612
646
  const label = {
613
647
  name: `_${ctx.n_loops}`,
614
- location: toLocationValue(ast.label.location),
648
+ location: toLocationValues(ast.label.location),
615
649
  };
616
650
  ctx.n_loops += 1;
617
651
  const ctx2 = {
@@ -630,7 +664,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
630
664
  ctx.n_loops = ctx2.n_loops;
631
665
  return variant("While", {
632
666
  type: variant("Null", null),
633
- location: toLocationValue(ast.location),
667
+ location: toLocationValues(ast.location),
634
668
  label,
635
669
  predicate,
636
670
  body,
@@ -640,13 +674,13 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
640
674
  const array = ast_to_ir(ast.array, ctx);
641
675
  const label = {
642
676
  name: `_${ctx.n_loops}`,
643
- location: toLocationValue(ast.label.location),
677
+ location: toLocationValues(ast.label.location),
644
678
  };
645
679
  ctx.n_loops += 1;
646
680
  const value = variant("Variable", {
647
681
  type: toEastTypeValue(ast.value.type),
648
682
  name: `_${ctx.n_vars}`,
649
- location: toLocationValue(ast.value.location),
683
+ location: toLocationValues(ast.value.location),
650
684
  mutable: ast.value.mutable, // false...
651
685
  captured: false,
652
686
  });
@@ -654,7 +688,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
654
688
  const key = variant("Variable", {
655
689
  type: toEastTypeValue(ast.key.type),
656
690
  name: `_${ctx.n_vars}`,
657
- location: toLocationValue(ast.key.location),
691
+ location: toLocationValues(ast.key.location),
658
692
  mutable: ast.key.mutable, // false...
659
693
  captured: false,
660
694
  });
@@ -675,7 +709,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
675
709
  ctx.n_loops = ctx2.n_loops;
676
710
  return variant("ForArray", {
677
711
  type: variant("Null", null),
678
- location: toLocationValue(ast.location),
712
+ location: toLocationValues(ast.location),
679
713
  label,
680
714
  key,
681
715
  value,
@@ -687,13 +721,13 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
687
721
  const set = ast_to_ir(ast.set, ctx);
688
722
  const label = {
689
723
  name: `_${ctx.n_loops}`,
690
- location: toLocationValue(ast.label.location),
724
+ location: toLocationValues(ast.label.location),
691
725
  };
692
726
  ctx.n_loops += 1;
693
727
  const key = variant("Variable", {
694
728
  type: toEastTypeValue(ast.key.type),
695
729
  name: `_${ctx.n_vars}`,
696
- location: toLocationValue(ast.key.location),
730
+ location: toLocationValues(ast.key.location),
697
731
  mutable: ast.key.mutable, // false...
698
732
  captured: false,
699
733
  });
@@ -714,7 +748,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
714
748
  ctx.n_loops = ctx2.n_loops;
715
749
  return variant("ForSet", {
716
750
  type: variant("Null", null),
717
- location: toLocationValue(ast.location),
751
+ location: toLocationValues(ast.location),
718
752
  label,
719
753
  key,
720
754
  set,
@@ -725,13 +759,13 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
725
759
  const dict = ast_to_ir(ast.dict, ctx);
726
760
  const label = {
727
761
  name: `_${ctx.n_loops}`,
728
- location: toLocationValue(ast.label.location),
762
+ location: toLocationValues(ast.label.location),
729
763
  };
730
764
  ctx.n_loops += 1;
731
765
  const value = variant("Variable", {
732
766
  type: toEastTypeValue(ast.value.type),
733
767
  name: `_${ctx.n_vars}`,
734
- location: toLocationValue(ast.value.location),
768
+ location: toLocationValues(ast.value.location),
735
769
  mutable: ast.value.mutable, // false...
736
770
  captured: false,
737
771
  });
@@ -739,7 +773,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
739
773
  const key = variant("Variable", {
740
774
  type: toEastTypeValue(ast.key.type),
741
775
  name: `_${ctx.n_vars}`,
742
- location: toLocationValue(ast.key.location),
776
+ location: toLocationValues(ast.key.location),
743
777
  mutable: ast.key.mutable, // false...
744
778
  captured: false,
745
779
  });
@@ -760,7 +794,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
760
794
  ctx.n_loops = ctx2.n_loops;
761
795
  return variant("ForDict", {
762
796
  type: variant("Null", null),
763
- location: toLocationValue(ast.location),
797
+ location: toLocationValues(ast.location),
764
798
  label,
765
799
  key,
766
800
  value,
@@ -775,7 +809,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
775
809
  const variable = variant("Variable", {
776
810
  type: toEastTypeValue(v.variable.type),
777
811
  name: `_${ctx.n_vars}`,
778
- location: toLocationValue(v.variable.location),
812
+ location: toLocationValues(v.variable.location),
779
813
  mutable: v.variable.mutable, // false...
780
814
  captured: false,
781
815
  });
@@ -796,19 +830,19 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
796
830
  ctx.n_loops = ctx2.n_loops;
797
831
  if (v.body.type.type !== "Never" && !isTypeEqual(v.body.type, ast.type)) {
798
832
  if (!isSubtype(v.body.type, ast.type)) {
799
- throw new Error(`Match case '${k}' body of type ${printType(v.body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocation(ast.location)}`);
833
+ throw new Error(`Match case '${k}' body of type ${printType(v.body.type)} is not compatible with expected type ${printType(ast.type)} at ${printLocations(ast.location)}`);
800
834
  }
801
835
  body = variant("As", {
802
836
  type: toEastTypeValue(ast.type),
803
837
  value: body,
804
- location: toLocationValue(ast.location),
838
+ location: toLocationValues(ast.location),
805
839
  });
806
840
  }
807
841
  cases.push({ case: k, variable, body });
808
842
  }
809
843
  return variant("Match", {
810
844
  type: toEastTypeValue(ast.type),
811
- location: toLocationValue(ast.location),
845
+ location: toLocationValues(ast.location),
812
846
  variant: variant_expr,
813
847
  cases,
814
848
  });
@@ -816,7 +850,7 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
816
850
  else if (ast.ast_type === "UnwrapRecursive") {
817
851
  return variant("UnwrapRecursive", {
818
852
  type: toEastTypeValue(ast.type),
819
- location: toLocationValue(ast.location),
853
+ location: toLocationValues(ast.location),
820
854
  value: ast_to_ir(ast.value, ctx),
821
855
  });
822
856
  }
@@ -827,14 +861,14 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
827
861
  }
828
862
  const existing = ctx.recursiveASTs.has(ast);
829
863
  if (existing) {
830
- throw new Error(`Circular reference detected when converting AST to IR at ${printLocation(ast.location)}`);
864
+ throw new Error(`Circular reference detected when converting AST to IR at ${printLocations(ast.location)}`);
831
865
  }
832
866
  // Register before recursing (enables cycle detection)
833
867
  ctx.recursiveASTs.add(ast);
834
868
  // Create WrapRecursive IR node with placeholder
835
869
  const wrapIR = variant("WrapRecursive", {
836
870
  type: toEastTypeValue(ast.type),
837
- location: toLocationValue(ast.location),
871
+ location: toLocationValues(ast.location),
838
872
  value: ast_to_ir(ast.value, ctx),
839
873
  });
840
874
  // The user may alias this AST value elsewhere in the tree, just not with a circular reference
@@ -844,32 +878,32 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
844
878
  else if (ast.ast_type === "Break") {
845
879
  const label = ctx.loop_ctx.get(ast.label);
846
880
  if (label === undefined) {
847
- throw new Error(`Label defined at ${printLocation(ast.label.location)} is not in scope at break at ${printLocation(ast.location)}`);
881
+ throw new Error(`Label defined at ${printLocations(ast.label.location)} is not in scope at break at ${printLocations(ast.location)}`);
848
882
  }
849
883
  return variant("Break", {
850
884
  type: variant("Never", null),
851
- location: toLocationValue(ast.location),
885
+ location: toLocationValues(ast.location),
852
886
  label,
853
887
  });
854
888
  }
855
889
  else if (ast.ast_type === "Continue") {
856
890
  const label = ctx.loop_ctx.get(ast.label);
857
891
  if (label === undefined) {
858
- throw new Error(`Label defined at ${printLocation(ast.label.location)} is not in scope at continue at ${printLocation(ast.location)}`);
892
+ throw new Error(`Label defined at ${printLocations(ast.label.location)} is not in scope at continue at ${printLocations(ast.location)}`);
859
893
  }
860
894
  return variant("Continue", {
861
895
  type: variant("Never", null),
862
- location: toLocationValue(ast.location),
896
+ location: toLocationValues(ast.location),
863
897
  label,
864
898
  });
865
899
  }
866
900
  else if (ast.ast_type === "Return") {
867
901
  if (!isSubtype(ast.value.type, ctx.output)) {
868
- throw new Error(`Attempted to return value of type ${printType(ast.value.type)} at ${printLocation(ast.location)}, but function expected return type of ${printType(ctx.output)}`);
902
+ throw new Error(`Attempted to return value of type ${printType(ast.value.type)} at ${printLocations(ast.location)}, but function expected return type of ${printType(ctx.output)}`);
869
903
  }
870
904
  return variant("Return", {
871
905
  type: variant("Never", null),
872
- location: toLocationValue(ast.location),
906
+ location: toLocationValues(ast.location),
873
907
  value: ast_to_ir(ast.value, ctx),
874
908
  });
875
909
  }
@@ -880,13 +914,13 @@ export function ast_to_ir(ast, ctx = { local_ctx: new Map(), parent_ctx: new Map
880
914
  catch (e) {
881
915
  if (e instanceof Error) {
882
916
  if (ast.ast_type === "Builtin") {
883
- e.message += `\n at ${ast.ast_type} ${ast.builtin} node located at ${printLocation(ast.location)}`;
917
+ e.message += `\n at ${ast.ast_type} ${ast.builtin} node located at ${printLocations(ast.location)}`;
884
918
  }
885
919
  else if (ast.ast_type === "Platform") {
886
- e.message += `\n at ${ast.ast_type} ${ast.name} node located at ${printLocation(ast.location)}`;
920
+ e.message += `\n at ${ast.ast_type} ${ast.name} node located at ${printLocations(ast.location)}`;
887
921
  }
888
922
  else {
889
- e.message += `\n at ${ast.ast_type} node located at ${printLocation(ast.location)}`;
923
+ e.message += `\n at ${ast.ast_type} node located at ${printLocations(ast.location)}`;
890
924
  }
891
925
  }
892
926
  throw e;