use crate::diagnostic::Diagnostic; use crate::source_range::SourceRange; use crate::symbol::ExpressibleSymbol; use crate::symbol_table::SymbolTable; use crate::type_info::TypeInfo; pub struct Identifier { name: String, scope_id: Option, expressible_symbol: Option, source_range: SourceRange, } impl Identifier { pub fn new(name: &str, source_range: SourceRange) -> Self { Self { name: name.into(), scope_id: None, expressible_symbol: None, source_range, } } pub fn name(&self) -> &str { &self.name } pub fn gather_declared_names(&mut self, symbol_table: &SymbolTable) -> Vec { self.scope_id = Some(symbol_table.current_scope_id()); vec![] } pub fn check_name_usages(&mut self, symbol_table: &SymbolTable) -> Vec { let maybe_expressible_symbol = symbol_table.find_expressible_symbol(self.scope_id.unwrap(), &self.name); match maybe_expressible_symbol { None => { vec![Diagnostic::new( &format!("Unable to resolve symbol {}", self.name), self.source_range.start(), self.source_range.end(), )] } Some(expressible_symbol) => { self.expressible_symbol = Some(expressible_symbol); vec![] } } } pub fn type_info(&self) -> TypeInfo { match self.expressible_symbol.as_ref().unwrap() { ExpressibleSymbol::Function(function_symbol) => { TypeInfo::Function(function_symbol.clone()) } ExpressibleSymbol::Parameter(parameter_symbol) => { parameter_symbol.borrow().type_info().clone() } ExpressibleSymbol::Variable(variable_symbol) => { variable_symbol.borrow().type_info().clone() } } } pub fn expressible_symbol(&self) -> &ExpressibleSymbol { self.expressible_symbol.as_ref().unwrap() } pub fn source_range(&self) -> &SourceRange { &self.source_range } }