Add Free enum variant to the symbol scope to be able to distuingish between true local and free variables.

This commit is contained in:
Windel Bouwman 2019-08-18 12:12:27 +02:00
parent 9b1771b483
commit 39c095d12c
2 changed files with 15 additions and 15 deletions

View file

@ -282,8 +282,8 @@ impl<O: OutputStream> Compiler<O> {
match symbol.scope { match symbol.scope {
SymbolScope::Global => bytecode::NameScope::Global, SymbolScope::Global => bytecode::NameScope::Global,
SymbolScope::Nonlocal => bytecode::NameScope::NonLocal, SymbolScope::Nonlocal => bytecode::NameScope::NonLocal,
SymbolScope::Unknown => bytecode::NameScope::Local, SymbolScope::Unknown => bytecode::NameScope::Free,
SymbolScope::Local => bytecode::NameScope::Local, SymbolScope::Local => bytecode::NameScope::Free,
} }
} }
@ -500,7 +500,7 @@ impl<O: OutputStream> Compiler<O> {
self.compile_jump_if(test, true, end_label)?; self.compile_jump_if(test, true, end_label)?;
self.emit(Instruction::LoadName { self.emit(Instruction::LoadName {
name: String::from("AssertionError"), name: String::from("AssertionError"),
scope: bytecode::NameScope::Local, scope: bytecode::NameScope::Global,
}); });
match msg { match msg {
Some(e) => { Some(e) => {
@ -736,7 +736,7 @@ impl<O: OutputStream> Compiler<O> {
// Check exception type: // Check exception type:
self.emit(Instruction::LoadName { self.emit(Instruction::LoadName {
name: String::from("isinstance"), name: String::from("isinstance"),
scope: bytecode::NameScope::Local, scope: bytecode::NameScope::Global,
}); });
self.emit(Instruction::Rotate { amount: 2 }); self.emit(Instruction::Rotate { amount: 2 });
self.compile_expression(exc_type)?; self.compile_expression(exc_type)?;
@ -931,11 +931,11 @@ impl<O: OutputStream> Compiler<O> {
self.emit(Instruction::LoadName { self.emit(Instruction::LoadName {
name: "__name__".to_string(), name: "__name__".to_string(),
scope: bytecode::NameScope::Local, scope: bytecode::NameScope::Free,
}); });
self.emit(Instruction::StoreName { self.emit(Instruction::StoreName {
name: "__module__".to_string(), name: "__module__".to_string(),
scope: bytecode::NameScope::Local, scope: bytecode::NameScope::Free,
}); });
self.compile_statements(new_body)?; self.compile_statements(new_body)?;
self.emit(Instruction::LoadConst { self.emit(Instruction::LoadConst {

View file

@ -213,21 +213,21 @@ impl SymbolTableAnalyzer {
if symbol.is_assigned || symbol.is_parameter { if symbol.is_assigned || symbol.is_parameter {
symbol.scope = SymbolScope::Local; symbol.scope = SymbolScope::Local;
} else { } else {
// TODO: comment this out and make it work properly: // 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__")
let found_in_outer_scope = self || self
.tables .tables
.iter() .iter()
.skip(1) .skip(1)
.any(|t| t.symbols.contains_key(&symbol.name)); .any(|t| t.symbols.contains_key(&symbol.name));
if found_in_outer_scope { 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 { } else {
// Well, it must be a global then :) // Well, it must be a global then :)
// symbol.scope = SymbolScope::Global; symbol.scope = SymbolScope::Global;
} }
} }
} }