@@ -10,12 +10,14 @@ use crate::error::CompileError;
10
10
use crate :: obj:: objcode;
11
11
use crate :: obj:: objcode:: PyCodeRef ;
12
12
use crate :: pyobject:: PyValue ;
13
+ use crate :: symboltable:: { make_symbol_table, statements_to_symbol_table, SymbolRole , SymbolScope } ;
13
14
use crate :: VirtualMachine ;
14
15
use num_complex:: Complex64 ;
15
16
use rustpython_parser:: { ast, parser} ;
16
17
17
18
struct Compiler {
18
19
code_object_stack : Vec < CodeObject > ,
20
+ scope_stack : Vec < SymbolScope > ,
19
21
nxt_label : usize ,
20
22
source_path : Option < String > ,
21
23
current_source_location : ast:: Location ,
@@ -38,15 +40,18 @@ pub fn compile(
38
40
match mode {
39
41
Mode :: Exec => {
40
42
let ast = parser:: parse_program ( source) . map_err ( CompileError :: Parse ) ?;
41
- compiler. compile_program ( & ast)
43
+ let symbol_table = make_symbol_table ( & ast) ;
44
+ compiler. compile_program ( & ast, symbol_table)
42
45
}
43
46
Mode :: Eval => {
44
47
let statement = parser:: parse_statement ( source) . map_err ( CompileError :: Parse ) ?;
45
- compiler. compile_statement_eval ( & statement)
48
+ let symbol_table = statements_to_symbol_table ( & statement) ;
49
+ compiler. compile_statement_eval ( & statement, symbol_table)
46
50
}
47
51
Mode :: Single => {
48
52
let ast = parser:: parse_program ( source) . map_err ( CompileError :: Parse ) ?;
49
- compiler. compile_program_single ( & ast)
53
+ let symbol_table = make_symbol_table ( & ast) ;
54
+ compiler. compile_program_single ( & ast, symbol_table)
50
55
}
51
56
} ?;
52
57
@@ -73,6 +78,7 @@ impl Compiler {
73
78
fn new ( ) -> Self {
74
79
Compiler {
75
80
code_object_stack : Vec :: new ( ) ,
81
+ scope_stack : Vec :: new ( ) ,
76
82
nxt_label : 0 ,
77
83
source_path : None ,
78
84
current_source_location : ast:: Location :: default ( ) ,
@@ -96,11 +102,17 @@ impl Compiler {
96
102
}
97
103
98
104
fn pop_code_object ( & mut self ) -> CodeObject {
105
+ // self.scope_stack.pop().unwrap();
99
106
self . code_object_stack . pop ( ) . unwrap ( )
100
107
}
101
108
102
- fn compile_program ( & mut self , program : & ast:: Program ) -> Result < ( ) , CompileError > {
109
+ fn compile_program (
110
+ & mut self ,
111
+ program : & ast:: Program ,
112
+ symbol_scope : SymbolScope ,
113
+ ) -> Result < ( ) , CompileError > {
103
114
let size_before = self . code_object_stack . len ( ) ;
115
+ self . scope_stack . push ( symbol_scope) ;
104
116
self . compile_statements ( & program. statements ) ?;
105
117
assert ! ( self . code_object_stack. len( ) == size_before) ;
106
118
@@ -112,7 +124,12 @@ impl Compiler {
112
124
Ok ( ( ) )
113
125
}
114
126
115
- fn compile_program_single ( & mut self , program : & ast:: Program ) -> Result < ( ) , CompileError > {
127
+ fn compile_program_single (
128
+ & mut self ,
129
+ program : & ast:: Program ,
130
+ symbol_scope : SymbolScope ,
131
+ ) -> Result < ( ) , CompileError > {
132
+ self . scope_stack . push ( symbol_scope) ;
116
133
for statement in & program. statements {
117
134
if let ast:: Statement :: Expression { ref expression } = statement. node {
118
135
self . compile_expression ( expression) ?;
@@ -132,7 +149,9 @@ impl Compiler {
132
149
fn compile_statement_eval (
133
150
& mut self ,
134
151
statements : & [ ast:: LocatedStatement ] ,
152
+ symbol_table : SymbolScope ,
135
153
) -> Result < ( ) , CompileError > {
154
+ self . scope_stack . push ( symbol_table) ;
136
155
for statement in statements {
137
156
if let ast:: Statement :: Expression { ref expression } = statement. node {
138
157
self . compile_expression ( expression) ?;
@@ -154,6 +173,31 @@ impl Compiler {
154
173
Ok ( ( ) )
155
174
}
156
175
176
+ fn scope_for_name ( & self , name : & str ) -> bytecode:: NameScope {
177
+ let role = self . lookup_name ( name) ;
178
+ match role {
179
+ SymbolRole :: Global => bytecode:: NameScope :: Global ,
180
+ _ => bytecode:: NameScope :: Local ,
181
+ }
182
+ }
183
+
184
+ fn load_name ( & mut self , name : & str ) {
185
+ // TODO: if global, do something else!
186
+ let scope = self . scope_for_name ( name) ;
187
+ self . emit ( Instruction :: LoadName {
188
+ name : name. to_string ( ) ,
189
+ scope,
190
+ } ) ;
191
+ }
192
+
193
+ fn store_name ( & mut self , name : & str ) {
194
+ let scope = self . scope_for_name ( name) ;
195
+ self . emit ( Instruction :: StoreName {
196
+ name : name. to_string ( ) ,
197
+ scope,
198
+ } ) ;
199
+ }
200
+
157
201
fn compile_statement ( & mut self , statement : & ast:: LocatedStatement ) -> Result < ( ) , CompileError > {
158
202
trace ! ( "Compiling {:?}" , statement) ;
159
203
self . set_source_location ( & statement. location ) ;
@@ -177,15 +221,14 @@ impl Compiler {
177
221
name : module. clone ( ) ,
178
222
symbol : symbol. clone ( ) ,
179
223
} ) ;
180
- self . emit ( Instruction :: StoreName {
181
- name : match alias {
182
- Some ( alias) => alias. clone ( ) ,
183
- None => match symbol {
184
- Some ( symbol) => symbol. clone ( ) ,
185
- None => module. clone ( ) ,
186
- } ,
224
+ let name = match alias {
225
+ Some ( alias) => alias. clone ( ) ,
226
+ None => match symbol {
227
+ Some ( symbol) => symbol. clone ( ) ,
228
+ None => module. clone ( ) ,
187
229
} ,
188
- } ) ;
230
+ } ;
231
+ self . store_name ( & name) ;
189
232
}
190
233
}
191
234
}
@@ -196,11 +239,8 @@ impl Compiler {
196
239
// Pop result of stack, since we not use it:
197
240
self . emit ( Instruction :: Pop ) ;
198
241
}
199
- ast:: Statement :: Global { names } => {
200
- unimplemented ! ( "global {:?}" , names) ;
201
- }
202
- ast:: Statement :: Nonlocal { names } => {
203
- unimplemented ! ( "nonlocal {:?}" , names) ;
242
+ ast:: Statement :: Global { .. } | ast:: Statement :: Nonlocal { .. } => {
243
+ // Handled during symbol table construction.
204
244
}
205
245
ast:: Statement :: If { test, body, orelse } => {
206
246
let end_label = self . new_label ( ) ;
@@ -323,6 +363,7 @@ impl Compiler {
323
363
self . compile_test ( test, Some ( end_label) , None , EvalContext :: Statement ) ?;
324
364
self . emit ( Instruction :: LoadName {
325
365
name : String :: from ( "AssertionError" ) ,
366
+ scope : bytecode:: NameScope :: Local ,
326
367
} ) ;
327
368
match msg {
328
369
Some ( e) => {
@@ -466,6 +507,7 @@ impl Compiler {
466
507
line_number,
467
508
name. to_string ( ) ,
468
509
) ) ;
510
+ self . enter_scope ( ) ;
469
511
470
512
let mut flags = bytecode:: FunctionOpArg :: empty ( ) ;
471
513
if have_defaults {
@@ -529,6 +571,7 @@ impl Compiler {
529
571
// Check exception type:
530
572
self . emit ( Instruction :: LoadName {
531
573
name : String :: from ( "isinstance" ) ,
574
+ scope : bytecode:: NameScope :: Local ,
532
575
} ) ;
533
576
self . emit ( Instruction :: Rotate { amount : 2 } ) ;
534
577
self . compile_expression ( exc_type) ?;
@@ -543,9 +586,7 @@ impl Compiler {
543
586
544
587
// We have a match, store in name (except x as y)
545
588
if let Some ( alias) = & handler. name {
546
- self . emit ( Instruction :: StoreName {
547
- name : alias. clone ( ) ,
548
- } ) ;
589
+ self . store_name ( alias) ;
549
590
} else {
550
591
// Drop exception from top of stack:
551
592
self . emit ( Instruction :: Pop ) ;
@@ -630,6 +671,7 @@ impl Compiler {
630
671
} ) ;
631
672
self . emit ( Instruction :: ReturnValue ) ;
632
673
let code = self . pop_code_object ( ) ;
674
+ self . leave_scope ( ) ;
633
675
634
676
// Prepare type annotations:
635
677
let mut num_annotations = 0 ;
@@ -683,9 +725,7 @@ impl Compiler {
683
725
self . store_docstring ( doc_str) ;
684
726
self . apply_decorators ( decorator_list) ;
685
727
686
- self . emit ( Instruction :: StoreName {
687
- name : name. to_string ( ) ,
688
- } ) ;
728
+ self . store_name ( name) ;
689
729
690
730
self . current_qualified_path = old_qualified_path;
691
731
self . in_loop = was_in_loop;
@@ -720,14 +760,17 @@ impl Compiler {
720
760
line_number,
721
761
name. to_string ( ) ,
722
762
) ) ;
763
+ self . enter_scope ( ) ;
723
764
724
765
let ( new_body, doc_str) = get_doc ( body) ;
725
766
726
767
self . emit ( Instruction :: LoadName {
727
768
name : "__name__" . to_string ( ) ,
769
+ scope : bytecode:: NameScope :: Local ,
728
770
} ) ;
729
771
self . emit ( Instruction :: StoreName {
730
772
name : "__module__" . to_string ( ) ,
773
+ scope : bytecode:: NameScope :: Local ,
731
774
} ) ;
732
775
self . compile_statements ( new_body) ?;
733
776
self . emit ( Instruction :: LoadConst {
@@ -736,6 +779,7 @@ impl Compiler {
736
779
self . emit ( Instruction :: ReturnValue ) ;
737
780
738
781
let code = self . pop_code_object ( ) ;
782
+ self . leave_scope ( ) ;
739
783
740
784
self . emit ( Instruction :: LoadConst {
741
785
value : bytecode:: Constant :: Code {
@@ -794,9 +838,7 @@ impl Compiler {
794
838
self . store_docstring ( doc_str) ;
795
839
self . apply_decorators ( decorator_list) ;
796
840
797
- self . emit ( Instruction :: StoreName {
798
- name : name. to_string ( ) ,
799
- } ) ;
841
+ self . store_name ( name) ;
800
842
self . current_qualified_path = old_qualified_path;
801
843
self . in_loop = was_in_loop;
802
844
Ok ( ( ) )
@@ -942,9 +984,7 @@ impl Compiler {
942
984
fn compile_store ( & mut self , target : & ast:: Expression ) -> Result < ( ) , CompileError > {
943
985
match target {
944
986
ast:: Expression :: Identifier { name } => {
945
- self . emit ( Instruction :: StoreName {
946
- name : name. to_string ( ) ,
947
- } ) ;
987
+ self . store_name ( name) ;
948
988
}
949
989
ast:: Expression :: Subscript { a, b } => {
950
990
self . compile_expression ( a) ?;
@@ -1231,9 +1271,7 @@ impl Compiler {
1231
1271
} ) ;
1232
1272
}
1233
1273
ast:: Expression :: Identifier { name } => {
1234
- self . emit ( Instruction :: LoadName {
1235
- name : name. to_string ( ) ,
1236
- } ) ;
1274
+ self . load_name ( name) ;
1237
1275
}
1238
1276
ast:: Expression :: Lambda { args, body } => {
1239
1277
let name = "<lambda>" . to_string ( ) ;
@@ -1242,6 +1280,7 @@ impl Compiler {
1242
1280
self . compile_expression ( body) ?;
1243
1281
self . emit ( Instruction :: ReturnValue ) ;
1244
1282
let code = self . pop_code_object ( ) ;
1283
+ self . leave_scope ( ) ;
1245
1284
self . emit ( Instruction :: LoadConst {
1246
1285
value : bytecode:: Constant :: Code {
1247
1286
code : Box :: new ( code) ,
@@ -1449,6 +1488,7 @@ impl Compiler {
1449
1488
// Load iterator onto stack (passed as first argument):
1450
1489
self . emit ( Instruction :: LoadName {
1451
1490
name : String :: from ( ".0" ) ,
1491
+ scope : bytecode:: NameScope :: Local ,
1452
1492
} ) ;
1453
1493
} else {
1454
1494
// Evaluate iterated item:
@@ -1588,6 +1628,26 @@ impl Compiler {
1588
1628
Ok ( ( ) )
1589
1629
}
1590
1630
1631
+ // Scope helpers:
1632
+ fn enter_scope ( & mut self ) {
1633
+ // println!("Enter scope {:?}", self.scope_stack);
1634
+ // Enter first subscope!
1635
+ let scope = self . scope_stack . last_mut ( ) . unwrap ( ) . sub_scopes . remove ( 0 ) ;
1636
+ self . scope_stack . push ( scope) ;
1637
+ }
1638
+
1639
+ fn leave_scope ( & mut self ) {
1640
+ // println!("Leave scope {:?}", self.scope_stack);
1641
+ let scope = self . scope_stack . pop ( ) . unwrap ( ) ;
1642
+ assert ! ( scope. sub_scopes. is_empty( ) ) ;
1643
+ }
1644
+
1645
+ fn lookup_name ( & self , name : & str ) -> & SymbolRole {
1646
+ // println!("Looking up {:?}", name);
1647
+ let scope = self . scope_stack . last ( ) . unwrap ( ) ;
1648
+ scope. lookup ( name) . unwrap ( )
1649
+ }
1650
+
1591
1651
// Low level helper functions:
1592
1652
fn emit ( & mut self , instruction : Instruction ) {
1593
1653
let location = self . current_source_location . clone ( ) ;
@@ -1657,14 +1717,16 @@ mod tests {
1657
1717
use crate :: bytecode:: CodeObject ;
1658
1718
use crate :: bytecode:: Constant :: * ;
1659
1719
use crate :: bytecode:: Instruction :: * ;
1720
+ use crate :: symboltable:: make_symbol_table;
1660
1721
use rustpython_parser:: parser;
1661
1722
1662
1723
fn compile_exec ( source : & str ) -> CodeObject {
1663
1724
let mut compiler = Compiler :: new ( ) ;
1664
1725
compiler. source_path = Some ( "source_path" . to_string ( ) ) ;
1665
1726
compiler. push_new_code_object ( "<module>" . to_string ( ) ) ;
1666
1727
let ast = parser:: parse_program ( & source. to_string ( ) ) . unwrap ( ) ;
1667
- compiler. compile_program ( & ast) . unwrap ( ) ;
1728
+ let symbol_scope = make_symbol_table ( & ast) ;
1729
+ compiler. compile_program ( & ast, symbol_scope) . unwrap ( ) ;
1668
1730
compiler. pop_code_object ( )
1669
1731
}
1670
1732
0 commit comments