@@ -29,8 +29,21 @@ struct Compiler<O: OutputStream = BasicOutputStream> {
2929 source_path : Option < String > ,
3030 current_source_location : ast:: Location ,
3131 current_qualified_path : Option < String > ,
32+ done_with_future_stmts : bool ,
3233 ctx : CompileContext ,
33- optimize : u8 ,
34+ opts : CompileOpts ,
35+ }
36+
37+ #[ derive( Debug , Clone ) ]
38+ pub struct CompileOpts {
39+ /// How optimized the bytecode output should be; any optimize > 0 does
40+ /// not emit assert statements
41+ pub optimize : u8 ,
42+ }
43+ impl Default for CompileOpts {
44+ fn default ( ) -> Self {
45+ CompileOpts { optimize : 0 }
46+ }
3447}
3548
3649#[ derive( Clone , Copy ) ]
@@ -60,31 +73,31 @@ pub fn compile(
6073 source : & str ,
6174 mode : Mode ,
6275 source_path : String ,
63- optimize : u8 ,
76+ opts : CompileOpts ,
6477) -> CompileResult < CodeObject > {
6578 match mode {
6679 Mode :: Exec => {
6780 let ast = parser:: parse_program ( source) ?;
68- compile_program ( ast, source_path, optimize )
81+ compile_program ( ast, source_path, opts )
6982 }
7083 Mode :: Eval => {
7184 let statement = parser:: parse_statement ( source) ?;
72- compile_statement_eval ( statement, source_path, optimize )
85+ compile_statement_eval ( statement, source_path, opts )
7386 }
7487 Mode :: Single => {
7588 let ast = parser:: parse_program ( source) ?;
76- compile_program_single ( ast, source_path, optimize )
89+ compile_program_single ( ast, source_path, opts )
7790 }
7891 }
7992}
8093
8194/// A helper function for the shared code of the different compile functions
8295fn with_compiler (
8396 source_path : String ,
84- optimize : u8 ,
97+ opts : CompileOpts ,
8598 f : impl FnOnce ( & mut Compiler ) -> CompileResult < ( ) > ,
8699) -> CompileResult < CodeObject > {
87- let mut compiler = Compiler :: new ( optimize ) ;
100+ let mut compiler = Compiler :: new ( opts ) ;
88101 compiler. source_path = Some ( source_path) ;
89102 compiler. push_new_code_object ( "<module>" . to_owned ( ) ) ;
90103 f ( & mut compiler) ?;
@@ -97,9 +110,9 @@ fn with_compiler(
97110pub fn compile_program (
98111 ast : ast:: Program ,
99112 source_path : String ,
100- optimize : u8 ,
113+ opts : CompileOpts ,
101114) -> CompileResult < CodeObject > {
102- with_compiler ( source_path, optimize , |compiler| {
115+ with_compiler ( source_path, opts , |compiler| {
103116 let symbol_table = make_symbol_table ( & ast) ?;
104117 compiler. compile_program ( & ast, symbol_table)
105118 } )
@@ -109,9 +122,9 @@ pub fn compile_program(
109122pub fn compile_statement_eval (
110123 statement : Vec < ast:: Statement > ,
111124 source_path : String ,
112- optimize : u8 ,
125+ opts : CompileOpts ,
113126) -> CompileResult < CodeObject > {
114- with_compiler ( source_path, optimize , |compiler| {
127+ with_compiler ( source_path, opts , |compiler| {
115128 let symbol_table = statements_to_symbol_table ( & statement) ?;
116129 compiler. compile_statement_eval ( & statement, symbol_table)
117130 } )
@@ -121,9 +134,9 @@ pub fn compile_statement_eval(
121134pub fn compile_program_single (
122135 ast : ast:: Program ,
123136 source_path : String ,
124- optimize : u8 ,
137+ opts : CompileOpts ,
125138) -> CompileResult < CodeObject > {
126- with_compiler ( source_path, optimize , |compiler| {
139+ with_compiler ( source_path, opts , |compiler| {
127140 let symbol_table = make_symbol_table ( & ast) ?;
128141 compiler. compile_program_single ( & ast, symbol_table)
129142 } )
@@ -134,24 +147,25 @@ where
134147 O : OutputStream ,
135148{
136149 fn default ( ) -> Self {
137- Compiler :: new ( 0 )
150+ Compiler :: new ( CompileOpts :: default ( ) )
138151 }
139152}
140153
141154impl < O : OutputStream > Compiler < O > {
142- fn new ( optimize : u8 ) -> Self {
155+ fn new ( opts : CompileOpts ) -> Self {
143156 Compiler {
144157 output_stack : Vec :: new ( ) ,
145158 symbol_table_stack : Vec :: new ( ) ,
146159 nxt_label : 0 ,
147160 source_path : None ,
148161 current_source_location : ast:: Location :: default ( ) ,
149162 current_qualified_path : None ,
163+ done_with_future_stmts : false ,
150164 ctx : CompileContext {
151165 in_loop : false ,
152166 func : FunctionContext :: NoFunction ,
153167 } ,
154- optimize ,
168+ opts ,
155169 }
156170 }
157171
@@ -314,6 +328,16 @@ impl<O: OutputStream> Compiler<O> {
314328 self . set_source_location ( statement. location ) ;
315329 use ast:: StatementType :: * ;
316330
331+ match & statement. node {
332+ // we do this here because `from __future__` still executes that `from` statement at runtime,
333+ // we still need to compile the ImportFrom down below
334+ ImportFrom { module, names, .. } if module. as_deref ( ) == Some ( "__future__" ) => {
335+ self . compile_future_features ( & names) ?
336+ }
337+ // if we find any other statement, stop accepting future statements
338+ _ => self . done_with_future_stmts = true ,
339+ }
340+
317341 match & statement. node {
318342 Import { names } => {
319343 // import a, b, c as d
@@ -518,7 +542,7 @@ impl<O: OutputStream> Compiler<O> {
518542 } => self . compile_class_def ( name, body, bases, keywords, decorator_list) ?,
519543 Assert { test, msg } => {
520544 // if some flag, ignore all assert statements!
521- if self . optimize == 0 {
545+ if self . opts . optimize == 0 {
522546 let end_label = self . new_label ( ) ;
523547 self . compile_jump_if ( test, true , end_label) ?;
524548 self . emit ( Instruction :: LoadName {
@@ -2112,6 +2136,28 @@ impl<O: OutputStream> Compiler<O> {
21122136 Ok ( ( ) )
21132137 }
21142138
2139+ fn compile_future_features (
2140+ & mut self ,
2141+ features : & [ ast:: ImportSymbol ] ,
2142+ ) -> Result < ( ) , CompileError > {
2143+ if self . done_with_future_stmts {
2144+ return Err ( self . error ( CompileErrorType :: InvalidFuturePlacement ) ) ;
2145+ }
2146+ for feature in features {
2147+ match & * feature. symbol {
2148+ // Python 3 features; we've already implemented them by default
2149+ "nested_scopes" | "generators" | "division" | "absolute_import"
2150+ | "with_statement" | "print_function" | "unicode_literals" => { }
2151+ // "generator_stop" => {}
2152+ // "annotations" => {}
2153+ other => {
2154+ return Err ( self . error ( CompileErrorType :: InvalidFutureFeature ( other. to_owned ( ) ) ) )
2155+ }
2156+ }
2157+ }
2158+ Ok ( ( ) )
2159+ }
2160+
21152161 // Scope helpers:
21162162 fn enter_scope ( & mut self ) {
21172163 // println!("Enter scope {:?}", self.symbol_table_stack);
0 commit comments