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