1
0
Files
developing-compilers/src/symbols/mod.rs
2024-11-10 10:34:38 +03:00

135 lines
3.1 KiB
Rust

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<Type>,
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<String, SymbolData>,
next_id: usize,
}
impl SymbolsTable {
pub fn new() -> Self {
Self {
symbols: HashMap::new(),
next_id: 0,
}
}
pub fn add(&mut self, symbol: impl Into<String>) -> 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<Symbol> {
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<Type> {
self.resolve(symbol).and_then(|data| data.ty)
}
pub fn temporary(&self, symbol: &Symbol) -> Option<bool> {
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<String, SymbolData>;
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()
}
}