use crate::memory::object_map::Memory;
use crate::memory::vm_data::VMData;
use crate::RuntimeResult;
use std::collections::HashMap;
#[derive(Debug, Default)]
pub struct VarMap<'run> {
var_map: HashMap<Key<'run>, VMData>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Key<'run> {
pub scope: usize,
pub key: &'run str,
}
impl<'run> VarMap<'run> {
pub fn new() -> Self {
VarMap {
var_map: HashMap::new()
}
}
pub fn insert(&mut self, key: Key<'run>, value: VMData, mem: &mut Memory) -> RuntimeResult<VMData> {
let old_data = self.var_map.insert(key, value);
match old_data {
Some(old_data) => {
match old_data.tag {
VMData::TAG_STR | VMData::TAG_LIST | VMData::TAG_OBJECT => {
mem.rc_dec(old_data.as_object())?;
}
_ => {}
}
}
None => {}
}
Ok(old_data.unwrap_or_else(|| VMData::new_unit()))
}
pub fn get(&self, key: &Key<'run>) -> Option<&VMData> {
self.var_map.get(key)
}
pub fn last(&self) -> &HashMap<Key<'_>, VMData> {
&self.var_map
}
pub fn clean_scope(&mut self, scope: usize, mem: &mut Memory) -> RuntimeResult<()> {
let mut to_remove = Vec::new();
self.var_map.retain(|key, value| {
if key.scope == scope {
match value.tag {
VMData::TAG_STR | VMData::TAG_LIST | VMData::TAG_OBJECT => {
to_remove.push(value.as_object());
}
_ => {}
}
false
} else {
true
}
});
for obj in to_remove {
mem.rc_dec(obj)?;
}
Ok(())
}
}