@@ -61,7 +61,7 @@ impl SymbolTable {
61
61
}
62
62
}
63
63
64
- #[ derive( Clone ) ]
64
+ #[ derive( Clone , Copy , PartialEq ) ]
65
65
pub enum SymbolTableType {
66
66
Module ,
67
67
Class ,
@@ -179,24 +179,24 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
179
179
/// build symbol table structure. It will mark variables
180
180
/// as local variables for example.
181
181
#[ derive( Default ) ]
182
- struct SymbolTableAnalyzer {
183
- tables : Vec < SymbolTable > ,
182
+ struct SymbolTableAnalyzer < ' a > {
183
+ tables : Vec < ( & ' a mut IndexMap < String , Symbol > , SymbolTableType ) > ,
184
184
}
185
185
186
- impl SymbolTableAnalyzer {
187
- fn analyze_symbol_table ( & mut self , symbol_table : & mut SymbolTable ) -> SymbolTableResult {
188
- // Store a copy to determine the parent.
189
- // TODO: this should be improved to resolve this clone action.
190
- self . tables . push ( symbol_table. clone ( ) ) ;
186
+ impl < ' a > SymbolTableAnalyzer < ' a > {
187
+ fn analyze_symbol_table ( & mut self , symbol_table : & ' a mut SymbolTable ) -> SymbolTableResult {
188
+ let symbols = & mut symbol_table. symbols ;
189
+ let sub_tables = & mut symbol_table. sub_tables ;
191
190
191
+ self . tables . push ( ( symbols, symbol_table. typ ) ) ;
192
192
// Analyze sub scopes:
193
- for sub_table in & mut symbol_table . sub_tables {
193
+ for sub_table in sub_tables {
194
194
self . analyze_symbol_table ( sub_table) ?;
195
195
}
196
- self . tables . pop ( ) ;
196
+ let ( symbols , _ ) = self . tables . pop ( ) . unwrap ( ) ;
197
197
198
198
// Analyze symbols:
199
- for symbol in symbol_table . symbols . values_mut ( ) {
199
+ for symbol in symbols. values_mut ( ) {
200
200
self . analyze_symbol ( symbol) ?;
201
201
}
202
202
@@ -207,11 +207,11 @@ impl SymbolTableAnalyzer {
207
207
match symbol. scope {
208
208
SymbolScope :: Nonlocal => {
209
209
// check if name is defined in parent table!
210
- let parent_symbol_table: Option < & SymbolTable > = self . tables . last ( ) ;
210
+ let parent_symbol_table = self . tables . last ( ) ;
211
211
// symbol.table.borrow().parent.clone();
212
212
213
- if let Some ( table ) = parent_symbol_table {
214
- if !table . symbols . contains_key ( & symbol. name ) {
213
+ if let Some ( ( symbols , _ ) ) = parent_symbol_table {
214
+ if !symbols. contains_key ( & symbol. name ) {
215
215
return Err ( SymbolTableError {
216
216
error : format ! ( "no binding for nonlocal '{}' found" , symbol. name) ,
217
217
location : Default :: default ( ) ,
@@ -241,12 +241,10 @@ impl SymbolTableAnalyzer {
241
241
} else {
242
242
// Interesting stuff about the __class__ variable:
243
243
// https://docs.python.org/3/reference/datamodel.html?highlight=__class__#creating-the-class-object
244
- let found_in_outer_scope = ( symbol. name == "__class__" )
245
- || self
246
- . tables
247
- . iter ( )
248
- . skip ( 1 )
249
- . any ( |t| t. symbols . contains_key ( & symbol. name ) ) ;
244
+ let found_in_outer_scope = symbol. name == "__class__"
245
+ || self . tables . iter ( ) . skip ( 1 ) . any ( |( symbols, typ) | {
246
+ * typ != SymbolTableType :: Class && symbols. contains_key ( & symbol. name )
247
+ } ) ;
250
248
251
249
if found_in_outer_scope {
252
250
// Symbol is in some outer scope.
@@ -387,7 +385,6 @@ impl SymbolTableBuilder {
387
385
keywords,
388
386
decorator_list,
389
387
} => {
390
- self . register_name ( name, SymbolUsage :: Assigned ) ?;
391
388
self . enter_scope ( name, SymbolTableType :: Class , statement. location . row ( ) ) ;
392
389
self . scan_statements ( body) ?;
393
390
self . leave_scope ( ) ;
@@ -396,6 +393,7 @@ impl SymbolTableBuilder {
396
393
self . scan_expression ( & keyword. value , & ExpressionContext :: Load ) ?;
397
394
}
398
395
self . scan_expressions ( decorator_list, & ExpressionContext :: Load ) ?;
396
+ self . register_name ( name, SymbolUsage :: Assigned ) ?;
399
397
}
400
398
Expression { expression } => {
401
399
self . scan_expression ( expression, & ExpressionContext :: Load ) ?
0 commit comments