use hashbrown::HashMap;
use alloc::rc::Rc;
pub type SymID = u32;
pub struct SymbolMap {
str_to_id: HashMap<Rc<String>, SymID>,
id_to_str: Vec<Rc<String>>,
}
macro_rules! generate_intrinsic_syms {
($($name:ident),*) => {
#[allow(non_camel_case_types)]
#[repr(u32)]
enum Intrinsics {
$($name,)*
}
$(
pub const $name: SymID = Intrinsics::$name as u32;
)*
impl SymbolMap {
pub fn is_intrinsic(sym: SymID) -> bool {
match sym {
$(
$name => true,
)*
_ => false,
}
}
pub fn insert_intrinsics(&mut self) {
let symbols = vec![
$(
stringify!($name).trim_end_matches("_SYM").to_ascii_lowercase(),
)*
];
for symbol in symbols {
self.insert(symbol.to_string());
}
}
}
};
}
generate_intrinsic_syms! {
INT_SYM,
FLOAT_SYM,
STR_SYM,
BOOL_SYM,
SYM_SYM,
NULL_SYM,
LIST_SYM,
MAP_SYM,
FN_SYM,
ARGS_SYM,
PATCH_SYM
}
pub const SELF_SYM: SymID = 11;
pub const ITER_SYM: SymID = 12;
pub const ITER_END_SYM: SymID = 13;
impl Default for SymbolMap {
fn default() -> Self {
Self::new()
}
}
impl SymbolMap {
pub fn new() -> Self {
let mut this = Self {
str_to_id: HashMap::new(),
id_to_str: Vec::new(),
};
this.insert_intrinsics();
this.insert("self".to_string());
this.insert("iter".to_string());
this.insert("iter_end".to_string());
this
}
pub fn get_id(&mut self, str: &str) -> SymID {
let str = str.to_string();
match self.str_to_id.get(&str) {
Some(id) => *id,
None => self.insert(str),
}
}
pub fn get_str(&mut self, id: SymID) -> &str {
&self.id_to_str[id as usize]
}
fn insert(&mut self, str: String) -> SymID {
let id = self.id_to_str.len() as u32;
let s = Rc::new(str);
self.id_to_str.push(s.clone());
self.str_to_id.insert(s.clone(), id);
id
}
}