@@ -129,31 +129,7 @@ pub struct Symbol {
129
129
pub name : String ,
130
130
// pub table: SymbolTableRef,
131
131
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 ,
157
133
}
158
134
159
135
impl Symbol {
@@ -162,15 +138,7 @@ impl Symbol {
162
138
name : name. to_owned ( ) ,
163
139
// table,
164
140
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 ( ) ,
174
142
}
175
143
}
176
144
@@ -186,7 +154,7 @@ impl Symbol {
186
154
}
187
155
188
156
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 ( )
190
158
}
191
159
}
192
160
@@ -328,7 +296,11 @@ impl SymbolTableAnalyzer {
328
296
st_typ : SymbolTableType ,
329
297
sub_tables : & mut [ SymbolTable ] ,
330
298
) -> 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
+ {
332
304
// propagate symbol to next higher level that can hold it,
333
305
// i.e., function or module. Comprehension is skipped and
334
306
// Class is not allowed and detected as error.
@@ -416,10 +388,10 @@ impl SymbolTableAnalyzer {
416
388
for ( table, typ) in self . tables . iter_mut ( ) . rev ( ) . take ( decl_depth) {
417
389
if let SymbolTableType :: Class = typ {
418
390
if let Some ( free_class) = table. get_mut ( name) {
419
- free_class. is_free_class = true ;
391
+ free_class. flags . insert ( SymbolFlags :: FREE_CLASS )
420
392
} else {
421
393
let mut symbol = Symbol :: new ( name) ;
422
- symbol. is_free_class = true ;
394
+ symbol. flags . insert ( SymbolFlags :: FREE_CLASS ) ;
423
395
symbol. scope = SymbolScope :: Free ;
424
396
table. insert ( name. to_owned ( ) , symbol) ;
425
397
}
@@ -443,7 +415,7 @@ impl SymbolTableAnalyzer {
443
415
) -> Option < SymbolScope > {
444
416
sub_tables. iter ( ) . find_map ( |st| {
445
417
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 ) {
447
419
if st_typ == SymbolTableType :: Class && name != "__class__" {
448
420
None
449
421
} else {
@@ -474,7 +446,7 @@ impl SymbolTableAnalyzer {
474
446
let table_type = last. 1 ;
475
447
476
448
// 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 ) {
478
450
return Err ( SymbolTableError {
479
451
error : format ! (
480
452
"assignment expression cannot rebind comprehension iteration variable {}" ,
@@ -501,7 +473,7 @@ impl SymbolTableAnalyzer {
501
473
if let Some ( parent_symbol) = symbols. get_mut ( & symbol. name ) {
502
474
if let SymbolScope :: Unknown = parent_symbol. scope {
503
475
// 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 ) ;
505
477
}
506
478
507
479
symbol. scope = if parent_symbol. is_global ( ) {
@@ -520,7 +492,7 @@ impl SymbolTableAnalyzer {
520
492
match symbols. get_mut ( & symbol. name ) {
521
493
Some ( parent_symbol) => {
522
494
// check if assignee is an iterator in top scope
523
- if parent_symbol. is_iter {
495
+ if parent_symbol. flags . contains ( SymbolFlags :: ITER ) {
524
496
return Err ( SymbolTableError {
525
497
error : format ! ( "assignment expression cannot rebind comprehension iteration variable {}" , symbol. name) ,
526
498
// TODO: accurate location info, somehow
@@ -529,7 +501,7 @@ impl SymbolTableAnalyzer {
529
501
}
530
502
531
503
// 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
533
505
}
534
506
None => {
535
507
// extend the scope of the inner symbol
@@ -1176,28 +1148,29 @@ impl SymbolTableBuilder {
1176
1148
1177
1149
// Some checks for the symbol that present on this scope level:
1178
1150
let symbol = if let Some ( symbol) = table. symbols . get_mut ( name. as_ref ( ) ) {
1151
+ let flags = & symbol. flags ;
1179
1152
// Role already set..
1180
1153
match role {
1181
1154
SymbolUsage :: Global if !symbol. is_global ( ) => {
1182
- if symbol . is_parameter {
1155
+ if flags . contains ( SymbolFlags :: PARAMETER ) {
1183
1156
return Err ( SymbolTableError {
1184
1157
error : format ! ( "name '{}' is parameter and global" , name) ,
1185
1158
location,
1186
1159
} ) ;
1187
1160
}
1188
- if symbol . is_referenced {
1161
+ if flags . contains ( SymbolFlags :: REFERENCED ) {
1189
1162
return Err ( SymbolTableError {
1190
1163
error : format ! ( "name '{}' is used prior to global declaration" , name) ,
1191
1164
location,
1192
1165
} ) ;
1193
1166
}
1194
- if symbol . is_annotated {
1167
+ if flags . contains ( SymbolFlags :: ANNOTATED ) {
1195
1168
return Err ( SymbolTableError {
1196
1169
error : format ! ( "annotated name '{}' can't be global" , name) ,
1197
1170
location,
1198
1171
} ) ;
1199
1172
}
1200
- if symbol . is_assigned {
1173
+ if flags . contains ( SymbolFlags :: ASSIGNED ) {
1201
1174
return Err ( SymbolTableError {
1202
1175
error : format ! (
1203
1176
"name '{}' is assigned to before global declaration" ,
@@ -1208,25 +1181,25 @@ impl SymbolTableBuilder {
1208
1181
}
1209
1182
}
1210
1183
SymbolUsage :: Nonlocal => {
1211
- if symbol . is_parameter {
1184
+ if flags . contains ( SymbolFlags :: PARAMETER ) {
1212
1185
return Err ( SymbolTableError {
1213
1186
error : format ! ( "name '{}' is parameter and nonlocal" , name) ,
1214
1187
location,
1215
1188
} ) ;
1216
1189
}
1217
- if symbol . is_referenced {
1190
+ if flags . contains ( SymbolFlags :: REFERENCED ) {
1218
1191
return Err ( SymbolTableError {
1219
1192
error : format ! ( "name '{}' is used prior to nonlocal declaration" , name) ,
1220
1193
location,
1221
1194
} ) ;
1222
1195
}
1223
- if symbol . is_annotated {
1196
+ if flags . contains ( SymbolFlags :: ANNOTATED ) {
1224
1197
return Err ( SymbolTableError {
1225
1198
error : format ! ( "annotated name '{}' can't be nonlocal" , name) ,
1226
1199
location,
1227
1200
} ) ;
1228
1201
}
1229
- if symbol . is_assigned {
1202
+ if flags . contains ( SymbolFlags :: ASSIGNED ) {
1230
1203
return Err ( SymbolTableError {
1231
1204
error : format ! (
1232
1205
"name '{}' is assigned to before nonlocal declaration" ,
@@ -1261,47 +1234,44 @@ impl SymbolTableBuilder {
1261
1234
} ;
1262
1235
1263
1236
// Set proper scope and flags on symbol:
1237
+ let flags = & mut symbol. flags ;
1264
1238
match role {
1265
1239
SymbolUsage :: Nonlocal => {
1266
1240
symbol. scope = SymbolScope :: Free ;
1267
- symbol . is_nonlocal = true ;
1241
+ flags . insert ( SymbolFlags :: NONLOCAL ) ;
1268
1242
}
1269
1243
SymbolUsage :: Imported => {
1270
- symbol. is_assigned = true ;
1271
- symbol. is_imported = true ;
1244
+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: IMPORTED ) ;
1272
1245
}
1273
1246
SymbolUsage :: Parameter => {
1274
- symbol . is_parameter = true ;
1247
+ flags . insert ( SymbolFlags :: PARAMETER ) ;
1275
1248
}
1276
1249
SymbolUsage :: AnnotationParameter => {
1277
- symbol. is_parameter = true ;
1278
- symbol. is_annotated = true ;
1250
+ flags. insert ( SymbolFlags :: PARAMETER | SymbolFlags :: ANNOTATED ) ;
1279
1251
}
1280
1252
SymbolUsage :: AnnotationAssigned => {
1281
- symbol. is_assigned = true ;
1282
- symbol. is_annotated = true ;
1253
+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: ANNOTATED ) ;
1283
1254
}
1284
1255
SymbolUsage :: Assigned => {
1285
- symbol . is_assigned = true ;
1256
+ flags . insert ( SymbolFlags :: ASSIGNED ) ;
1286
1257
}
1287
1258
SymbolUsage :: AssignedNamedExprInCompr => {
1288
- symbol. is_assigned = true ;
1289
- symbol. is_assign_namedexpr_in_comprehension = true ;
1259
+ flags. insert ( SymbolFlags :: ASSIGNED | SymbolFlags :: ASSIGNED_IN_COMPREHENSION ) ;
1290
1260
}
1291
1261
SymbolUsage :: Global => {
1292
1262
symbol. scope = SymbolScope :: GlobalExplicit ;
1293
1263
}
1294
1264
SymbolUsage :: Used => {
1295
- symbol . is_referenced = true ;
1265
+ flags . insert ( SymbolFlags :: REFERENCED ) ;
1296
1266
}
1297
1267
SymbolUsage :: Iter => {
1298
- symbol . is_iter = true ;
1268
+ flags . insert ( SymbolFlags :: ITER ) ;
1299
1269
}
1300
1270
}
1301
1271
1302
1272
// and even more checking
1303
1273
// 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 )
1305
1275
/*&& symbol.is_assign_namedexpr_in_comprehension*/
1306
1276
{
1307
1277
return Err ( SymbolTableError {
0 commit comments