@@ -129,31 +129,7 @@ pub struct Symbol {
129129 pub name : String ,
130130 // pub table: SymbolTableRef,
131131 pub scope : SymbolScope ,
132- // TODO: Use bitflags replace
133- pub is_referenced : bool ,
134- pub is_assigned : bool ,
135- pub is_parameter : bool ,
136- pub is_annotated : bool ,
137- pub is_imported : bool ,
138- pub is_nonlocal : bool ,
139-
140- // indicates if the symbol gets a value assigned by a named expression in a comprehension
141- // this is required to correct the scope in the analysis.
142- pub is_assign_namedexpr_in_comprehension : bool ,
143-
144- // indicates that the symbol is used a bound iterator variable. We distinguish this case
145- // from normal assignment to detect unallowed re-assignment to iterator variables.
146- pub is_iter : bool ,
147-
148- /// indicates that the symbol is a free variable in a class method from the scope that the
149- /// class is defined in, e.g.:
150- /// ```python
151- /// def foo(x):
152- /// class A:
153- /// def method(self):
154- /// return x // is_free_class
155- /// ```
156- pub is_free_class : bool ,
132+ pub flags : SymbolFlags ,
157133}
158134
159135impl Symbol {
@@ -162,15 +138,7 @@ impl Symbol {
162138 name : name. to_owned ( ) ,
163139 // table,
164140 scope : SymbolScope :: Unknown ,
165- is_referenced : false ,
166- is_assigned : false ,
167- is_parameter : false ,
168- is_annotated : false ,
169- is_imported : false ,
170- is_nonlocal : false ,
171- is_assign_namedexpr_in_comprehension : false ,
172- is_iter : false ,
173- is_free_class : false ,
141+ flags : SymbolFlags :: empty ( ) ,
174142 }
175143 }
176144
@@ -186,7 +154,7 @@ impl Symbol {
186154 }
187155
188156 pub fn is_bound ( & self ) -> bool {
189- self . is_assigned || self . is_parameter || self . is_imported || self . is_iter
157+ ! ( self . flags & SymbolFlags :: BOUND ) . is_empty ( )
190158 }
191159}
192160
@@ -328,7 +296,11 @@ impl SymbolTableAnalyzer {
328296 st_typ : SymbolTableType ,
329297 sub_tables : & mut [ SymbolTable ] ,
330298 ) -> SymbolTableResult {
331- if symbol. is_assign_namedexpr_in_comprehension && st_typ == SymbolTableType :: Comprehension {
299+ if symbol
300+ . flags
301+ . contains ( SymbolFlags :: ASSIGNED_IN_COMPREHENSION )
302+ && st_typ == SymbolTableType :: Comprehension
303+ {
332304 // propagate symbol to next higher level that can hold it,
333305 // i.e., function or module. Comprehension is skipped and
334306 // Class is not allowed and detected as error.
@@ -416,10 +388,10 @@ impl SymbolTableAnalyzer {
416388 for ( table, typ) in self . tables . iter_mut ( ) . rev ( ) . take ( decl_depth) {
417389 if let SymbolTableType :: Class = typ {
418390 if let Some ( free_class) = table. get_mut ( name) {
419- free_class. is_free_class = true ;
391+ free_class. flags . insert ( SymbolFlags :: FREE_CLASS )
420392 } else {
421393 let mut symbol = Symbol :: new ( name) ;
422- symbol. is_free_class = true ;
394+ symbol. flags . insert ( SymbolFlags :: FREE_CLASS ) ;
423395 symbol. scope = SymbolScope :: Free ;
424396 table. insert ( name. to_owned ( ) , symbol) ;
425397 }
@@ -443,7 +415,7 @@ impl SymbolTableAnalyzer {
443415 ) -> Option < SymbolScope > {
444416 sub_tables. iter ( ) . find_map ( |st| {
445417 st. symbols . get ( name) . and_then ( |sym| {
446- if sym. scope == SymbolScope :: Free || sym. is_free_class {
418+ if sym. scope == SymbolScope :: Free || sym. flags . contains ( SymbolFlags :: FREE_CLASS ) {
447419 if st_typ == SymbolTableType :: Class && name != "__class__" {
448420 None
449421 } else {
@@ -474,7 +446,7 @@ impl SymbolTableAnalyzer {
474446 let table_type = last. 1 ;
475447
476448 // it is not allowed to use an iterator variable as assignee in a named expression
477- if symbol. is_iter {
449+ if symbol. flags . contains ( SymbolFlags :: ITER ) {
478450 return Err ( SymbolTableError {
479451 error : format ! (
480452 "assignment expression cannot rebind comprehension iteration variable {}" ,
@@ -501,7 +473,7 @@ impl SymbolTableAnalyzer {
501473 if let Some ( parent_symbol) = symbols. get_mut ( & symbol. name ) {
502474 if let SymbolScope :: Unknown = parent_symbol. scope {
503475 // this information is new, as the assignment is done in inner scope
504- parent_symbol. is_assigned = true ;
476+ parent_symbol. flags . insert ( SymbolFlags :: ASSIGNED ) ;
505477 }
506478
507479 symbol. scope = if parent_symbol. is_global ( ) {
@@ -520,7 +492,7 @@ impl SymbolTableAnalyzer {
520492 match symbols. get_mut ( & symbol. name ) {
521493 Some ( parent_symbol) => {
522494 // check if assignee is an iterator in top scope
523- if parent_symbol. is_iter {
495+ if parent_symbol. flags . contains ( SymbolFlags :: ITER ) {
524496 return Err ( SymbolTableError {
525497 error : format ! ( "assignment expression cannot rebind comprehension iteration variable {}" , symbol. name) ,
526498 // TODO: accurate location info, somehow
@@ -529,7 +501,7 @@ impl SymbolTableAnalyzer {
529501 }
530502
531503 // we synthesize the assignment to the symbol from inner scope
532- parent_symbol. is_assigned = true ; // more checks are required
504+ parent_symbol. flags . insert ( SymbolFlags :: ASSIGNED ) ; // more checks are required
533505 }
534506 None => {
535507 // extend the scope of the inner symbol
@@ -1176,28 +1148,29 @@ impl SymbolTableBuilder {
11761148
11771149 // Some checks for the symbol that present on this scope level:
11781150 let symbol = if let Some ( symbol) = table. symbols . get_mut ( name. as_ref ( ) ) {
1151+ let flags = & symbol. flags ;
11791152 // Role already set..
11801153 match role {
11811154 SymbolUsage :: Global if !symbol. is_global ( ) => {
1182- if symbol . is_parameter {
1155+ if flags . contains ( SymbolFlags :: PARAMETER ) {
11831156 return Err ( SymbolTableError {
11841157 error : format ! ( "name '{}' is parameter and global" , name) ,
11851158 location,
11861159 } ) ;
11871160 }
1188- if symbol . is_referenced {
1161+ if flags . contains ( SymbolFlags :: REFERENCED ) {
11891162 return Err ( SymbolTableError {
11901163 error : format ! ( "name '{}' is used prior to global declaration" , name) ,
11911164 location,
11921165 } ) ;
11931166 }
1194- if symbol . is_annotated {
1167+ if flags . contains ( SymbolFlags :: ANNOTATED ) {
11951168 return Err ( SymbolTableError {
11961169 error : format ! ( "annotated name '{}' can't be global" , name) ,
11971170 location,
11981171 } ) ;
11991172 }
1200- if symbol . is_assigned {
1173+ if flags . contains ( SymbolFlags :: ASSIGNED ) {
12011174 return Err ( SymbolTableError {
12021175 error : format ! (
12031176 "name '{}' is assigned to before global declaration" ,
@@ -1208,25 +1181,25 @@ impl SymbolTableBuilder {
12081181 }
12091182 }
12101183 SymbolUsage :: Nonlocal => {
1211- if symbol . is_parameter {
1184+ if flags . contains ( SymbolFlags :: PARAMETER ) {
12121185 return Err ( SymbolTableError {
12131186 error : format ! ( "name '{}' is parameter and nonlocal" , name) ,
12141187 location,
12151188 } ) ;
12161189 }
1217- if symbol . is_referenced {
1190+ if flags . contains ( SymbolFlags :: REFERENCED ) {
12181191 return Err ( SymbolTableError {
12191192 error : format ! ( "name '{}' is used prior to nonlocal declaration" , name) ,
12201193 location,
12211194 } ) ;
12221195 }
1223- if symbol . is_annotated {
1196+ if flags . contains ( SymbolFlags :: ANNOTATED ) {
12241197 return Err ( SymbolTableError {
12251198 error : format ! ( "annotated name '{}' can't be nonlocal" , name) ,
12261199 location,
12271200 } ) ;
12281201 }
1229- if symbol . is_assigned {
1202+ if flags . contains ( SymbolFlags :: ASSIGNED ) {
12301203 return Err ( SymbolTableError {
12311204 error : format ! (
12321205 "name '{}' is assigned to before nonlocal declaration" ,
@@ -1261,47 +1234,44 @@ impl SymbolTableBuilder {
12611234 } ;
12621235
12631236 // Set proper scope and flags on symbol:
1237+ let flags = & mut symbol. flags ;
12641238 match role {
12651239 SymbolUsage :: Nonlocal => {
12661240 symbol. scope = SymbolScope :: Free ;
1267- symbol . is_nonlocal = true ;
1241+ flags . insert ( SymbolFlags :: NONLOCAL ) ;
12681242 }
12691243 SymbolUsage :: Imported => {
1270- symbol. is_assigned = true ;
1271- symbol. is_imported = true ;
1244+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: IMPORTED ) ;
12721245 }
12731246 SymbolUsage :: Parameter => {
1274- symbol . is_parameter = true ;
1247+ flags . insert ( SymbolFlags :: PARAMETER ) ;
12751248 }
12761249 SymbolUsage :: AnnotationParameter => {
1277- symbol. is_parameter = true ;
1278- symbol. is_annotated = true ;
1250+ flags. insert ( SymbolFlags :: PARAMETER | SymbolFlags :: ANNOTATED ) ;
12791251 }
12801252 SymbolUsage :: AnnotationAssigned => {
1281- symbol. is_assigned = true ;
1282- symbol. is_annotated = true ;
1253+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: ANNOTATED ) ;
12831254 }
12841255 SymbolUsage :: Assigned => {
1285- symbol . is_assigned = true ;
1256+ flags . insert ( SymbolFlags :: ASSIGNED ) ;
12861257 }
12871258 SymbolUsage :: AssignedNamedExprInCompr => {
1288- symbol. is_assigned = true ;
1289- symbol. is_assign_namedexpr_in_comprehension = true ;
1259+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: ASSIGNED_IN_COMPREHENSION ) ;
12901260 }
12911261 SymbolUsage :: Global => {
12921262 symbol. scope = SymbolScope :: GlobalExplicit ;
12931263 }
12941264 SymbolUsage :: Used => {
1295- symbol . is_referenced = true ;
1265+ flags . insert ( SymbolFlags :: REFERENCED ) ;
12961266 }
12971267 SymbolUsage :: Iter => {
1298- symbol . is_iter = true ;
1268+ flags . insert ( SymbolFlags :: ITER ) ;
12991269 }
13001270 }
13011271
13021272 // and even more checking
13031273 // it is not allowed to assign to iterator variables (by named expressions)
1304- if symbol . is_iter && symbol . is_assigned
1274+ if flags . contains ( SymbolFlags :: ITER | SymbolFlags :: ASSIGNED )
13051275 /*&& symbol.is_assign_namedexpr_in_comprehension*/
13061276 {
13071277 return Err ( SymbolTableError {
0 commit comments