@elaraai/east 1.0.30 → 1.0.32

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.
@@ -22,7 +22,7 @@ import { StructExpr } from "./struct.js";
22
22
  import { VariantExpr } from "./variant.js";
23
23
  import { RecursiveExpr } from "./recursive.js";
24
24
  import { createFunctionExpr, FunctionExpr } from "./function.js";
25
- import { valueOrExprToAst, valueOrExprToAstTyped } from "./ast.js";
25
+ import { astUnderCurrentSourceMap, valueOrExprToAst, valueOrExprToAstTyped } from "./ast.js";
26
26
  import { toEastTypeValue } from "../type_of_type.js";
27
27
  import { isVariant } from "../containers/variant.js";
28
28
  import { RefExpr } from "./ref.js";
@@ -135,167 +135,181 @@ export function from(value, type) {
135
135
  if (typeof value !== "function") {
136
136
  throw new Error(`Expected function but got ${typeof value}`);
137
137
  }
138
- const { inputs, output } = type;
139
- const input_variables = inputs.map(i => ({
140
- ast_type: "Variable",
141
- type: i,
142
- loc_id: get_location_id(),
143
- mutable: false,
144
- }));
145
- const $ = BlockBuilder(output);
146
- const input_exprs = input_variables.map(fromAst);
147
- const ret = value($, ...input_exprs);
148
- const statements = $.statements;
149
- if (ret !== undefined) {
150
- if (ret instanceof Expr) {
151
- // It is possible this expression is already the last statement.
152
- // Input of the form `$ => $.xxx()` or `$ => { ...; return $.xxx(); }` will cause this
153
- // So we filter out this case to avoid unintended repeated statements (and if users write an identical expression twice, they won't be `===`)
154
- if (statements.length === 0 || statements[statements.length - 1] !== ret[AstSymbol]) {
155
- statements.push(Expr.ast(ret));
138
+ // Build under a source map (inheriting any ambient one) and stamp the
139
+ // map on the result so a later embed can re-intern the locations —
140
+ // otherwise a top-level East.value(lambda, FunctionType) loses its
141
+ // pointer to user code (issue #204).
142
+ return ensure_source_map(() => {
143
+ const { inputs, output } = type;
144
+ const input_variables = inputs.map(i => ({
145
+ ast_type: "Variable",
146
+ type: i,
147
+ loc_id: get_location_id(),
148
+ mutable: false,
149
+ }));
150
+ const $ = BlockBuilder(output);
151
+ const input_exprs = input_variables.map(fromAst);
152
+ const ret = value($, ...input_exprs);
153
+ const statements = $.statements;
154
+ if (ret !== undefined) {
155
+ if (ret instanceof Expr) {
156
+ // It is possible this expression is already the last statement.
157
+ // Input of the form `$ => $.xxx()` or `$ => { ...; return $.xxx(); }` will cause this
158
+ // So we filter out this case to avoid unintended repeated statements (and if users write an identical expression twice, they won't be `===`)
159
+ if (statements.length === 0 || statements[statements.length - 1] !== ret[AstSymbol]) {
160
+ statements.push(Expr.ast(ret));
161
+ }
156
162
  }
157
- }
158
- else {
159
- const retAst = valueOrExprToAstTyped(ret, output);
160
- statements.push(retAst);
161
- }
162
- }
163
- let body_ast;
164
- if (isTypeEqual(output, NullType)) {
165
- if (statements.length === 0) {
166
- body_ast = { ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null };
167
- }
168
- else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
169
- body_ast = statements[0];
170
- }
171
- else {
172
- if (!isSubtype(statements[statements.length - 1].type, NullType)) {
173
- statements.push({ ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null });
163
+ else {
164
+ const retAst = valueOrExprToAstTyped(ret, output);
165
+ statements.push(retAst);
174
166
  }
175
- body_ast = {
176
- ast_type: "Block",
177
- type: statements[statements.length - 1].type,
178
- loc_id: get_location_id(),
179
- statements: statements,
180
- };
181
167
  }
182
- }
183
- else {
184
- if (statements.length === 0) {
185
- throw new Error(`Function expected output of type ${printType(output)}, but no function body or statements were provided`);
186
- }
187
- else if (statements.length === 1) {
188
- if (!isSubtype(statements[0].type, output)) {
189
- throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[0].type)}`);
168
+ let body_ast;
169
+ if (isTypeEqual(output, NullType)) {
170
+ if (statements.length === 0) {
171
+ body_ast = { ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null };
172
+ }
173
+ else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
174
+ body_ast = statements[0];
175
+ }
176
+ else {
177
+ if (!isSubtype(statements[statements.length - 1].type, NullType)) {
178
+ statements.push({ ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null });
179
+ }
180
+ body_ast = {
181
+ ast_type: "Block",
182
+ type: statements[statements.length - 1].type,
183
+ loc_id: get_location_id(),
184
+ statements: statements,
185
+ };
190
186
  }
191
- body_ast = statements[0];
192
187
  }
193
188
  else {
194
- if (!isSubtype(statements[statements.length - 1].type, output)) {
195
- throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[statements.length - 1].type)}`);
189
+ if (statements.length === 0) {
190
+ throw new Error(`Function expected output of type ${printType(output)}, but no function body or statements were provided`);
191
+ }
192
+ else if (statements.length === 1) {
193
+ if (!isSubtype(statements[0].type, output)) {
194
+ throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[0].type)}`);
195
+ }
196
+ body_ast = statements[0];
197
+ }
198
+ else {
199
+ if (!isSubtype(statements[statements.length - 1].type, output)) {
200
+ throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[statements.length - 1].type)}`);
201
+ }
202
+ body_ast = {
203
+ ast_type: "Block",
204
+ type: statements[statements.length - 1].type,
205
+ loc_id: get_location_id(),
206
+ statements: statements,
207
+ };
196
208
  }
197
- body_ast = {
198
- ast_type: "Block",
199
- type: statements[statements.length - 1].type,
200
- loc_id: get_location_id(),
201
- statements: statements,
202
- };
203
209
  }
204
- }
205
- if (!isSubtype(body_ast.type, output)) {
206
- throw new Error(`Expected function definition to return type ${printType(output)}, got ${printType(body_ast.type)}`);
207
- }
208
- const ast = {
209
- ast_type: "Function",
210
- type: FunctionType(inputs, output),
211
- loc_id: get_location_id(),
212
- parameters: input_variables,
213
- body: body_ast,
214
- };
215
- return fromAst(ast);
210
+ if (!isSubtype(body_ast.type, output)) {
211
+ throw new Error(`Expected function definition to return type ${printType(output)}, got ${printType(body_ast.type)}`);
212
+ }
213
+ const ast = {
214
+ ast_type: "Function",
215
+ type: FunctionType(inputs, output),
216
+ loc_id: get_location_id(),
217
+ parameters: input_variables,
218
+ body: body_ast,
219
+ };
220
+ const expr = fromAst(ast);
221
+ Object.defineProperty(expr, SourceMapSymbol, { enumerable: false, value: get_current_source_map() });
222
+ Object.defineProperty(ast, SourceMapSymbol, { enumerable: false, value: get_current_source_map() });
223
+ return expr;
224
+ }); // ensure_source_map
216
225
  }
