@@ -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
@@ -2802,6 +2838,7 @@ export class Compiler extends DiagnosticEmitter {
28022838  ) : ExpressionRef  { 
28032839    let  module  =  this . module ; 
28042840    let  cases  =  statement . cases ; 
2841+     let  labelNode  =  statement . label ; 
28052842    let  numCases  =  cases . length ; 
28062843
28072844    // Compile the condition (always executes) 
@@ -2824,6 +2861,9 @@ export class Compiler extends DiagnosticEmitter {
28242861    let  breakIndex  =  1 ; 
28252862    let  defaultIndex  =  - 1 ; 
28262863    let  label  =  outerFlow . pushControlFlowLabel ( ) ; 
2864+     let  breakLabel  =  `break|${ label }  ; 
2865+     if  ( labelNode )  outerFlow . addUserLabel ( labelNode . text ,  breakLabel ,  null ,  labelNode ) ; 
2866+ 
28272867    for  ( let  i  =  0 ;  i  <  numCases ;  ++ i )  { 
28282868      let  case_  =  cases [ i ] ; 
28292869      if  ( case_ . isDefault )  { 
@@ -2843,7 +2883,7 @@ export class Compiler extends DiagnosticEmitter {
28432883    // If there is a default case, break to it, otherwise break out of the switch 
28442884    breaks [ breakIndex ]  =  module . br ( defaultIndex  >=  0 
28452885      ? `case${ defaultIndex } ${ label }  
2846-       : `break| ${ label } ` 
2886+       : breakLabel 
28472887    ) ; 
28482888
28492889    // Nest the case blocks in order, to be targeted by the br_if sequence 
@@ -2859,7 +2899,6 @@ export class Compiler extends DiagnosticEmitter {
28592899      let  innerFlow  =  outerFlow . fork ( /* newBreakContext */  true ,  /* newContinueContext */  false ) ; 
28602900      if  ( fallThroughFlow )  innerFlow . mergeBranch ( fallThroughFlow ) ; 
28612901      this . currentFlow  =  innerFlow ; 
2862-       let  breakLabel  =  `break|${ label }  ; 
28632902      innerFlow . breakLabel  =  breakLabel ; 
28642903
28652904      let  isLast  =  i  ==  numCases  -  1 ; 
@@ -2897,6 +2936,7 @@ export class Compiler extends DiagnosticEmitter {
28972936      currentBlock  =  module . block ( nextLabel ,  stmts ,  TypeRef . None ) ;  // must be a labeled block 
28982937    } 
28992938    outerFlow . popControlFlowLabel ( label ) ; 
2939+     if  ( labelNode )  outerFlow . removeUserLabel ( labelNode . text ) ; 
29002940
29012941    // If the switch has a default, we only get past through any breaking flow 
29022942    if  ( defaultIndex  >=  0 )  { 
@@ -3208,6 +3248,8 @@ export class Compiler extends DiagnosticEmitter {
32083248    thenFlow . breakLabel  =  breakLabel ; 
32093249    let  continueLabel  =  `while-continue|${ label }  ; 
32103250    thenFlow . continueLabel  =  continueLabel ; 
3251+     let  labelNode  =  statement . label ; 
3252+     if  ( labelNode )  thenFlow . addUserLabel ( labelNode . text ,  breakLabel ,  continueLabel ,  labelNode ) ; 
32113253    this . currentFlow  =  thenFlow ; 
32123254    let  bodyStmts  =  new  Array < ExpressionRef > ( ) ; 
32133255    let  body  =  statement . body ; 
@@ -3220,6 +3262,7 @@ export class Compiler extends DiagnosticEmitter {
32203262      module . br ( continueLabel ) 
32213263    ) ; 
32223264    thenFlow . popControlFlowLabel ( label ) ; 
3265+     if  ( labelNode )  thenFlow . removeUserLabel ( labelNode . text ) ; 
32233266
32243267    let  possiblyContinues  =  thenFlow . isAny ( FlowFlags . Continues  |  FlowFlags . ConditionallyContinues ) ; 
32253268    let  possiblyBreaks  =  thenFlow . isAny ( FlowFlags . Breaks  |  FlowFlags . ConditionallyBreaks ) ; 
0 commit comments