135 lines
3.1 KiB
Rust
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()
|
|
}
|
|
}
|