Don't clone SymbolTables when analyzing

This commit is contained in:
coolreader18 2019-09-07 18:11:47 -05:00
parent d7f99dc7b1
commit 5919a1e1ba

View file

@ -61,7 +61,7 @@ impl SymbolTable {
} }
} }
#[derive(Clone, PartialEq)] #[derive(Clone, Copy, PartialEq)]
pub enum SymbolTableType { pub enum SymbolTableType {
Module, Module,
Class, Class,
@ -179,24 +179,24 @@ fn analyze_symbol_table(symbol_table: &mut SymbolTable) -> SymbolTableResult {
/// build symbol table structure. It will mark variables /// build symbol table structure. It will mark variables
/// as local variables for example. /// as local variables for example.
#[derive(Default)] #[derive(Default)]
struct SymbolTableAnalyzer { struct SymbolTableAnalyzer<'a> {
tables: Vec<SymbolTable>, tables: Vec<(&'a mut IndexMap<String, Symbol>, SymbolTableType)>,
} }
impl SymbolTableAnalyzer { impl<'a> SymbolTableAnalyzer<'a> {
fn analyze_symbol_table(&mut self, symbol_table: &mut SymbolTable) -> SymbolTableResult { fn analyze_symbol_table(&mut self, symbol_table: &'a mut SymbolTable) -> SymbolTableResult {
// Store a copy to determine the parent. let symbols = &mut symbol_table.symbols;
// TODO: this should be improved to resolve this clone action. let sub_tables = &mut symbol_table.sub_tables;
self.tables.push(symbol_table.clone());
self.tables.push((symbols, symbol_table.typ));
// Analyze sub scopes: // Analyze sub scopes:
for sub_table in &mut symbol_table.sub_tables { for sub_table in sub_tables {
self.analyze_symbol_table(sub_table)?; self.analyze_symbol_table(sub_table)?;
} }
self.tables.pop(); let (symbols, _) = self.tables.pop().unwrap();
// Analyze symbols: // Analyze symbols:
for symbol in symbol_table.symbols.values_mut() { for symbol in symbols.values_mut() {
self.analyze_symbol(symbol)?; self.analyze_symbol(symbol)?;
} }
@ -207,11 +207,11 @@ impl SymbolTableAnalyzer {
match symbol.scope { match symbol.scope {
SymbolScope::Nonlocal => { SymbolScope::Nonlocal => {
// check if name is defined in parent table! // check if name is defined in parent table!
let parent_symbol_table: Option<&SymbolTable> = self.tables.last(); let parent_symbol_table = self.tables.last();
// symbol.table.borrow().parent.clone(); // symbol.table.borrow().parent.clone();
if let Some(table) = parent_symbol_table { if let Some((symbols, _)) = parent_symbol_table {
if !table.symbols.contains_key(&symbol.name) { if !symbols.contains_key(&symbol.name) {
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(),
@ -242,8 +242,8 @@ impl SymbolTableAnalyzer {
// Interesting stuff about the __class__ variable: // Interesting stuff about the __class__ variable:
// https://docs.python.org/3/reference/datamodel.html?highlight=__class__#creating-the-class-object // 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 = symbol.name == "__class__"
|| self.tables.iter().skip(1).any(|t| { || self.tables.iter().skip(1).any(|(symbols, typ)| {
t.typ != SymbolTableType::Class && t.symbols.contains_key(&symbol.name) *typ != SymbolTableType::Class && symbols.contains_key(&symbol.name)
}); });
if found_in_outer_scope { if found_in_outer_scope {