217
226
  else if (type && type.type === "AsyncFunction") {
218
227
  if (typeof value !== "function") {
219
228
  throw new Error(`Expected function but got ${typeof value}`);
220
229
  }
221
- const { inputs, output } = type;
222
- const input_variables = inputs.map(i => ({
223
- ast_type: "Variable",
224
- type: i,
225
- loc_id: get_location_id(),
226
- mutable: false,
227
- }));
228
- const $ = BlockBuilder(output);
229
- const input_exprs = input_variables.map(fromAst);
230
- const ret = value($, ...input_exprs);
231
- const statements = $.statements;
232
- if (ret !== undefined) {
233
- if (ret instanceof Expr) {
234
- // It is possible this expression is already the last statement.
235
- // Input of the form `$ => $.xxx()` or `$ => { ...; return $.xxx(); }` will cause this
236
- // So we filter out this case to avoid unintended repeated statements (and if users write an identical expression twice, they won't be `===`)
237
- if (statements.length === 0 || statements[statements.length - 1] !== ret[AstSymbol]) {
238
- statements.push(Expr.ast(ret));
230
+ return ensure_source_map(() => {
231
+ const { inputs, output } = type;
232
+ const input_variables = inputs.map(i => ({
233
+ ast_type: "Variable",
234
+ type: i,
235
+ loc_id: get_location_id(),
236
+ mutable: false,
237
+ }));
238
+ const $ = BlockBuilder(output);
239
+ const input_exprs = input_variables.map(fromAst);
240
+ const ret = value($, ...input_exprs);
241
+ const statements = $.statements;
242
+ if (ret !== undefined) {
243
+ if (ret instanceof Expr) {
244
+ // It is possible this expression is already the last statement.
245
+ // Input of the form `$ => $.xxx()` or `$ => { ...; return $.xxx(); }` will cause this
246
+ // So we filter out this case to avoid unintended repeated statements (and if users write an identical expression twice, they won't be `===`)
247
+ if (statements.length === 0 || statements[statements.length - 1] !== ret[AstSymbol]) {
248
+ statements.push(Expr.ast(ret));
249
+ }
239
250
  }
240
- }
241
- else {
242
- const retAst = valueOrExprToAstTyped(ret, output);
243
- statements.push(retAst);
244
- }
245
- }
246
- let body_ast;
247
- if (isTypeEqual(output, NullType)) {
248
- if (statements.length === 0) {
249
- body_ast = { ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null };
250
- }
251
- else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
252
- body_ast = statements[0];
253
- }
254
- else {
255
- if (!isSubtype(statements[statements.length - 1].type, NullType)) {
256
- statements.push({ ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null });
251
+ else {
252
+ const retAst = valueOrExprToAstTyped(ret, output);
253
+ statements.push(retAst);
257
254
  }
258
- body_ast = {
259
- ast_type: "Block",
260
- type: statements[statements.length - 1].type,
261
- loc_id: get_location_id(),
262
- statements: statements,
263
- };
264
255
  }
265
- }
266
- else {
267
- if (statements.length === 0) {
268
- throw new Error(`Function expected output of type ${printType(output)}, but no function body or statements were provided`);
269
- }
270
- else if (statements.length === 1) {
271
- if (!isSubtype(statements[0].type, output)) {
272
- throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[0].type)}`);
256
+ let body_ast;
257
+ if (isTypeEqual(output, NullType)) {
258
+ if (statements.length === 0) {
259
+ body_ast = { ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null };
260
+ }
261
+ else if (statements.length === 1 && isSubtype(statements[0].type, NullType)) {
262
+ body_ast = statements[0];
263
+ }
264
+ else {
265
+ if (!isSubtype(statements[statements.length - 1].type, NullType)) {
266
+ statements.push({ ast_type: "Value", type: NullType, loc_id: get_location_id(), value: null });
267
+ }
268
+ body_ast = {
269
+ ast_type: "Block",
270
+ type: statements[statements.length - 1].type,
271
+ loc_id: get_location_id(),
272
+ statements: statements,
273
+ };
273
274
  }
274
- body_ast = statements[0];
275
275
  }
276
276
  else {
277
- if (!isSubtype(statements[statements.length - 1].type, output)) {
278
- throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[statements.length - 1].type)}`);
277
+ if (statements.length === 0) {
278
+ throw new Error(`Function expected output of type ${printType(output)}, but no function body or statements were provided`);
279
+ }
280
+ else if (statements.length === 1) {
281
+ if (!isSubtype(statements[0].type, output)) {
282
+ throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[0].type)}`);
283
+ }
284
+ body_ast = statements[0];
285
+ }
286
+ else {
287
+ if (!isSubtype(statements[statements.length - 1].type, output)) {
288
+ throw new Error(`Function expected output of type ${printType(output)}, but function body has type ${printType(statements[statements.length - 1].type)}`);
289
+ }
290
+ body_ast = {
291
+ ast_type: "Block",
292
+ type: statements[statements.length - 1].type,
293
+ loc_id: get_location_id(),
294
+ statements: statements,
295
+ };
279
296
  }
280
- body_ast = {
281
- ast_type: "Block",
282
- type: statements[statements.length - 1].type,
283
- loc_id: get_location_id(),
284
- statements: statements,
285
- };
286
297
  }
287
- }
288
- if (!isSubtype(body_ast.type, output)) {
289
- throw new Error(`Expected function definition to return type ${printType(output)}, got ${printType(body_ast.type)}`);
290
- }
291
- const ast = {
292
- ast_type: "AsyncFunction",
293
- type: FunctionType(inputs, output),
294
- loc_id: get_location_id(),
295
- parameters: input_variables,
296
- body: body_ast,
297
- };
298
- return fromAst(ast);
298
+ if (!isSubtype(body_ast.type, output)) {
299
+ throw new Error(`Expected function definition to return type ${printType(output)}, got ${printType(body_ast.type)}`);
300
+ }
301
+ const ast = {
302
+ ast_type: "AsyncFunction",
303
+ type: FunctionType(inputs, output),
304
+ loc_id: get_location_id(),
305
+ parameters: input_variables,
306
+ body: body_ast,
307
+ };
308
+ const expr = fromAst(ast);
309
+ Object.defineProperty(expr, SourceMapSymbol, { enumerable: false, value: get_current_source_map() });
310
+ Object.defineProperty(ast, SourceMapSymbol, { enumerable: false, value: get_current_source_map() });
311
+ return expr;
312
+ }); // ensure_source_map
299
313
  }
300
314
  const ast = type ? valueOrExprToAstTyped(value, type) : valueOrExprToAst(value);
301
315
  return fromAst(ast);
@@ -1549,7 +1563,7 @@ export const BlockBuilder = (return_type) => {
1549
1563
  if (type && !isSubtype(Expr.type(value), type)) {
1550
1564
  throw typeMismatchError(Expr.type(value), type, { loc_id: get_location_id() });
1551
1565
  }
1552
- ast = Expr.ast(value);
1566
+ ast = astUnderCurrentSourceMap(value);
1553
1567
  }
1554
1568
  else {
1555
1569
  ast = type ? valueOrExprToAstTyped(value, type) : valueOrExprToAst(value);
@@ -1578,7 +1592,7 @@ export const BlockBuilder = (return_type) => {
1578
1592
  if (type && !isSubtype(Expr.type(value), type)) {
1579
1593
  throw typeMismatchError(Expr.type(value), type, { loc_id: get_location_id() });
1580
1594
  }
1581
- ast = Expr.ast(value);
1595
+ ast = astUnderCurrentSourceMap(value);
1582
1596
  }
1583
1597
  else {
1584
1598
  ast = type ? valueOrExprToAstTyped(value, type) : valueOrExprToAst(value);