From 39c095d12c6d6f17d3575126452a4f85c89a38e9 Mon Sep 17 00:00:00 2001 From: Windel Bouwman Date: Sun, 18 Aug 2019 12:12:27 +0200 Subject: [PATCH] Add Free enum variant to the symbol scope to be able to distuingish between true local and free variables. --- src/compile.rs | 12 ++++++------ src/symboltable.rs | 18 +++++++++--------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/compile.rs b/src/compile.rs index 23b46f1..2a95190 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -282,8 +282,8 @@ impl Compiler { match symbol.scope { SymbolScope::Global => bytecode::NameScope::Global, SymbolScope::Nonlocal => bytecode::NameScope::NonLocal, - SymbolScope::Unknown => bytecode::NameScope::Local, - SymbolScope::Local => bytecode::NameScope::Local, + SymbolScope::Unknown => bytecode::NameScope::Free, + SymbolScope::Local => bytecode::NameScope::Free, } } @@ -500,7 +500,7 @@ impl Compiler { self.compile_jump_if(test, true, end_label)?; self.emit(Instruction::LoadName { name: String::from("AssertionError"), - scope: bytecode::NameScope::Local, + scope: bytecode::NameScope::Global, }); match msg { Some(e) => { @@ -736,7 +736,7 @@ impl Compiler { // Check exception type: self.emit(Instruction::LoadName { name: String::from("isinstance"), - scope: bytecode::NameScope::Local, + scope: bytecode::NameScope::Global, }); self.emit(Instruction::Rotate { amount: 2 }); self.compile_expression(exc_type)?; @@ -931,11 +931,11 @@ impl Compiler { self.emit(Instruction::LoadName { name: "__name__".to_string(), - scope: bytecode::NameScope::Local, + scope: bytecode::NameScope::Free, }); self.emit(Instruction::StoreName { name: "__module__".to_string(), - scope: bytecode::NameScope::Local, + scope: bytecode::NameScope::Free, }); self.compile_statements(new_body)?; self.emit(Instruction::LoadConst { diff --git a/src/symboltable.rs b/src/symboltable.rs index 46174c3..d99ae82 100644 --- a/src/symboltable.rs +++ b/src/symboltable.rs @@ -213,21 +213,21 @@ impl SymbolTableAnalyzer { if symbol.is_assigned || symbol.is_parameter { symbol.scope = SymbolScope::Local; } else { - // TODO: comment this out and make it work properly: - /* - */ - let found_in_outer_scope = self - .tables - .iter() - .skip(1) - .any(|t| t.symbols.contains_key(&symbol.name)); + // 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(|t| t.symbols.contains_key(&symbol.name)); if found_in_outer_scope { // Symbol is in some outer scope. symbol.is_free = true; } else { // Well, it must be a global then :) - // symbol.scope = SymbolScope::Global; + symbol.scope = SymbolScope::Global; } } }