@@ -27,12 +27,32 @@ struct Compiler<O: OutputStream = BasicOutputStream> {
2727 source_path : Option < String > ,
2828 current_source_location : ast:: Location ,
2929 current_qualified_path : Option < String > ,
30- in_loop : bool ,
31- in_function_def : bool ,
32- in_async_func : bool ,
30+ ctx : CompileContext ,
3331 optimize : u8 ,
3432}
3533
34+ #[ derive( Clone , Copy ) ]
35+ struct CompileContext {
36+ in_loop : bool ,
37+ func : FunctionContext ,
38+ }
39+
40+ #[ derive( Clone , Copy ) ]
41+ enum FunctionContext {
42+ NoFunction ,
43+ Function ,
44+ AsyncFunction ,
45+ }
46+
47+ impl CompileContext {
48+ fn in_func ( self ) -> bool {
49+ match self . func {
50+ FunctionContext :: NoFunction => false ,
51+ _ => true ,
52+ }
53+ }
54+ }
55+
3656/// Compile a given sourcecode into a bytecode object.
3757pub fn compile (
3858 source : & str ,
@@ -125,9 +145,10 @@ impl<O: OutputStream> Compiler<O> {
125145 source_path : None ,
126146 current_source_location : ast:: Location :: default ( ) ,
127147 current_qualified_path : None ,
128- in_loop : false ,
129- in_function_def : false ,
130- in_async_func : false ,
148+ ctx : CompileContext {
149+ in_loop : false ,
150+ func : FunctionContext :: NoFunction ,
151+ } ,
131152 optimize,
132153 }
133154 }
@@ -510,7 +531,7 @@ impl<O: OutputStream> Compiler<O> {
510531 }
511532 }
512533 Break => {
513- if !self . in_loop {
534+ if !self . ctx . in_loop {
514535 return Err ( CompileError {
515536 error : CompileErrorType :: InvalidBreak ,
516537 location : statement. location . clone ( ) ,
@@ -519,7 +540,7 @@ impl<O: OutputStream> Compiler<O> {
519540 self . emit ( Instruction :: Break ) ;
520541 }
521542 Continue => {
522- if !self . in_loop {
543+ if !self . ctx . in_loop {
523544 return Err ( CompileError {
524545 error : CompileErrorType :: InvalidContinue ,
525546 location : statement. location . clone ( ) ,
@@ -528,7 +549,7 @@ impl<O: OutputStream> Compiler<O> {
528549 self . emit ( Instruction :: Continue ) ;
529550 }
530551 Return { value } => {
531- if !self . in_function_def {
552+ if !self . ctx . in_func ( ) {
532553 return Err ( CompileError {
533554 error : CompileErrorType :: InvalidReturn ,
534555 location : statement. location . clone ( ) ,
@@ -814,17 +835,20 @@ impl<O: OutputStream> Compiler<O> {
814835 is_async : bool ,
815836 ) -> Result < ( ) , CompileError > {
816837 // Create bytecode for this function:
817- // remember to restore self.in_loop to the original after the function is compiled
818- let was_in_loop = self . in_loop ;
819- let was_in_function_def = self . in_function_def ;
838+ // remember to restore self.ctx.in_loop to the original after the function is compiled
839+ let prev_ctx = self . ctx ;
820840
821- let was_in_async_func = self . in_async_func ;
822- self . in_async_func = is_async;
823- self . in_loop = false ;
824- self . in_function_def = true ;
841+ self . ctx = CompileContext {
842+ in_loop : false ,
843+ func : if is_async {
844+ FunctionContext :: AsyncFunction
845+ } else {
846+ FunctionContext :: Function
847+ } ,
848+ } ;
825849
826- let old_qualified_path = self . current_qualified_path . clone ( ) ;
827850 let qualified_name = self . create_qualified_name ( name, "" ) ;
851+ let old_qualified_path = self . current_qualified_path . take ( ) ;
828852 self . current_qualified_path = Some ( self . create_qualified_name ( name, ".<locals>" ) ) ;
829853
830854 self . prepare_decorators ( decorator_list) ?;
@@ -911,9 +935,7 @@ impl<O: OutputStream> Compiler<O> {
911935 self . store_name ( name) ;
912936
913937 self . current_qualified_path = old_qualified_path;
914- self . in_loop = was_in_loop;
915- self . in_function_def = was_in_function_def;
916- self . in_async_func = was_in_async_func;
938+ self . ctx = prev_ctx;
917939 Ok ( ( ) )
918940 }
919941
@@ -925,11 +947,14 @@ impl<O: OutputStream> Compiler<O> {
925947 keywords : & [ ast:: Keyword ] ,
926948 decorator_list : & [ ast:: Expression ] ,
927949 ) -> Result < ( ) , CompileError > {
928- let was_in_loop = self . in_loop ;
929- self . in_loop = false ;
950+ let prev_ctx = self . ctx ;
951+ self . ctx = CompileContext {
952+ func : FunctionContext :: NoFunction ,
953+ in_loop : false ,
954+ } ;
930955
931- let old_qualified_path = self . current_qualified_path . clone ( ) ;
932956 let qualified_name = self . create_qualified_name ( name, "" ) ;
957+ let old_qualified_path = self . current_qualified_path . take ( ) ;
933958 self . current_qualified_path = Some ( qualified_name. clone ( ) ) ;
934959
935960 self . prepare_decorators ( decorator_list) ?;
@@ -1033,7 +1058,7 @@ impl<O: OutputStream> Compiler<O> {
10331058
10341059 self . store_name ( name) ;
10351060 self . current_qualified_path = old_qualified_path;
1036- self . in_loop = was_in_loop ;
1061+ self . ctx = prev_ctx ;
10371062 Ok ( ( ) )
10381063 }
10391064
@@ -1075,10 +1100,10 @@ impl<O: OutputStream> Compiler<O> {
10751100
10761101 self . compile_jump_if ( test, false , else_label) ?;
10771102
1078- let was_in_loop = self . in_loop ;
1079- self . in_loop = true ;
1103+ let was_in_loop = self . ctx . in_loop ;
1104+ self . ctx . in_loop = true ;
10801105 self . compile_statements ( body) ?;
1081- self . in_loop = was_in_loop;
1106+ self . ctx . in_loop = was_in_loop;
10821107 self . emit ( Instruction :: Jump {
10831108 target : start_label,
10841109 } ) ;
@@ -1143,11 +1168,11 @@ impl<O: OutputStream> Compiler<O> {
11431168 self . emit ( Instruction :: JumpIfTrue { target : else_label } ) ;
11441169 self . emit ( Instruction :: Raise { argc : 0 } ) ;
11451170
1146- let was_in_loop = self . in_loop ;
1147- self . in_loop = true ;
1171+ let was_in_loop = self . ctx . in_loop ;
1172+ self . ctx . in_loop = true ;
11481173 self . set_label ( body_label) ;
11491174 self . compile_statements ( body) ?;
1150- self . in_loop = was_in_loop;
1175+ self . ctx . in_loop = was_in_loop;
11511176 } else {
11521177 // Retrieve Iterator
11531178 self . emit ( Instruction :: GetIter ) ;
@@ -1158,10 +1183,10 @@ impl<O: OutputStream> Compiler<O> {
11581183 // Start of loop iteration, set targets:
11591184 self . compile_store ( target) ?;
11601185
1161- let was_in_loop = self . in_loop ;
1162- self . in_loop = true ;
1186+ let was_in_loop = self . ctx . in_loop ;
1187+ self . ctx . in_loop = true ;
11631188 self . compile_statements ( body) ?;
1164- self . in_loop = was_in_loop;
1189+ self . ctx . in_loop = was_in_loop;
11651190 }
11661191
11671192 self . emit ( Instruction :: Jump {
@@ -1617,7 +1642,7 @@ impl<O: OutputStream> Compiler<O> {
16171642 self . emit ( Instruction :: BuildSlice { size } ) ;
16181643 }
16191644 Yield { value } => {
1620- if !self . in_function_def || self . in_async_func {
1645+ if !self . ctx . in_func ( ) {
16211646 return Err ( CompileError {
16221647 error : CompileErrorType :: InvalidYield ,
16231648 location : self . current_source_location . clone ( ) ,
@@ -1683,12 +1708,11 @@ impl<O: OutputStream> Compiler<O> {
16831708 self . load_name ( name) ;
16841709 }
16851710 Lambda { args, body } => {
1686- let was_in_loop = self . in_loop ;
1687- let was_in_function_def = self . in_function_def ;
1688- let was_in_async_func = self . in_async_func ;
1689- self . in_async_func = false ;
1690- self . in_loop = false ;
1691- self . in_function_def = true ;
1711+ let prev_ctx = self . ctx ;
1712+ self . ctx = CompileContext {
1713+ in_loop : false ,
1714+ func : FunctionContext :: Function ,
1715+ } ;
16921716
16931717 let name = "<lambda>" . to_string ( ) ;
16941718 self . enter_function ( & name, args) ?;
@@ -1707,9 +1731,7 @@ impl<O: OutputStream> Compiler<O> {
17071731 // Turn code object into function object:
17081732 self . emit ( Instruction :: MakeFunction ) ;
17091733
1710- self . in_loop = was_in_loop;
1711- self . in_function_def = was_in_function_def;
1712- self . in_async_func = was_in_async_func;
1734+ self . ctx = prev_ctx;
17131735 }
17141736 Comprehension { kind, generators } => {
17151737 self . compile_comprehension ( kind, generators) ?;
0 commit comments