mirror of
https://github.com/RustPython/Parser.git
synced 2025-07-19 11:05:45 +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 {
|
if scope_depth > 0 {
|
||||||
// check if the name is already defined in any outer scope
|
// check if the name is already defined in any outer scope
|
||||||
// therefore
|
// therefore
|
||||||
if scope_depth < 2
|
if scope_depth < 2 || !self.found_in_outer_scope(symbol) {
|
||||||
|| !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
|
|
||||||
{
|
|
||||||
return Err(SymbolTableError {
|
return Err(SymbolTableError {
|
||||||
error: format!("no binding for nonlocal '{}' found", symbol.name),
|
error: format!("no binding for nonlocal '{}' found", symbol.name),
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
|
@ -274,18 +266,19 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
||||||
Ok(())
|
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) {
|
fn analyze_unknown_symbol(&self, symbol: &mut Symbol) {
|
||||||
if symbol.is_assigned || symbol.is_parameter {
|
if symbol.is_assigned || symbol.is_parameter {
|
||||||
symbol.scope = SymbolScope::Local;
|
symbol.scope = SymbolScope::Local;
|
||||||
} else {
|
} else if self.found_in_outer_scope(symbol) {
|
||||||
// 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 in some outer scope.
|
||||||
symbol.is_free = true;
|
symbol.is_free = true;
|
||||||
} else if self.tables.is_empty() {
|
} else if self.tables.is_empty() {
|
||||||
|
@ -296,7 +289,6 @@ impl<'a> SymbolTableAnalyzer<'a> {
|
||||||
symbol.scope = SymbolScope::Global;
|
symbol.scope = SymbolScope::Global;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Implements the symbol analysis and scope extension for names
|
// Implements the symbol analysis and scope extension for names
|
||||||
// assigned by a named expression in a comprehension. See:
|
// assigned by a named expression in a comprehension. See:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue