@@ -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