mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-16 01:25:25 +00:00
Fix __class__ nonlocal resolution
This commit is contained in:
parent
16a896d513
commit
eedbf3aa6c
1 changed files with 18 additions and 26 deletions
|
@ -235,15 +235,7 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
|||
if scope_depth > 0 {
|
||||
// check if the name is already defined in any outer scope
|
||||
// therefore
|
||||
if scope_depth < 2
|
||||
|| !self
|
||||
.tables
|
||||
.iter()
|
||||
.skip(1) // omit the global scope as it is not non-local
|
||||
.rev() // revert the order for better performance
|
||||
.any(|t| t.0.contains_key(&symbol.name))
|
||||
// true when any of symbol tables contains the name -> then negate
|
||||
{
|
||||
if scope_depth < 2 || !self.found_in_outer_scope(symbol) {
|
||||
return Err(SymbolTableError {
|
||||
error: format!("no binding for nonlocal '{}' found", symbol.name),
|
||||
location: Default::default(),
|
||||
|
@ -274,27 +266,27 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn found_in_outer_scope(&self, symbol: &Symbol) -> bool {
|
||||
// Interesting stuff about the __class__ variable:
|
||||
// https://docs.python.org/3/reference/datamodel.html?highlight=__class__#creating-the-class-object
|
||||
symbol.name == "__class__"
|
||||
|| self.tables.iter().skip(1).any(|(symbols, typ)| {
|
||||
*typ != SymbolTableType::Class && symbols.contains_key(&symbol.name)
|
||||
})
|
||||
}
|
||||
|
||||
fn analyze_unknown_symbol(&self, symbol: &mut Symbol) {
|
||||
if symbol.is_assigned || symbol.is_parameter {
|
||||
symbol.scope = SymbolScope::Local;
|
||||
} else if self.found_in_outer_scope(symbol) {
|
||||
// Symbol is in some outer scope.
|
||||
symbol.is_free = true;
|
||||
} else if self.tables.is_empty() {
|
||||
// Don't make assumptions when we don't know.
|
||||
symbol.scope = SymbolScope::Unknown;
|
||||
} else {
|
||||
// Interesting stuff about the __class__ variable:
|
||||
// https://docs.python.org/3/reference/datamodel.html?highlight=__class__#creating-the-class-object
|
||||
let found_in_outer_scope = symbol.name == "__class__"
|
||||
|| self.tables.iter().skip(1).any(|(symbols, typ)| {
|
||||
*typ != SymbolTableType::Class && symbols.contains_key(&symbol.name)
|
||||
});
|
||||
|
||||
if found_in_outer_scope {
|
||||
// Symbol is in some outer scope.
|
||||
symbol.is_free = true;
|
||||
} else if self.tables.is_empty() {
|
||||
// Don't make assumptions when we don't know.
|
||||
symbol.scope = SymbolScope::Unknown;
|
||||
} else {
|
||||
// If there are scopes above we can assume global.
|
||||
symbol.scope = SymbolScope::Global;
|
||||
}
|
||||
// If there are scopes above we can assume global.
|
||||
symbol.scope = SymbolScope::Global;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue