use crate::ns::*; use by_address::ByAddress; use std::cell::RefCell; use std::collections::HashMap; use std::rc::Rc; /// Structure that assigns semantic symbols to AST nodes. pub struct AstToSymbol { compilation_units: RefCell>, AstToSymbol1>>, } struct AstToSymbol1 { expressions: HashMap>, Symbol>, directives: HashMap>, Symbol>, simple_variable_definitions: HashMap>, Symbol>, } impl AstToSymbol1 { fn new() -> Self { Self { expressions: HashMap::new(), directives: HashMap::new(), simple_variable_definitions: HashMap::new(), } } } impl AstToSymbol { pub fn new() -> Rc { Rc::new(Self { compilation_units: RefCell::new(HashMap::new()), }) } } pub trait AstToSymbolAccessor { fn get(&self, node: &Rc) -> Option; fn set(&self, node: &Rc, symbol: &Symbol); fn delete(&self, node: &Rc) -> bool; fn has(&self, node: &Rc) -> bool { self.get(node).is_some() } } impl AstToSymbolAccessor for AstToSymbol { fn get(&self, node: &Rc) -> Option { let compilation_units = self.compilation_units.borrow(); let m1 = compilation_units.get(&ByAddress(node.location().compilation_unit())); if let Some(m1) = m1 { m1.expressions.get(&AstAsKey(node.clone())).cloned() } else { None } } fn set(&self, node: &Rc, symbol: &Symbol) { let compilation_unit = node.location().compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit.clone())); if let Some(m1) = m1 { m1.expressions.insert(AstAsKey(node.clone()), symbol.clone()); } else { let mut m1 = AstToSymbol1::new(); m1.expressions.insert(AstAsKey(node.clone()), symbol.clone()); compilation_units.insert(ByAddress(compilation_unit), m1); } } fn delete(&self, node: &Rc) -> bool { let compilation_unit = node.location().compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit)); if let Some(m1) = m1 { m1.expressions.remove(&AstAsKey(node.clone())).is_some() } else { false } } } impl AstToSymbolAccessor for AstToSymbol { fn get(&self, node: &Rc) -> Option { let compilation_units = self.compilation_units.borrow(); let m1 = compilation_units.get(&ByAddress(node.location().compilation_unit())); if let Some(m1) = m1 { m1.directives.get(&AstAsKey(node.clone())).cloned() } else { None } } fn set(&self, node: &Rc, symbol: &Symbol) { let compilation_unit = node.location().compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit.clone())); if let Some(m1) = m1 { m1.directives.insert(AstAsKey(node.clone()), symbol.clone()); } else { let mut m1 = AstToSymbol1::new(); m1.directives.insert(AstAsKey(node.clone()), symbol.clone()); compilation_units.insert(ByAddress(compilation_unit), m1); } } fn delete(&self, node: &Rc) -> bool { let compilation_unit = node.location().compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit)); if let Some(m1) = m1 { m1.directives.remove(&AstAsKey(node.clone())).is_some() } else { false } } } impl AstToSymbolAccessor for AstToSymbol { fn get(&self, node: &Rc) -> Option { let compilation_units = self.compilation_units.borrow(); let m1 = compilation_units.get(&ByAddress(node.location.compilation_unit())); if let Some(m1) = m1 { m1.simple_variable_definitions.get(&AstAsKey(node.clone())).cloned() } else { None } } fn set(&self, node: &Rc, symbol: &Symbol) { let compilation_unit = node.location.compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit.clone())); if let Some(m1) = m1 { m1.simple_variable_definitions.insert(AstAsKey(node.clone()), symbol.clone()); } else { let mut m1 = AstToSymbol1::new(); m1.simple_variable_definitions.insert(AstAsKey(node.clone()), symbol.clone()); compilation_units.insert(ByAddress(compilation_unit), m1); } } fn delete(&self, node: &Rc) -> bool { let compilation_unit = node.location.compilation_unit(); let mut compilation_units = self.compilation_units.borrow_mut(); let m1 = compilation_units.get_mut(&ByAddress(compilation_unit)); if let Some(m1) = m1 { m1.simple_variable_definitions.remove(&AstAsKey(node.clone())).is_some() } else { false } } }