@@ -17,6 +17,7 @@ struct Compiler {
17
17
source_path : Option < String > ,
18
18
current_source_location : ast:: Location ,
19
19
in_loop : bool ,
20
+ in_function_def : bool ,
20
21
}
21
22
22
23
/// Compile a given sourcecode into a bytecode object.
@@ -75,6 +76,7 @@ impl Compiler {
75
76
source_path : None ,
76
77
current_source_location : ast:: Location :: default ( ) ,
77
78
in_loop : false ,
79
+ in_function_def : false ,
78
80
}
79
81
}
80
82
@@ -232,9 +234,10 @@ impl Compiler {
232
234
233
235
self . compile_test ( test, None , Some ( else_label) , EvalContext :: Statement ) ?;
234
236
237
+ let was_in_loop = self . in_loop ;
235
238
self . in_loop = true ;
236
239
self . compile_statements ( body) ?;
237
- self . in_loop = false ;
240
+ self . in_loop = was_in_loop ;
238
241
self . emit ( Instruction :: Jump {
239
242
target : start_label,
240
243
} ) ;
@@ -295,10 +298,10 @@ impl Compiler {
295
298
// Start of loop iteration, set targets:
296
299
self . compile_store ( target) ?;
297
300
298
- // Body of loop:
301
+ let was_in_loop = self . in_loop ;
299
302
self . in_loop = true ;
300
303
self . compile_statements ( body) ?;
301
- self . in_loop = false ;
304
+ self . in_loop = was_in_loop ;
302
305
303
306
self . emit ( Instruction :: Jump {
304
307
target : start_label,
@@ -431,6 +434,11 @@ impl Compiler {
431
434
decorator_list,
432
435
} => {
433
436
// Create bytecode for this function:
437
+ // remember to restore self.in_loop to the original after the function is compiled
438
+ let was_in_loop = self . in_loop ;
439
+ let was_in_function_def = self . in_function_def ;
440
+ self . in_loop = false ;
441
+ self . in_function_def = true ;
434
442
let flags = self . enter_function ( name, args) ?;
435
443
self . compile_statements ( body) ?;
436
444
@@ -458,6 +466,8 @@ impl Compiler {
458
466
self . emit ( Instruction :: StoreName {
459
467
name : name. to_string ( ) ,
460
468
} ) ;
469
+ self . in_loop = was_in_loop;
470
+ self . in_function_def = was_in_function_def;
461
471
}
462
472
ast:: Statement :: ClassDef {
463
473
name,
@@ -466,6 +476,8 @@ impl Compiler {
466
476
keywords,
467
477
decorator_list,
468
478
} => {
479
+ let was_in_loop = self . in_loop ;
480
+ self . in_loop = false ;
469
481
self . prepare_decorators ( decorator_list) ?;
470
482
self . emit ( Instruction :: LoadBuildClass ) ;
471
483
let line_number = self . get_source_line_number ( ) ;
@@ -546,6 +558,7 @@ impl Compiler {
546
558
self . emit ( Instruction :: StoreName {
547
559
name : name. to_string ( ) ,
548
560
} ) ;
561
+ self . in_loop = was_in_loop;
549
562
}
550
563
ast:: Statement :: Assert { test, msg } => {
551
564
// TODO: if some flag, ignore all assert statements!
@@ -584,6 +597,9 @@ impl Compiler {
584
597
self . emit ( Instruction :: Continue ) ;
585
598
}
586
599
ast:: Statement :: Return { value } => {
600
+ if !self . in_function_def {
601
+ return Err ( CompileError :: InvalidReturn ) ;
602
+ }
587
603
match value {
588
604
Some ( e) => {
589
605
let size = e. len ( ) ;
@@ -663,7 +679,6 @@ impl Compiler {
663
679
name : & str ,
664
680
args : & ast:: Parameters ,
665
681
) -> Result < bytecode:: FunctionOpArg , CompileError > {
666
- self . in_loop = false ;
667
682
let have_kwargs = !args. defaults . is_empty ( ) ;
668
683
if have_kwargs {
669
684
// Construct a tuple:
@@ -971,6 +986,9 @@ impl Compiler {
971
986
self . emit ( Instruction :: BuildSlice { size } ) ;
972
987
}
973
988
ast:: Expression :: Yield { value } => {
989
+ if !self . in_function_def {
990
+ return Err ( CompileError :: InvalidYield ) ;
991
+ }
974
992
self . mark_generator ( ) ;
975
993
match value {
976
994
Some ( expression) => self . compile_expression ( expression) ?,
@@ -1021,6 +1039,7 @@ impl Compiler {
1021
1039
}
1022
1040
ast:: Expression :: Lambda { args, body } => {
1023
1041
let name = "<lambda>" . to_string ( ) ;
1042
+ // no need to worry about the self.loop_depth because there are no loops in lambda expressions
1024
1043
let flags = self . enter_function ( & name, args) ?;
1025
1044
self . compile_expression ( body) ?;
1026
1045
self . emit ( Instruction :: ReturnValue ) ;
@@ -1369,10 +1388,11 @@ impl Compiler {
1369
1388
1370
1389
// Low level helper functions:
1371
1390
fn emit ( & mut self , instruction : Instruction ) {
1372
- self . current_code_object ( ) . instructions . push ( instruction) ;
1373
- // TODO: insert source filename
1374
1391
let location = self . current_source_location . clone ( ) ;
1375
- self . current_code_object ( ) . locations . push ( location) ;
1392
+ let mut cur_code_obj = self . current_code_object ( ) ;
1393
+ cur_code_obj. instructions . push ( instruction) ;
1394
+ cur_code_obj. locations . push ( location) ;
1395
+ // TODO: insert source filename
1376
1396
}
1377
1397
1378
1398
fn current_code_object ( & mut self ) -> & mut CodeObject {
@@ -1413,6 +1433,7 @@ mod tests {
1413
1433
use crate :: bytecode:: Constant :: * ;
1414
1434
use crate :: bytecode:: Instruction :: * ;
1415
1435
use rustpython_parser:: parser;
1436
+
1416
1437
fn compile_exec ( source : & str ) -> CodeObject {
1417
1438
let mut compiler = Compiler :: new ( ) ;
1418
1439
compiler. source_path = Some ( "source_path" . to_string ( ) ) ;
0 commit comments