use crate::{ast::Stmt, prelude}; use std::collections::HashMap; #[derive(Debug)] pub struct SymbolTable { pub(crate) hashmap: HashMap, pub(crate) unit_types: HashMap, } impl SymbolTable { pub fn new() -> Self { SymbolTable { hashmap: HashMap::new(), unit_types: HashMap::new(), } } pub fn insert(&mut self, value: Stmt) -> &mut Self { match &value { Stmt::VarDecl(identifier, _) => { self.hashmap.insert(format!("var.{}", identifier), value); } Stmt::UnitDecl(identifier, to_unit, _) => { self.unit_types.insert(identifier.to_string(), ()); self.unit_types.insert(to_unit.to_string(), ()); self.hashmap .insert(format!("unit.{}.{}", identifier, to_unit), value); } Stmt::FnDecl(identifier, _, _) => { self.hashmap.insert(format!("fn.{}", identifier), value); } _ => panic!("Can only insert VarDecl, UnitDecl and FnDecl into symbol table."), } self } pub fn get_var(&self, key: &str) -> Option<&Stmt> { self.hashmap.get(&format!("var.{}", key)) } pub fn get_unit(&self, key: &str, to_unit: &str) -> Option<&Stmt> { self.hashmap.get(&format!("unit.{}.{}", key, to_unit)) } pub fn get_fn(&self, key: &str) -> Option<&Stmt> { self.hashmap.get(&format!("fn.{}", key)) } pub fn set(&mut self, value: Stmt) { let existing_item = match &value { Stmt::VarDecl(identifier, _) => self.hashmap.get_mut(&format!("var.{}", identifier)), Stmt::UnitDecl(identifier, to_unit, _) => self .hashmap .get_mut(&format!("unit.{}.{}", identifier, to_unit)), Stmt::FnDecl(identifier, _, _) => self.hashmap.get_mut(&format!("fn.{}", identifier)), _ => panic!("Can only set VarDecl, UnitDecl and FnDecl in symbol table."), }; if let Some(stmt) = existing_item { *stmt = value; } else { self.insert(value); } } pub fn contains_var(&self, identifier: &str) -> bool { prelude::CONSTANTS.contains_key(identifier) || self.hashmap.contains_key(&format!("var.{}", identifier)) } pub fn contains_unit(&self, identifier: &str) -> bool { self.unit_types.contains_key(identifier) } pub fn contains_fn(&self, identifier: &str) -> bool { prelude::is_prelude_func(identifier) || self.hashmap.contains_key(&format!("fn.{}", identifier)) } }