Skip to content

Commit a5ef816

Browse files
committed
Replace bool variable with SymbolFlags
1 parent dbf27a9 commit a5ef816

File tree

3 files changed

+49
-75
lines changed

3 files changed

+49
-75
lines changed

compiler/codegen/src/compile.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use crate::{
99
error::{CodegenError, CodegenErrorType},
1010
ir,
11-
symboltable::{self, SymbolScope, SymbolTable},
11+
symboltable::{self, SymbolFlags, SymbolScope, SymbolTable},
1212
IndexSet,
1313
};
1414
use itertools::Itertools;
@@ -272,7 +272,9 @@ impl Compiler {
272272
let freevar_cache = table
273273
.symbols
274274
.iter()
275-
.filter(|(_, s)| s.scope == SymbolScope::Free || s.is_free_class)
275+
.filter(|(_, s)| {
276+
s.scope == SymbolScope::Free || s.flags.contains(SymbolFlags::FREE_CLASS)
277+
})
276278
.map(|(var, _)| var.clone())
277279
.collect();
278280

@@ -1209,7 +1211,7 @@ impl Compiler {
12091211
let vars = match symbol.scope {
12101212
SymbolScope::Free => &parent_code.freevar_cache,
12111213
SymbolScope::Cell => &parent_code.cellvar_cache,
1212-
_ if symbol.is_free_class => &parent_code.freevar_cache,
1214+
_ if symbol.flags.contains(SymbolFlags::FREE_CLASS) => &parent_code.freevar_cache,
12131215
x => unreachable!(
12141216
"var {} in a {:?} should be free or cell but it's {:?}",
12151217
var, table.typ, x

compiler/codegen/src/symboltable.rs

Lines changed: 35 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

159135
impl 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 {

vm/src/stdlib/symtable.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ mod symtable {
55
use crate::{
66
builtins::PyStrRef, compiler, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
77
};
8-
use rustpython_codegen::symboltable::{Symbol, SymbolScope, SymbolTable, SymbolTableType};
8+
use rustpython_codegen::symboltable::{
9+
Symbol, SymbolFlags, SymbolScope, SymbolTable, SymbolTableType,
10+
};
911
use std::fmt;
1012

1113
#[pyfunction]
@@ -179,7 +181,7 @@ mod symtable {
179181

180182
#[pymethod]
181183
fn is_imported(&self) -> bool {
182-
self.symbol.is_imported
184+
self.symbol.flags.contains(SymbolFlags::IMPORTED)
183185
}
184186

185187
#[pymethod]
@@ -190,22 +192,22 @@ mod symtable {
190192

191193
#[pymethod]
192194
fn is_nonlocal(&self) -> bool {
193-
self.symbol.is_nonlocal
195+
self.symbol.flags.contains(SymbolFlags::NONLOCAL)
194196
}
195197

196198
#[pymethod]
197199
fn is_referenced(&self) -> bool {
198-
self.symbol.is_referenced
200+
self.symbol.flags.contains(SymbolFlags::REFERENCED)
199201
}
200202

201203
#[pymethod]
202204
fn is_assigned(&self) -> bool {
203-
self.symbol.is_assigned
205+
self.symbol.flags.contains(SymbolFlags::ASSIGNED)
204206
}
205207

206208
#[pymethod]
207209
fn is_parameter(&self) -> bool {
208-
self.symbol.is_parameter
210+
self.symbol.flags.contains(SymbolFlags::PARAMETER)
209211
}
210212

211213
#[pymethod]
@@ -220,7 +222,7 @@ mod symtable {
220222

221223
#[pymethod]
222224
fn is_annotated(&self) -> bool {
223-
self.symbol.is_annotated
225+
self.symbol.flags.contains(SymbolFlags::ANNOTATED)
224226
}
225227

226228
#[pymethod]

0 commit comments

Comments
 (0)