pub mod builtin; use std::{ collections::{hash_map, HashMap}, fmt::Display, }; use crate::ast::typed::Type; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Symbol(usize); #[derive(Debug)] pub struct SymbolData { pub id: Symbol, pub name: String, pub ty: Option, pub temporary: bool, } impl Display for SymbolData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut builder = f.debug_struct("symbol"); builder.field("id", &self.id.0); if let Some(ty) = self.ty { builder.field("type", &ty); } if self.temporary { builder.field("temporary", &self.temporary); } builder.finish() } } impl Display for Symbol { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } #[derive(Debug)] pub struct SymbolsTable { symbols: HashMap, next_id: usize, } impl SymbolsTable { pub fn new() -> Self { Self { symbols: HashMap::new(), next_id: 0, } } pub fn add(&mut self, symbol: impl Into) -> Symbol { let symbol = symbol.into(); if let hash_map::Entry::Vacant(e) = self.symbols.entry(symbol.clone()) { e.insert(SymbolData { id: Symbol(self.next_id), name: symbol, ty: None, temporary: false, }); self.next_id += 1; return Symbol(self.next_id - 1); } self.get(&symbol).unwrap() } pub fn get(&self, symbol: &str) -> Option { self.symbols.get(symbol).map(|data| data.id) } pub fn resolve(&self, symbol: &Symbol) -> Option<&SymbolData> { self.symbols.iter().find_map( |(_name, data)| { if &data.id == symbol { Some(data) } else { None } }, ) } pub fn resolve_mut(&mut self, symbol: &Symbol) -> Option<&mut SymbolData> { self.symbols.iter_mut().find_map( |(_name, data)| { if &data.id == symbol { Some(data) } else { None } }, ) } pub fn type_of(&self, symbol: &Symbol) -> Option { self.resolve(symbol).and_then(|data| data.ty) } pub fn temporary(&self, symbol: &Symbol) -> Option { self.resolve(symbol).map(|data| data.temporary) } } impl Default for SymbolsTable { fn default() -> Self { Self::new() } } impl IntoIterator for SymbolsTable { type Item = (String, SymbolData); type IntoIter = hash_map::IntoIter; fn into_iter(self) -> Self::IntoIter { self.symbols.into_iter() } } impl<'a> IntoIterator for &'a SymbolsTable { type Item = (&'a String, &'a SymbolData); type IntoIter = hash_map::Iter<'a, String, SymbolData>; fn into_iter(self) -> Self::IntoIter { self.symbols.iter() } }