@@ -2290,6 +2290,8 @@ export class Compiler extends DiagnosticEmitter {
2290
2290
private compileBlockStatement (
2291
2291
statement : BlockStatement
2292
2292
) : ExpressionRef {
2293
+ if ( statement . label ) return this . compileLabeledBlockStatement ( statement ) ;
2294
+
2293
2295
let statements = statement . statements ;
2294
2296
let outerFlow = this . currentFlow ;
2295
2297
let innerFlow = outerFlow . fork ( ) ;
@@ -2301,6 +2303,30 @@ export class Compiler extends DiagnosticEmitter {
2301
2303
return this . module . flatten ( stmts ) ;
2302
2304
}
2303
2305
2306
+ private compileLabeledBlockStatement (
2307
+ statement : BlockStatement
2308
+ ) : ExpressionRef {
2309
+ let statements = statement . statements ;
2310
+ let outerFlow = this . currentFlow ;
2311
+ let innerFlow = outerFlow . fork ( ) ;
2312
+
2313
+ let labelNode = assert ( statement . label ) ;
2314
+ let label = innerFlow . pushControlFlowLabel ( ) ;
2315
+ let breakLabel = `block-break|${ label } `
2316
+ innerFlow . addUserLabel ( labelNode . text , breakLabel , null , labelNode ) ;
2317
+ this . currentFlow = innerFlow ;
2318
+
2319
+ let stmts = this . compileStatements ( statements ) ;
2320
+ innerFlow . popControlFlowLabel ( label ) ;
2321
+ innerFlow . removeUserLabel ( labelNode . text ) ;
2322
+
2323
+ outerFlow . inherit ( innerFlow ) ;
2324
+ this . currentFlow = outerFlow ;
2325
+ return innerFlow . isAny ( FlowFlags . Breaks | FlowFlags . ConditionallyBreaks )
2326
+ ? this . module . block ( breakLabel , stmts )
2327
+ : this . module . flatten ( stmts ) ;
2328
+ }
2329
+
2304
2330
private compileTypeDeclaration ( statement : TypeDeclaration ) : ExpressionRef {
2305
2331
let flow = this . currentFlow ;
2306
2332
let name = statement . name . text ;
@@ -2324,23 +2350,25 @@ export class Compiler extends DiagnosticEmitter {
2324
2350
) : ExpressionRef {
2325
2351
let module = this . module ;
2326
2352
let labelNode = statement . label ;
2353
+ let flow = this . currentFlow ;
2354
+ let breakLabel : string | null = null ;
2327
2355
if ( labelNode ) {
2328
- this . error (
2329
- DiagnosticCode . Not_implemented_0 ,
2330
- labelNode . range ,
2331
- "Break label"
2332
- ) ;
2333
- return module . unreachable ( ) ;
2356
+ const userLabel = flow . getUserLabel ( labelNode . text ) ;
2357
+ if ( userLabel ) breakLabel = userLabel . breakLabel ;
2358
+ } else {
2359
+ breakLabel = flow . breakLabel ;
2334
2360
}
2335
- let flow = this . currentFlow ;
2336
- let breakLabel = flow . breakLabel ;
2361
+
2337
2362
if ( breakLabel == null ) {
2338
2363
this . error (
2339
- DiagnosticCode . A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement ,
2364
+ labelNode
2365
+ ? DiagnosticCode . A_break_statement_can_only_jump_to_a_label_of_an_enclosing_statement
2366
+ : DiagnosticCode . A_break_statement_can_only_be_used_within_an_enclosing_iteration_or_switch_statement ,
2340
2367
statement . range
2341
2368
) ;
2342
2369
return module . unreachable ( ) ;
2343
2370
}
2371
+
2344
2372
flow . set ( FlowFlags . Breaks ) ;
2345
2373
return module . br ( breakLabel ) ;
2346
2374
}
@@ -2349,25 +2377,27 @@ export class Compiler extends DiagnosticEmitter {
2349
2377
statement : ContinueStatement
2350
2378
) : ExpressionRef {
2351
2379
let module = this . module ;
2352
- let label = statement . label ;
2353
- if ( label ) {
2354
- this . error (
2355
- DiagnosticCode . Not_implemented_0 ,
2356
- label . range ,
2357
- "Continue label"
2358
- ) ;
2359
- return module . unreachable ( ) ;
2380
+ let labelNode = statement . label ;
2381
+ let flow = this . currentFlow ;
2382
+ let continueLabel : string | null = null ;
2383
+ if ( labelNode ) {
2384
+ const userLabel = flow . getUserLabel ( labelNode . text ) ;
2385
+ if ( userLabel ) continueLabel = userLabel . continueLabel ;
2386
+ } else {
2387
+ continueLabel = flow . continueLabel ;
2360
2388
}
2389
+
2361
2390
// Check if 'continue' is allowed here
2362
- let flow = this . currentFlow ;
2363
- let continueLabel = flow . continueLabel ;
2364
2391
if ( continueLabel == null ) {
2365
2392
this . error (
2366
- DiagnosticCode . A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement ,
2393
+ labelNode
2394
+ ? DiagnosticCode . A_continue_statement_can_only_jump_to_a_label_of_an_enclosing_iteration_statement
2395
+ : DiagnosticCode . A_continue_statement_can_only_be_used_within_an_enclosing_iteration_statement ,
2367
2396
statement . range
2368
2397
) ;
2369
2398
return module . unreachable ( ) ;
2370
2399
}
2400
+
2371
2401
flow . set ( FlowFlags . Continues | FlowFlags . Terminates ) ;
2372
2402
return module . br ( continueLabel ) ;
2373
2403
}
@@ -2409,6 +2439,8 @@ export class Compiler extends DiagnosticEmitter {
2409
2439
let continueLabel = `do-continue|${ label } ` ;
2410
2440
flow . continueLabel = continueLabel ;
2411
2441
let loopLabel = `do-loop|${ label } ` ;
2442
+ let labelNode = statement . label ;
2443
+ if ( labelNode ) flow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
2412
2444
this . currentFlow = flow ;
2413
2445
let bodyStmts = new Array < ExpressionRef > ( ) ;
2414
2446
let body = statement . body ;
@@ -2418,6 +2450,7 @@ export class Compiler extends DiagnosticEmitter {
2418
2450
bodyStmts . push ( this . compileStatement ( body ) ) ;
2419
2451
}
2420
2452
flow . popControlFlowLabel ( label ) ;
2453
+ if ( labelNode ) flow . removeUserLabel ( labelNode . text ) ;
2421
2454
2422
2455
let possiblyContinues = flow . isAny ( FlowFlags . Continues | FlowFlags . ConditionallyContinues ) ;
2423
2456
let possiblyBreaks = flow . isAny ( FlowFlags . Breaks | FlowFlags . ConditionallyBreaks ) ;
@@ -2573,6 +2606,8 @@ export class Compiler extends DiagnosticEmitter {
2573
2606
bodyFlow . breakLabel = breakLabel ;
2574
2607
let continueLabel = `for-continue|${ label } ` ;
2575
2608
bodyFlow . continueLabel = continueLabel ;
2609
+ let labelNode = statement . label ;
2610
+ if ( labelNode ) bodyFlow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
2576
2611
let loopLabel = `for-loop|${ label } ` ;
2577
2612
this . currentFlow = bodyFlow ;
2578
2613
let bodyStmts = new Array < ExpressionRef > ( ) ;
@@ -2583,6 +2618,7 @@ export class Compiler extends DiagnosticEmitter {
2583
2618
bodyStmts . push ( this . compileStatement ( body ) ) ;
2584
2619
}
2585
2620
bodyFlow . popControlFlowLabel ( label ) ;
2621
+ if ( labelNode ) bodyFlow . removeUserLabel ( labelNode . text ) ;
2586
2622
bodyFlow . breakLabel = null ;
2587
2623
bodyFlow . continueLabel = null ;
2588
2624
@@ -3208,6 +3244,8 @@ export class Compiler extends DiagnosticEmitter {
3208
3244
thenFlow . breakLabel = breakLabel ;
3209
3245
let continueLabel = `while-continue|${ label } ` ;
3210
3246
thenFlow . continueLabel = continueLabel ;
3247
+ let labelNode = statement . label ;
3248
+ if ( labelNode ) thenFlow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
3211
3249
this . currentFlow = thenFlow ;
3212
3250
let bodyStmts = new Array < ExpressionRef > ( ) ;
3213
3251
let body = statement . body ;
@@ -3220,6 +3258,7 @@ export class Compiler extends DiagnosticEmitter {
3220
3258
module . br ( continueLabel )
3221
3259
) ;
3222
3260
thenFlow . popControlFlowLabel ( label ) ;
3261
+ if ( labelNode ) thenFlow . removeUserLabel ( labelNode . text ) ;
3223
3262
3224
3263
let possiblyContinues = thenFlow . isAny ( FlowFlags . Continues | FlowFlags . ConditionallyContinues ) ;
3225
3264
let possiblyBreaks = thenFlow . isAny ( FlowFlags . Breaks | FlowFlags . ConditionallyBreaks ) ;
0 commit comments