@@ -183,6 +183,26 @@ class CLet extends Node {
183
183
184
184
type CExpr = CLet | ITE | CApp ;
185
185
186
+ const undefExpr : AExpr = t . identifier ( "undefined" ) ;
187
+
188
+ function addLoc ( obj : any ,
189
+ start : number ,
190
+ end : number ,
191
+ loc : t . SourceLocation ) : any {
192
+ for ( const prop in Object . keys ( obj ) ) {
193
+ if ( obj [ prop ] !== undefined &&
194
+ ( obj [ prop ] . loc === undefined || obj [ prop ] . loc === nullLoc ) ) {
195
+ obj . start = start ;
196
+ obj . end = end ;
197
+ obj [ prop ] = loc ;
198
+ if ( typeof obj [ prop ] === 'object' ) {
199
+ addLoc ( obj [ prop ] , start , end , loc ) ;
200
+ }
201
+ }
202
+ }
203
+ return obj ;
204
+ }
205
+
186
206
function cpsExprList ( exprs : t . Expression [ ] ,
187
207
k : ( args : AExpr [ ] ) => CExpr ,
188
208
ek : ( arg : AExpr ) => CExpr ,
@@ -200,8 +220,6 @@ function cpsExprList(exprs: t.Expression[],
200
220
}
201
221
}
202
222
203
- const undefExpr : AExpr = t . identifier ( "undefined" ) ;
204
-
205
223
function cpsObjMembers ( mems : t . ObjectMember [ ] ,
206
224
k : ( args : AExpr [ ] [ ] ) => CExpr ,
207
225
ek : ( arg : AExpr ) => CExpr ,
@@ -236,62 +254,64 @@ function cpsExpr(expr: t.Expression,
236
254
case 'NullLiteral' :
237
255
case 'RegExpLiteral' :
238
256
case 'TemplateLiteral' :
239
- return k ( expr ) ;
257
+ return addLoc ( k ( expr ) , expr . start , expr . end , expr . loc ) ;
240
258
case 'ArrayExpression' :
241
- return cpsExprList ( < t . Expression [ ] > expr . elements , ( args : AExpr [ ] ) => {
259
+ return addLoc ( cpsExprList ( < t . Expression [ ] > expr . elements , ( args : AExpr [ ] ) => {
242
260
const arr = path . scope . generateUidIdentifier ( 'arr' ) ;
243
261
return new CLet ( 'const' , arr , new BArrayLit ( args ) , k ( arr ) ) ;
244
- } , ek , path ) ;
262
+ } , ek , path ) , expr . start , expr . end , expr . loc ) ;
245
263
case "AssignmentExpression" :
246
- return cpsExpr ( expr . right , r => {
264
+ return addLoc ( cpsExpr ( expr . right , r => {
247
265
const assign = path . scope . generateUidIdentifier ( 'assign' ) ;
248
266
return new CLet ( 'const' , assign ,
249
267
new BAssign ( expr . operator , expr . left , r ) , k ( r ) ) ;
250
- } , ek , path ) ;
268
+ } , ek , path ) , expr . start , expr . end , expr . loc ) ;
251
269
case 'BinaryExpression' :
252
- return cpsExpr ( expr . left , l =>
270
+ return addLoc ( cpsExpr ( expr . left , l =>
253
271
cpsExpr ( expr . right , r => {
254
272
let bop = path . scope . generateUidIdentifier ( 'bop' ) ;
255
273
return new CLet ( 'const' , bop , new BOp2 ( expr . operator , l , r ) , k ( bop ) ) ;
256
- } , ek , path ) , ek , path ) ;
274
+ } , ek , path ) , ek , path ) , expr . start , expr . end , expr . loc ) ;
257
275
case 'ConditionalExpression' :
258
- return cpsExpr ( expr . test , tst => new ITE ( tst ,
276
+ return addLoc ( cpsExpr ( expr . test , tst => new ITE ( tst ,
259
277
cpsExpr ( expr . consequent , k , ek , path ) ,
260
- cpsExpr ( expr . alternate , k , ek , path ) ) , ek , path ) ;
278
+ cpsExpr ( expr . alternate , k , ek , path ) ) , ek , path ) ,
279
+ expr . start , expr . end , expr . loc ) ;
261
280
case 'UnaryExpression' :
262
- return cpsExpr ( expr . argument , v => {
281
+ return addLoc ( cpsExpr ( expr . argument , v => {
263
282
let unop = path . scope . generateUidIdentifier ( 'unop' ) ;
264
283
return new CLet ( 'const' , unop , new BOp1 ( expr . operator , v ) , k ( unop ) ) ;
265
- } , ek , path ) ;
284
+ } , ek , path ) , expr . start , expr . end , expr . loc ) ;
266
285
case "FunctionExpression" :
267
286
let func = path . scope . generateUidIdentifier ( 'func' ) ;
268
- return new CLet ( 'const' , func ,
287
+ return addLoc ( new CLet ( 'const' , func ,
269
288
new BFun ( expr . id , < t . Identifier [ ] > ( expr . params ) ,
270
289
cpsStmt ( expr . body ,
271
290
r => new CApp ( < t . Identifier > ( expr . params [ 0 ] ) , [ r ] ) ,
272
291
r => new CApp ( < t . Identifier > ( expr . params [ 1 ] ) , [ r ] ) ,
273
- path ) ) , k ( func ) ) ;
292
+ path ) ) , k ( func ) ) , expr . start , expr . end , expr . loc ) ;
274
293
case "CallExpression" :
275
- return cpsExpr ( expr . callee , f =>
294
+ return addLoc ( cpsExpr ( expr . callee , f =>
276
295
cpsExprList ( < t . Expression [ ] > ( expr . arguments ) , args => {
277
296
const kFun = path . scope . generateUidIdentifier ( 'kFun' ) ;
278
297
const kErr = path . scope . generateUidIdentifier ( 'kErr' ) ;
279
298
const r = path . scope . generateUidIdentifier ( 'r' ) ;
280
299
return new CLet ( 'const' , kFun , new BFun ( undefined , [ r ] , k ( r ) ) ,
281
300
new CLet ( 'const' , kErr , new BFun ( undefined , [ r ] , ek ( r ) ) ,
282
301
new CApp ( f , [ kFun , kErr , ...args ] ) ) ) ;
283
- } , ek , path ) , ek , path ) ;
302
+ } , ek , path ) , ek , path ) , expr . start , expr . end , expr . loc ) ;
284
303
case 'MemberExpression' :
285
- return cpsExpr ( expr . object , o =>
304
+ return addLoc ( cpsExpr ( expr . object , o =>
286
305
cpsExpr ( expr . property , p => {
287
306
const obj = path . scope . generateUidIdentifier ( 'obj' ) ;
288
307
return new CLet ( 'const' , obj , new BGet ( o , p ) , k ( obj ) ) ;
289
- } , ek , path ) , ek , path ) ;
308
+ } , ek , path ) , ek , path ) , expr . start , expr . end , expr . loc ) ;
290
309
case 'NewExpression' :
291
310
const tmp = path . scope . generateUidIdentifier ( 'new' ) ;
292
- return new CLet ( 'const' , tmp , expr , k ( tmp ) ) ;
311
+ return addLoc ( new CLet ( 'const' , tmp , expr , k ( tmp ) ) ,
312
+ expr . start , expr . end , expr . loc ) ;
293
313
case 'ObjectExpression' :
294
- return cpsObjMembers ( < t . ObjectMember [ ] > expr . properties ,
314
+ return addLoc ( cpsObjMembers ( < t . ObjectMember [ ] > expr . properties ,
295
315
( mems : AExpr [ ] [ ] ) => {
296
316
const obj = path . scope . generateUidIdentifier ( 'obj' ) ;
297
317
const fields = new Map ( ) ;
@@ -302,13 +322,13 @@ function cpsExpr(expr: t.Expression,
302
322
return new CLet ( 'const' , obj , new BObj ( fields ) , k ( obj ) ) ;
303
323
} ,
304
324
ek ,
305
- path ) ;
325
+ path ) , expr . start , expr . end , expr . loc ) ;
306
326
case 'UpdateExpression' :
307
- return cpsExpr ( expr . argument , ( v : AExpr ) => {
327
+ return addLoc ( cpsExpr ( expr . argument , ( v : AExpr ) => {
308
328
const tmp = path . scope . generateUidIdentifier ( 'update' ) ;
309
329
return new CLet ( 'const' , tmp ,
310
330
new BIncrDecr ( expr . operator , v , expr . prefix ) , k ( tmp ) ) ;
311
- } , ek , path ) ;
331
+ } , ek , path ) , expr . start , expr . end , expr . loc ) ;
312
332
}
313
333
throw new Error ( `${ expr . type } not yet implemented` ) ;
314
334
}
@@ -321,58 +341,64 @@ function cpsStmt(stmt: t.Statement,
321
341
case "BlockStatement" : {
322
342
let [ head , ...tail ] = stmt . body ;
323
343
if ( head === undefined ) {
324
- return k ( undefExpr ) ;
344
+ return addLoc ( k ( undefExpr ) , stmt . start , stmt . end , stmt . loc ) ;
325
345
} else if ( tail === [ ] ) {
326
- return cpsStmt ( head , k , ek , path ) ;
346
+ return addLoc ( cpsStmt ( head , k , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
327
347
} else {
328
- return cpsStmt ( head , v => cpsStmt ( t . blockStatement ( tail ) ,
329
- k , ek , path ) , ek , path ) ;
348
+ return addLoc ( cpsStmt ( head , v => cpsStmt ( t . blockStatement ( tail ) ,
349
+ k , ek , path ) , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
330
350
}
331
351
}
332
352
case "BreakStatement" :
333
- return cpsExpr ( stmt . label , label => new CApp ( label , [ undefExpr ] ) , ek , path ) ;
353
+ return addLoc ( cpsExpr ( stmt . label , label =>
354
+ new CApp ( label , [ undefExpr ] ) , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
334
355
case "EmptyStatement" :
335
- return k ( undefExpr ) ;
356
+ return addLoc ( k ( undefExpr ) , stmt . start , stmt . end , stmt . loc ) ;
336
357
case "ExpressionStatement" :
337
- return cpsExpr ( stmt . expression , _ => k ( undefExpr ) , ek , path ) ;
358
+ return addLoc ( cpsExpr ( stmt . expression , _ =>
359
+ k ( undefExpr ) , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
338
360
case "IfStatement" :
339
- return cpsExpr ( stmt . test , tst => new ITE ( tst ,
361
+ return addLoc ( cpsExpr ( stmt . test , tst => new ITE ( tst ,
340
362
cpsStmt ( stmt . consequent , k , ek , path ) ,
341
- cpsStmt ( stmt . alternate , k , ek , path ) ) , ek , path ) ;
363
+ cpsStmt ( stmt . alternate , k , ek , path ) ) , ek , path ) ,
364
+ stmt . start , stmt . end , stmt . loc ) ;
342
365
case "LabeledStatement" : {
343
366
const kErr = path . scope . generateUidIdentifier ( 'kErr' ) ;
344
- return cpsExpr ( t . callExpression ( t . functionExpression ( undefined ,
367
+ return addLoc ( cpsExpr ( t . callExpression ( t . functionExpression ( undefined ,
345
368
[ stmt . label , kErr ] , flatBodyStatement ( [ stmt . body ] ) ) , [ ] ) ,
346
- k , ek , path ) ;
369
+ k , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
347
370
}
348
371
case "ReturnStatement" :
349
372
let returnK = ( r : AExpr ) =>
350
373
new CApp ( < t . Identifier > ( < ReturnStatement > stmt ) . kArg , [ r ] ) ;
351
- return cpsExpr ( stmt . argument , r => returnK ( r ) , ek , path ) ;
374
+ return addLoc ( cpsExpr ( stmt . argument , r =>
375
+ returnK ( r ) , ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
352
376
case 'ThrowStatement' :
353
- return cpsExpr ( stmt . argument , ek , v => new CApp ( v , [ undefExpr ] ) , path ) ;
377
+ return addLoc ( cpsExpr ( stmt . argument , ek , v =>
378
+ new CApp ( v , [ undefExpr ] ) , path ) , stmt . start , stmt . end , stmt . loc ) ;
354
379
case 'TryStatement' :
355
380
const kFun = path . scope . generateUidIdentifier ( 'kFun' ) ;
356
381
const kErr = path . scope . generateUidIdentifier ( 'kErr' ) ;
357
- return cpsExpr ( t . callExpression ( t . functionExpression ( undefined ,
382
+ return addLoc ( cpsExpr ( t . callExpression ( t . functionExpression ( undefined ,
358
383
[ kFun , kErr ] ,
359
384
stmt . block ) , [ ] ) , k , e =>
360
385
new CLet ( 'const' , stmt . handler . param , new BAtom ( e ) ,
361
- cpsStmt ( stmt . handler . body , k , ek , path ) ) , path ) ;
386
+ cpsStmt ( stmt . handler . body , k , ek , path ) ) , path ) ,
387
+ stmt . start , stmt . end , stmt . loc ) ;
362
388
case "VariableDeclaration" : {
363
389
const { declarations } = stmt ;
364
390
const [ head , ...tail ] = declarations ;
365
391
if ( head === undefined ) {
366
- return k ( undefExpr ) ;
392
+ return addLoc ( k ( undefExpr ) , stmt . start , stmt . end , stmt . loc ) ;
367
393
} else if ( tail === [ ] ) {
368
- return cpsExpr ( head . init , v =>
394
+ return addLoc ( cpsExpr ( head . init , v =>
369
395
new CLet ( stmt . kind , < t . Identifier > head . id , new BAtom ( v ) , k ( undefExpr ) ) ,
370
- ek , path ) ;
396
+ ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
371
397
} else {
372
- return cpsExpr ( head . init , v =>
398
+ return addLoc ( cpsExpr ( head . init , v =>
373
399
new CLet ( stmt . kind , < t . Identifier > head . id , new BAtom ( v ) ,
374
400
cpsStmt ( t . variableDeclaration ( stmt . kind , tail ) , k , ek , path ) ) ,
375
- ek , path ) ;
401
+ ek , path ) , stmt . start , stmt . end , stmt . loc ) ;
376
402
}
377
403
}
378
404
default :
@@ -383,30 +409,38 @@ function cpsStmt(stmt: t.Statement,
383
409
function generateBExpr ( bexpr : BExpr ) : t . Expression {
384
410
switch ( bexpr . type ) {
385
411
case 'BFun' :
386
- return t . functionExpression ( bexpr . id ,
412
+ return addLoc ( t . functionExpression ( bexpr . id ,
387
413
bexpr . args ,
388
- flatBodyStatement ( generateJS ( bexpr . body ) ) ) ;
414
+ flatBodyStatement ( generateJS ( bexpr . body ) ) ) ,
415
+ bexpr . start , bexpr . end , bexpr . loc ) ;
389
416
case 'atom' :
390
417
return bexpr . atom ;
391
418
case 'op2' :
392
- return t . binaryExpression ( bexpr . name , bexpr . l , bexpr . r ) ;
419
+ return addLoc ( t . binaryExpression ( bexpr . name , bexpr . l , bexpr . r ) ,
420
+ bexpr . start , bexpr . end , bexpr . loc ) ;
393
421
case 'op1' :
394
- return t . unaryExpression ( bexpr . name , bexpr . v ) ;
422
+ return addLoc ( t . unaryExpression ( bexpr . name , bexpr . v ) ,
423
+ bexpr . start , bexpr . end , bexpr . loc ) ;
395
424
case 'assign' :
396
- return t . assignmentExpression ( bexpr . operator , bexpr . x , bexpr . v ) ;
425
+ return addLoc ( t . assignmentExpression ( bexpr . operator , bexpr . x , bexpr . v ) ,
426
+ bexpr . start , bexpr . end , bexpr . loc ) ;
397
427
case 'obj' :
398
428
const properties : t . ObjectProperty [ ] = [ ] ;
399
429
bexpr . fields . forEach ( ( value , key ) =>
400
430
properties . push ( t . objectProperty ( key , value ) ) ) ;
401
- return t . objectExpression ( properties ) ;
431
+ return addLoc ( t . objectExpression ( properties ) ,
432
+ bexpr . start , bexpr . end , bexpr . loc ) ;
402
433
case 'get' :
403
- return t . memberExpression ( bexpr . object , bexpr . property ) ;
434
+ return addLoc ( t . memberExpression ( bexpr . object , bexpr . property ) ,
435
+ bexpr . start , bexpr . end , bexpr . loc ) ;
404
436
case 'NewExpression' :
405
437
return bexpr ;
406
438
case 'incr/decr' :
407
- return t . updateExpression ( bexpr . operator , bexpr . argument , bexpr . prefix ) ;
439
+ return addLoc ( t . updateExpression ( bexpr . operator , bexpr . argument , bexpr . prefix ) ,
440
+ bexpr . start , bexpr . end , bexpr . loc ) ;
408
441
case 'arraylit' :
409
- return t . arrayExpression ( bexpr . arrayItems ) ;
442
+ return addLoc ( t . arrayExpression ( bexpr . arrayItems ) ,
443
+ bexpr . start , bexpr . end , bexpr . loc ) ;
410
444
case 'update' :
411
445
throw new Error ( `${ bexpr . type } generation is not yet implemented` ) ;
412
446
}
@@ -415,14 +449,17 @@ function generateBExpr(bexpr: BExpr): t.Expression {
415
449
function generateJS ( cexpr : CExpr ) : t . Statement [ ] {
416
450
switch ( cexpr . type ) {
417
451
case 'app' :
418
- return [ t . returnStatement ( t . callExpression ( cexpr . f , cexpr . args ) ) ] ;
452
+ return [ addLoc ( t . returnStatement ( t . callExpression ( cexpr . f , cexpr . args ) ) ,
453
+ cexpr . start , cexpr . end , cexpr . loc ) ] ;
419
454
case 'ITE' :
420
- return [ t . ifStatement ( cexpr . e1 ,
455
+ return [ addLoc ( t . ifStatement ( cexpr . e1 ,
421
456
flatBodyStatement ( generateJS ( cexpr . e2 ) ) ,
422
- flatBodyStatement ( generateJS ( cexpr . e3 ) ) ) ] ;
457
+ flatBodyStatement ( generateJS ( cexpr . e3 ) ) ) ,
458
+ cexpr . start , cexpr . end , cexpr . loc ) ] ;
423
459
case 'let' :
424
460
const decl = letExpression ( cexpr . x , generateBExpr ( cexpr . named ) , cexpr . kind ) ;
425
- return [ decl , ...generateJS ( cexpr . body ) ] ;
461
+ return [ addLoc ( decl , cexpr . start , cexpr . end , cexpr . loc ) ,
462
+ ...generateJS ( cexpr . body ) ] ;
426
463
}
427
464
}
428
465
0 commit comments