@@ -20,32 +20,39 @@ struct Compiler {
2020 current_qualified_path : Option < String > ,
2121 in_loop : bool ,
2222 in_function_def : bool ,
23+ optimize : bool ,
2324}
2425
2526/// Compile a given sourcecode into a bytecode object.
26- pub fn compile ( source : & str , mode : & Mode , source_path : String ) -> Result < CodeObject , CompileError > {
27+ pub fn compile (
28+ source : & str ,
29+ mode : & Mode ,
30+ source_path : String ,
31+ optimize : bool ,
32+ ) -> Result < CodeObject , CompileError > {
2733 match mode {
2834 Mode :: Exec => {
2935 let ast = parser:: parse_program ( source) ?;
30- compile_program ( ast, source_path)
36+ compile_program ( ast, source_path, optimize )
3137 }
3238 Mode :: Eval => {
3339 let statement = parser:: parse_statement ( source) ?;
34- compile_statement_eval ( statement, source_path)
40+ compile_statement_eval ( statement, source_path, optimize )
3541 }
3642 Mode :: Single => {
3743 let ast = parser:: parse_program ( source) ?;
38- compile_program_single ( ast, source_path)
44+ compile_program_single ( ast, source_path, optimize )
3945 }
4046 }
4147}
4248
4349/// A helper function for the shared code of the different compile functions
4450fn with_compiler (
4551 source_path : String ,
52+ optimize : bool ,
4653 f : impl FnOnce ( & mut Compiler ) -> Result < ( ) , CompileError > ,
4754) -> Result < CodeObject , CompileError > {
48- let mut compiler = Compiler :: new ( ) ;
55+ let mut compiler = Compiler :: new ( optimize ) ;
4956 compiler. source_path = Some ( source_path) ;
5057 compiler. push_new_code_object ( "<module>" . to_string ( ) ) ;
5158 f ( & mut compiler) ?;
@@ -55,8 +62,12 @@ fn with_compiler(
5562}
5663
5764/// Compile a standard Python program to bytecode
58- pub fn compile_program ( ast : ast:: Program , source_path : String ) -> Result < CodeObject , CompileError > {
59- with_compiler ( source_path, |compiler| {
65+ pub fn compile_program (
66+ ast : ast:: Program ,
67+ source_path : String ,
68+ optimize : bool ,
69+ ) -> Result < CodeObject , CompileError > {
70+ with_compiler ( source_path, optimize, |compiler| {
6071 let symbol_table = make_symbol_table ( & ast) ?;
6172 compiler. compile_program ( & ast, symbol_table)
6273 } )
@@ -66,8 +77,9 @@ pub fn compile_program(ast: ast::Program, source_path: String) -> Result<CodeObj
6677pub fn compile_statement_eval (
6778 statement : Vec < ast:: LocatedStatement > ,
6879 source_path : String ,
80+ optimize : bool ,
6981) -> Result < CodeObject , CompileError > {
70- with_compiler ( source_path, |compiler| {
82+ with_compiler ( source_path, optimize , |compiler| {
7183 let symbol_table = statements_to_symbol_table ( & statement) ?;
7284 compiler. compile_statement_eval ( & statement, symbol_table)
7385 } )
@@ -77,8 +89,9 @@ pub fn compile_statement_eval(
7789pub fn compile_program_single (
7890 ast : ast:: Program ,
7991 source_path : String ,
92+ optimize : bool ,
8093) -> Result < CodeObject , CompileError > {
81- with_compiler ( source_path, |compiler| {
94+ with_compiler ( source_path, optimize , |compiler| {
8295 let symbol_table = make_symbol_table ( & ast) ?;
8396 compiler. compile_program_single ( & ast, symbol_table)
8497 } )
@@ -98,8 +111,14 @@ enum EvalContext {
98111
99112type Label = usize ;
100113
114+ impl Default for Compiler {
115+ fn default ( ) -> Self {
116+ Compiler :: new ( false )
117+ }
118+ }
119+
101120impl Compiler {
102- fn new ( ) -> Self {
121+ fn new ( optimize : bool ) -> Self {
103122 Compiler {
104123 code_object_stack : Vec :: new ( ) ,
105124 scope_stack : Vec :: new ( ) ,
@@ -109,6 +128,7 @@ impl Compiler {
109128 current_qualified_path : None ,
110129 in_loop : false ,
111130 in_function_def : false ,
131+ optimize,
112132 }
113133 }
114134
@@ -434,29 +454,30 @@ impl Compiler {
434454 decorator_list,
435455 } => self . compile_class_def ( name, body, bases, keywords, decorator_list) ?,
436456 ast:: Statement :: Assert { test, msg } => {
437- // TODO: if some flag, ignore all assert statements!
438-
439- let end_label = self . new_label ( ) ;
440- self . compile_test ( test, Some ( end_label) , None , EvalContext :: Statement ) ?;
441- self . emit ( Instruction :: LoadName {
442- name : String :: from ( "AssertionError" ) ,
443- scope : bytecode:: NameScope :: Local ,
444- } ) ;
445- match msg {
446- Some ( e) => {
447- self . compile_expression ( e) ?;
448- self . emit ( Instruction :: CallFunction {
449- typ : CallType :: Positional ( 1 ) ,
450- } ) ;
451- }
452- None => {
453- self . emit ( Instruction :: CallFunction {
454- typ : CallType :: Positional ( 0 ) ,
455- } ) ;
457+ // if some flag, ignore all assert statements!
458+ if !self . optimize {
459+ let end_label = self . new_label ( ) ;
460+ self . compile_test ( test, Some ( end_label) , None , EvalContext :: Statement ) ?;
461+ self . emit ( Instruction :: LoadName {
462+ name : String :: from ( "AssertionError" ) ,
463+ scope : bytecode:: NameScope :: Local ,
464+ } ) ;
465+ match msg {
466+ Some ( e) => {
467+ self . compile_expression ( e) ?;
468+ self . emit ( Instruction :: CallFunction {
469+ typ : CallType :: Positional ( 1 ) ,
470+ } ) ;
471+ }
472+ None => {
473+ self . emit ( Instruction :: CallFunction {
474+ typ : CallType :: Positional ( 0 ) ,
475+ } ) ;
476+ }
456477 }
478+ self . emit ( Instruction :: Raise { argc : 1 } ) ;
479+ self . set_label ( end_label) ;
457480 }
458- self . emit ( Instruction :: Raise { argc : 1 } ) ;
459- self . set_label ( end_label) ;
460481 }
461482 ast:: Statement :: Break => {
462483 if !self . in_loop {
@@ -1868,7 +1889,7 @@ mod tests {
18681889 use rustpython_parser:: parser;
18691890
18701891 fn compile_exec ( source : & str ) -> CodeObject {
1871- let mut compiler = Compiler :: new ( ) ;
1892+ let mut compiler: Compiler = Default :: default ( ) ;
18721893 compiler. source_path = Some ( "source_path" . to_string ( ) ) ;
18731894 compiler. push_new_code_object ( "<module>" . to_string ( ) ) ;
18741895 let ast = parser:: parse_program ( & source. to_string ( ) ) . unwrap ( ) ;
0 commit comments