use rustc_hash::{FxHashMap, FxHashSet};
use crate::types::Type;
pub struct VariableMap {
vars: Vec<FxHashMap<String, (usize, Type)>>
}
impl Default for VariableMap {
fn default() -> Self {
Self::new()
}
}
impl VariableMap {
pub fn new() -> Self {
VariableMap { vars: vec!(FxHashMap::default()) }
}
pub fn add_context(&mut self) {
self.vars.push(FxHashMap::default());
}
pub fn remove_context(&mut self) {
self.vars.pop().unwrap();
}
pub fn define_var(&mut self, name: String, idx: usize, t: Type) {
self.vars.last_mut().unwrap().entry(name).or_insert((idx, t));
}
pub fn is_var_defined(&mut self, name: &String) -> bool {
for ctx in self.vars.iter().rev() {
if ctx.contains_key(name) {
return true;
}
}
false
}
pub fn is_var_defined_in_last_ctx(&mut self, name: &String) -> bool {
self.vars.last().unwrap().contains_key(name)
}
pub fn get_var(&mut self, name: &String) -> Option<&(usize, Type)> {
for ctx in self.vars.iter().rev() {
if let Some(v) = ctx.get(name) {
return Some(v);
}
}
None
}
pub fn for_each_last_ctx<T: FnMut(usize)>(&self, f: T) {
self.vars.last().unwrap().values().map(|(i, _)| *i).for_each(f);
}
pub fn var_names(&self) -> FxHashSet<&String> {
self.vars.iter().rev().flat_map(|i| i.keys()).collect()
}
}