use crate::name_analysis::symbol::{ FunctionSymbol, ModuleSymbol, ParameterSymbol, Symbol, SymbolInner, TypeSymbol, UseStatementSymbol, VariableSymbol, }; use crate::name_analysis::symbol_table::SymbolInsertError::SymbolAlreadyDefined; use crate::name_analysis::symbol_table::SymbolLookupError::NoDefinition; use std::cell::RefCell; use std::collections::HashMap; use std::fmt::Display; use std::rc::Rc; /* Scope */ #[derive(Debug)] struct Scope { parent: Option, use_statement_symbols: HashMap>>, module_symbols: HashMap>, type_symbols: HashMap>, function_symbols: HashMap>>, parameter_symbols: HashMap>, variable_symbols: HashMap>, debug_name: String, } impl Scope { pub fn new(parent: Option, debug_name: String) -> Scope { Scope { parent, use_statement_symbols: HashMap::new(), module_symbols: HashMap::new(), type_symbols: HashMap::new(), function_symbols: HashMap::new(), parameter_symbols: HashMap::new(), variable_symbols: HashMap::new(), debug_name, } } fn get_any_symbol(&self, name: &str) -> Option { self.variable_symbols .get(name) .map(|s| Symbol::Variable(s.clone())) .or_else(|| { self.parameter_symbols .get(name) .map(|s| Symbol::Parameter(s.clone())) }) .or_else(|| { self.function_symbols .get(name) .map(|s| Symbol::Function(s.clone())) }) .or_else(|| { self.type_symbols .get(name) .map(|ts| Symbol::Type(ts.clone())) }) .or_else(|| { self.module_symbols .get(name) .map(|ms| Symbol::Module(ms.clone())) }) .or_else(|| { self.use_statement_symbols .get(name) .map(|us| Symbol::UseStatement(us.clone())) }) } fn get_module_symbol_by_declared_name(&self, name: &str) -> Option> { for module_symbol in self.module_symbols.values() { if module_symbol.declared_name() == name { return Some(module_symbol.clone()); } } None } fn get_type_symbol_by_declared_name(&self, declared_name: &str) -> Option> { if let Some(type_symbol) = self.type_symbols.get(declared_name) { Some(type_symbol.clone()) } else { for use_statement_symbol in self.use_statement_symbols.values() { let borrowed = use_statement_symbol.borrow(); if borrowed.declared_name() == declared_name { if let Some(referenced_symbol) = borrowed.referenced_symbol() { match *referenced_symbol { Symbol::Type(type_symbol) => return Some(type_symbol.clone()), _ => continue, } } } } None } } fn get_type_symbol_by_fqn(&self, fqn: &str) -> Option> { self.type_symbols.values().find(|s| s.fqn() == fqn).cloned() } fn get_usable_symbol_by_fqn(&self, fqn: &str) -> Option { for function_symbol in self.function_symbols.values() { if function_symbol.borrow().fqn() == fqn { return Some(Symbol::Function(function_symbol.clone())); } } for type_symbol in self.type_symbols.values() { if type_symbol.fqn() == fqn { return Some(Symbol::Type(type_symbol.clone())); } } None } fn get_usable_symbol_by_declared_name(&self, declared_name: &str) -> Option { for function_symbol in self.function_symbols.values() { if function_symbol.borrow().declared_name() == declared_name { return Some(Symbol::Function(function_symbol.clone())); } } for type_symbol in self.type_symbols.values() { if type_symbol.declared_name() == declared_name { return Some(Symbol::Type(type_symbol.clone())); } } None } fn get_value_symbol_by_declared_name(&self, declared_name: &str) -> Option { for variable_symbol in self.variable_symbols.values() { if variable_symbol.declared_name() == declared_name { return Some(Symbol::Variable(variable_symbol.clone())); } } for parameter_symbol in self.parameter_symbols.values() { if parameter_symbol.declared_name() == declared_name { return Some(Symbol::Parameter(parameter_symbol.clone())); } } None } fn get_expressible_by_declared_name(&self, declared_name: &str) -> Option { self.variable_symbols .get(declared_name) .map(|s| Symbol::Variable(s.clone())) .or_else(|| { self.parameter_symbols .get(declared_name) .map(|p| Symbol::Parameter(p.clone())) }) .or_else(|| { self.function_symbols .get(declared_name) .map(|f| Symbol::Function(f.clone())) }) .or_else(|| { self.type_symbols .get(declared_name) .map(|t| Symbol::Type(t.clone())) }) .or_else(|| { self.use_statement_symbols .get(declared_name) .map(|us| Symbol::UseStatement(us.clone())) }) } fn get_expressible_by_fqn(&self, fqn: &str) -> Option { self.function_symbols .values() .find(|fs| fs.borrow().fqn() == fqn) .map(|f| Symbol::Function(f.clone())) .or_else(|| { self.type_symbols .values() .find(|ts| ts.fqn() == fqn) .map(|ts| Symbol::Type(ts.clone())) }) } } /* Symbol table */ #[derive(Debug)] pub enum SymbolInsertError { SymbolAlreadyDefined(Symbol), } #[derive(Debug)] pub enum SymbolLookupError { NoDefinition, } #[derive(Debug)] pub struct SymbolTable { scopes: Vec, current_scope_id: usize, } /// Contains a vec of scopes, like a flattened tree impl SymbolTable { pub fn new() -> Self { let mut t = SymbolTable { scopes: vec![Scope::new(None, String::from("GlobalScope"))], current_scope_id: 0, }; t } pub fn current_scope_id(&self) -> usize { self.current_scope_id } pub fn scopes(&self) -> &Vec { &self.scopes } pub fn push_scope(&mut self, debug_name: &str) { let id = self.scopes.len(); self.scopes.push(Scope::new( Some(self.current_scope_id), debug_name.to_string(), )); self.current_scope_id = id; } pub fn pop_scope(&mut self) { if let Some(parent_id) = self.scopes[self.current_scope_id].parent { self.current_scope_id = parent_id; } } pub fn insert_use_statement_symbol( &mut self, use_statement_symbol: UseStatementSymbol, ) -> Result>, SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_usable_symbol_by_declared_name(use_statement_symbol.declared_name()) { Err(SymbolAlreadyDefined(defined_symbol)) } else { let declared_name = use_statement_symbol.declared_name().to_string(); let to_insert = Rc::new(RefCell::new(use_statement_symbol)); let to_return = to_insert.clone(); current_scope .use_statement_symbols .insert(declared_name, to_insert); Ok(to_return) } } pub fn insert_module_symbol( &mut self, module_symbol: ModuleSymbol, ) -> Result<(), SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_module_symbol_by_declared_name(module_symbol.declared_name()) { Err(SymbolAlreadyDefined(Symbol::Module(defined_symbol.clone()))) } else { current_scope.module_symbols.insert( module_symbol.declared_name().to_string(), Rc::new(module_symbol), ); Ok(()) } } pub fn insert_type_symbol(&mut self, type_symbol: TypeSymbol) -> Result<(), SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_usable_symbol_by_declared_name(type_symbol.declared_name()) { Err(SymbolAlreadyDefined(defined_symbol)) } else { current_scope.type_symbols.insert( type_symbol.declared_name().to_string(), Rc::new(type_symbol), ); Ok(()) } } pub fn insert_function_symbol( &mut self, function_symbol: FunctionSymbol, ) -> Result>, SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_usable_symbol_by_declared_name(function_symbol.declared_name()) { Err(SymbolAlreadyDefined(defined_symbol)) } else { let declared_name = function_symbol.declared_name().to_string(); let to_insert = Rc::new(RefCell::new(function_symbol)); let to_return = to_insert.clone(); current_scope .function_symbols .insert(declared_name, to_insert); Ok(to_return) } } pub fn insert_parameter_symbol( &mut self, parameter_symbol: ParameterSymbol, ) -> Result, SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_value_symbol_by_declared_name(parameter_symbol.declared_name()) { Err(SymbolAlreadyDefined(defined_symbol)) } else { let to_insert = Rc::new(parameter_symbol); let to_return = to_insert.clone(); current_scope .parameter_symbols .insert(to_insert.declared_name().to_string(), to_insert); Ok(to_return) } } pub fn insert_variable_symbol( &mut self, variable_symbol: VariableSymbol, ) -> Result<(), SymbolInsertError> { let current_scope = self.scopes.get_mut(self.current_scope_id).unwrap(); if let Some(defined_symbol) = current_scope.get_value_symbol_by_declared_name(variable_symbol.declared_name()) { Err(SymbolAlreadyDefined(defined_symbol)) } else { current_scope.variable_symbols.insert( variable_symbol.declared_name().to_string(), Rc::new(variable_symbol), ); Ok(()) } } #[deprecated(note = "Use more specific lookup methods.")] pub fn lookup(&self, name: &str, scope_id: usize) -> Result { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { if let Some(symbol) = scope.get_any_symbol(name) { return Ok(symbol); } scope_opt = if let Some(parent_id) = scope.parent { Some(&self.scopes[parent_id]) } else { None }; } Err(NoDefinition) } pub fn lookup_type_by_declared_name( &self, declared_name: &str, scope_id: usize, ) -> Result, SymbolLookupError> { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { if let Some(symbol) = scope.get_type_symbol_by_declared_name(declared_name) { return Ok(symbol); } scope_opt = if let Some(parent_id) = scope.parent { Some(&self.scopes[parent_id]) } else { None } } Err(NoDefinition) } pub fn lookup_type_by_fqn( &self, fqn: &str, scope_id: usize, ) -> Result, SymbolLookupError> { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { if let Some(symbol) = scope.get_type_symbol_by_fqn(fqn) { return Ok(symbol); } scope_opt = if let Some(parent_id) = scope.parent { Some(&self.scopes[parent_id]) } else { None } } Err(NoDefinition) } pub fn lookup_usable_by_fqn( &self, fully_qualified_name: &str, scope_id: usize, ) -> Result { for scope in &self.scopes { if let Some(symbol) = scope.get_usable_symbol_by_fqn(fully_qualified_name) { return Ok(symbol); } } Err(NoDefinition) } pub fn lookup_expressible_by_declared_name( &self, declared_name: &str, scope_id: usize, ) -> Result { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { if let Some(symbol) = scope.get_expressible_by_declared_name(declared_name) { return Ok(symbol); } scope_opt = if let Some(parent_id) = scope.parent { Some(&self.scopes[parent_id]) } else { None } } Err(NoDefinition) } pub fn lookup_expressible_by_fqn( &self, fqn: &str, scope_id: usize, ) -> Result { let mut scope_opt = Some(&self.scopes[scope_id]); while let Some(scope) = scope_opt { if let Some(symbol) = scope.get_expressible_by_fqn(fqn) { return Ok(symbol); } scope_opt = if let Some(parent_id) = scope.parent { Some(&self.scopes[parent_id]) } else { None } } Err(NoDefinition) } } impl Display for SymbolTable { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { writeln!(f, "SymbolTable(current_scope = {})", self.current_scope_id)?; for (i, scope) in self.scopes.iter().enumerate() { writeln!(f, "----Scope {} {}----", i, scope.debug_name)?; for symbol in scope.use_statement_symbols.values() { writeln!(f, "{:#?}", symbol.borrow())?; } for symbol in scope.module_symbols.values() { writeln!(f, "{:#?}", symbol)?; } for symbol in scope.type_symbols.values() { writeln!(f, "{:#?}", symbol)?; } for symbol in scope.function_symbols.values() { writeln!(f, "{:#?}", symbol.borrow())?; } for symbol in scope.parameter_symbols.values() { writeln!(f, "{:#?}", symbol)?; } for symbol in scope.variable_symbols.values() { writeln!(f, "{:#?}", symbol)?; } } Ok(()) } }