@@ -2290,6 +2290,8 @@ export class Compiler extends DiagnosticEmitter {
22902290 private compileBlockStatement (
22912291 statement : BlockStatement
22922292 ) : ExpressionRef {
2293+ if ( statement . label ) return this . compileLabeledBlockStatement ( statement ) ;
2294+
22932295 let statements = statement . statements ;
22942296 let outerFlow = this . currentFlow ;
22952297 let innerFlow = outerFlow . fork ( ) ;
@@ -2301,6 +2303,30 @@ export class Compiler extends DiagnosticEmitter {
23012303 return this . module . flatten ( stmts ) ;
23022304 }
23032305
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+
23042330 private compileTypeDeclaration ( statement : TypeDeclaration ) : ExpressionRef {
23052331 let flow = this . currentFlow ;
23062332 let name = statement . name . text ;
@@ -2324,23 +2350,25 @@ export class Compiler extends DiagnosticEmitter {
23242350 ) : ExpressionRef {
23252351 let module = this . module ;
23262352 let labelNode = statement . label ;
2353+ let flow = this . currentFlow ;
2354+ let breakLabel : string | null = null ;
23272355 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 ;
23342360 }
2335- let flow = this . currentFlow ;
2336- let breakLabel = flow . breakLabel ;
2361+
23372362 if ( breakLabel == null ) {
23382363 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 ,
23402367 statement . range
23412368 ) ;
23422369 return module . unreachable ( ) ;
23432370 }
2371+
23442372 flow . set ( FlowFlags . Breaks ) ;
23452373 return module . br ( breakLabel ) ;
23462374 }
@@ -2349,25 +2377,27 @@ export class Compiler extends DiagnosticEmitter {
23492377 statement : ContinueStatement
23502378 ) : ExpressionRef {
23512379 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 ;
23602388 }
2389+
23612390 // Check if 'continue' is allowed here
2362- let flow = this . currentFlow ;
2363- let continueLabel = flow . continueLabel ;
23642391 if ( continueLabel == null ) {
23652392 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 ,
23672396 statement . range
23682397 ) ;
23692398 return module . unreachable ( ) ;
23702399 }
2400+
23712401 flow . set ( FlowFlags . Continues | FlowFlags . Terminates ) ;
23722402 return module . br ( continueLabel ) ;
23732403 }
@@ -2409,6 +2439,8 @@ export class Compiler extends DiagnosticEmitter {
24092439 let continueLabel = `do-continue|${ label } ` ;
24102440 flow . continueLabel = continueLabel ;
24112441 let loopLabel = `do-loop|${ label } ` ;
2442+ let labelNode = statement . label ;
2443+ if ( labelNode ) flow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
24122444 this . currentFlow = flow ;
24132445 let bodyStmts = new Array < ExpressionRef > ( ) ;
24142446 let body = statement . body ;
@@ -2418,6 +2450,7 @@ export class Compiler extends DiagnosticEmitter {
24182450 bodyStmts . push ( this . compileStatement ( body ) ) ;
24192451 }
24202452 flow . popControlFlowLabel ( label ) ;
2453+ if ( labelNode ) flow . removeUserLabel ( labelNode . text ) ;
24212454
24222455 let possiblyContinues = flow . isAny ( FlowFlags . Continues | FlowFlags . ConditionallyContinues ) ;
24232456 let possiblyBreaks = flow . isAny ( FlowFlags . Breaks | FlowFlags . ConditionallyBreaks ) ;
@@ -2573,6 +2606,8 @@ export class Compiler extends DiagnosticEmitter {
25732606 bodyFlow . breakLabel = breakLabel ;
25742607 let continueLabel = `for-continue|${ label } ` ;
25752608 bodyFlow . continueLabel = continueLabel ;
2609+ let labelNode = statement . label ;
2610+ if ( labelNode ) bodyFlow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
25762611 let loopLabel = `for-loop|${ label } ` ;
25772612 this . currentFlow = bodyFlow ;
25782613 let bodyStmts = new Array < ExpressionRef > ( ) ;
@@ -2583,6 +2618,7 @@ export class Compiler extends DiagnosticEmitter {
25832618 bodyStmts . push ( this . compileStatement ( body ) ) ;
25842619 }
25852620 bodyFlow . popControlFlowLabel ( label ) ;
2621+ if ( labelNode ) bodyFlow . removeUserLabel ( labelNode . text ) ;
25862622 bodyFlow . breakLabel = null ;
25872623 bodyFlow . continueLabel = null ;
25882624
@@ -3208,6 +3244,8 @@ export class Compiler extends DiagnosticEmitter {
32083244 thenFlow . breakLabel = breakLabel ;
32093245 let continueLabel = `while-continue|${ label } ` ;
32103246 thenFlow . continueLabel = continueLabel ;
3247+ let labelNode = statement . label ;
3248+ if ( labelNode ) thenFlow . addUserLabel ( labelNode . text , breakLabel , continueLabel , labelNode ) ;
32113249 this . currentFlow = thenFlow ;
32123250 let bodyStmts = new Array < ExpressionRef > ( ) ;
32133251 let body = statement . body ;
@@ -3220,6 +3258,7 @@ export class Compiler extends DiagnosticEmitter {
32203258 module . br ( continueLabel )
32213259 ) ;
32223260 thenFlow . popControlFlowLabel ( label ) ;
3261+ if ( labelNode ) thenFlow . removeUserLabel ( labelNode . text ) ;
32233262
32243263 let possiblyContinues = thenFlow . isAny ( FlowFlags . Continues | FlowFlags . ConditionallyContinues ) ;
32253264 let possiblyBreaks = thenFlow . isAny ( FlowFlags . Breaks | FlowFlags . ConditionallyBreaks ) ;
0 commit comments