@@ -88,7 +88,8 @@ impl CodeInfo {
8888 | SetupExcept { handler : l }
8989 | SetupWith { end : l }
9090 | SetupAsyncWith { end : l }
91- | SetupLoop { end : l } => {
91+ | SetupLoop { end : l }
92+ | Continue { target : l } => {
9293 * l = label_map[ l. 0 ] . expect ( "label never set" ) ;
9394 }
9495
@@ -131,7 +132,7 @@ impl Default for CompileOpts {
131132
132133#[ derive( Debug , Clone , Copy ) ]
133134struct CompileContext {
134- in_loop : bool ,
135+ loop_data : Option < ( Label , Label ) > ,
135136 in_class : bool ,
136137 func : FunctionContext ,
137138}
@@ -144,6 +145,9 @@ enum FunctionContext {
144145}
145146
146147impl CompileContext {
148+ fn in_loop ( self ) -> bool {
149+ self . loop_data . is_some ( )
150+ }
147151 fn in_func ( self ) -> bool {
148152 self . func != FunctionContext :: NoFunction
149153 }
@@ -236,7 +240,7 @@ impl Compiler {
236240 current_qualified_path : None ,
237241 done_with_future_stmts : false ,
238242 ctx : CompileContext {
239- in_loop : false ,
243+ loop_data : None ,
240244 in_class : false ,
241245 func : FunctionContext :: NoFunction ,
242246 } ,
@@ -737,19 +741,21 @@ impl Compiler {
737741 }
738742 }
739743 Break => {
740- if !self . ctx . in_loop {
744+ if !self . ctx . in_loop ( ) {
741745 return Err ( self . error_loc ( CompileErrorType :: InvalidBreak , statement. location ) ) ;
742746 }
743747 self . emit ( Instruction :: Break ) ;
744748 }
745- Continue => {
746- if !self . ctx . in_loop {
749+ Continue => match self . ctx . loop_data {
750+ Some ( ( start, _) ) => {
751+ self . emit ( Instruction :: Continue { target : start } ) ;
752+ }
753+ None => {
747754 return Err (
748755 self . error_loc ( CompileErrorType :: InvalidContinue , statement. location )
749756 ) ;
750757 }
751- self . emit ( Instruction :: Continue ) ;
752- }
758+ } ,
753759 Return { value } => {
754760 if !self . ctx . in_func ( ) {
755761 return Err ( self . error_loc ( CompileErrorType :: InvalidReturn , statement. location ) ) ;
@@ -1052,7 +1058,7 @@ impl Compiler {
10521058 let prev_ctx = self . ctx ;
10531059
10541060 self . ctx = CompileContext {
1055- in_loop : false ,
1061+ loop_data : None ,
10561062 in_class : prev_ctx. in_class ,
10571063 func : if is_async {
10581064 FunctionContext :: AsyncFunction
@@ -1258,7 +1264,7 @@ impl Compiler {
12581264 self . ctx = CompileContext {
12591265 func : FunctionContext :: NoFunction ,
12601266 in_class : true ,
1261- in_loop : false ,
1267+ loop_data : None ,
12621268 } ;
12631269
12641270 let qualified_name = self . create_qualified_name ( name, "" ) ;
@@ -1399,10 +1405,10 @@ impl Compiler {
13991405
14001406 self . compile_jump_if ( test, false , else_label) ?;
14011407
1402- let was_in_loop = self . ctx . in_loop ;
1403- self . ctx . in_loop = true ;
1408+ let was_in_loop = self . ctx . loop_data ;
1409+ self . ctx . loop_data = Some ( ( start_label , end_label ) ) ;
14041410 self . compile_statements ( body) ?;
1405- self . ctx . in_loop = was_in_loop;
1411+ self . ctx . loop_data = was_in_loop;
14061412 self . emit ( Instruction :: Jump {
14071413 target : start_label,
14081414 } ) ;
@@ -1428,6 +1434,8 @@ impl Compiler {
14281434 let else_label = self . new_label ( ) ;
14291435 let end_label = self . new_label ( ) ;
14301436
1437+ self . emit ( Instruction :: SetupLoop { end : end_label } ) ;
1438+
14311439 // The thing iterated:
14321440 self . compile_expression ( iter) ?;
14331441
@@ -1437,7 +1445,6 @@ impl Compiler {
14371445
14381446 self . emit ( Instruction :: GetAIter ) ;
14391447
1440- self . emit ( Instruction :: SetupLoop { end : end_label } ) ;
14411448 self . set_label ( start_label) ;
14421449 self . emit ( Instruction :: SetupExcept {
14431450 handler : check_asynciter_label,
@@ -1459,26 +1466,25 @@ impl Compiler {
14591466 self . emit ( Instruction :: JumpIfTrue { target : else_label } ) ;
14601467 self . emit ( Instruction :: Raise { argc : 0 } ) ;
14611468
1462- let was_in_loop = self . ctx . in_loop ;
1463- self . ctx . in_loop = true ;
1469+ let was_in_loop = self . ctx . loop_data ;
1470+ self . ctx . loop_data = Some ( ( start_label , end_label ) ) ;
14641471 self . set_label ( body_label) ;
14651472 self . compile_statements ( body) ?;
1466- self . ctx . in_loop = was_in_loop;
1473+ self . ctx . loop_data = was_in_loop;
14671474 } else {
14681475 // Retrieve Iterator
14691476 self . emit ( Instruction :: GetIter ) ;
14701477
1471- self . emit ( Instruction :: SetupLoop { end : end_label } ) ;
14721478 self . set_label ( start_label) ;
14731479 self . emit ( Instruction :: ForIter { target : else_label } ) ;
14741480
14751481 // Start of loop iteration, set targets:
14761482 self . compile_store ( target) ?;
14771483
1478- let was_in_loop = self . ctx . in_loop ;
1479- self . ctx . in_loop = true ;
1484+ let was_in_loop = self . ctx . loop_data ;
1485+ self . ctx . loop_data = Some ( ( start_label , end_label ) ) ;
14801486 self . compile_statements ( body) ?;
1481- self . ctx . in_loop = was_in_loop;
1487+ self . ctx . loop_data = was_in_loop;
14821488 }
14831489
14841490 self . emit ( Instruction :: Jump {
@@ -2009,7 +2015,7 @@ impl Compiler {
20092015 Lambda { args, body } => {
20102016 let prev_ctx = self . ctx ;
20112017 self . ctx = CompileContext {
2012- in_loop : false ,
2018+ loop_data : Option :: None ,
20132019 in_class : prev_ctx. in_class ,
20142020 func : FunctionContext :: Function ,
20152021 } ;
@@ -2182,7 +2188,7 @@ impl Compiler {
21822188 let prev_ctx = self . ctx ;
21832189
21842190 self . ctx = CompileContext {
2185- in_loop : false ,
2191+ loop_data : None ,
21862192 in_class : prev_ctx. in_class ,
21872193 func : FunctionContext :: Function ,
21882194 } ;
0 commit comments