use hashbrown::HashMap; use std::rc::Rc; use crate::ty::internal::{AttrSet, Value}; #[derive(Debug, Default, Clone)] pub struct LetEnv<'jit, 'vm> { map: Rc>>, last: Option>>, } #[derive(Debug, Default, Clone)] pub struct WithEnv<'jit, 'vm> { map: Rc>, last: Option>>, } impl<'jit, 'vm> LetEnv<'jit, 'vm> { pub fn new(map: Rc>>) -> Self { Self { map, last: None } } pub fn lookup(&self, symbol: usize) -> Option> { if let Some(val) = self.map.get(&symbol).cloned() { return Some(val); } self.last.as_ref().map(|env| env.lookup(symbol)).flatten() } pub fn enter_let(self, new: impl Iterator)>) -> Self { let map = Rc::new(new.collect()); let last = Some(self.into()); LetEnv { last, map } } pub fn enter_with(self, new: Rc>) -> Self { let map = new .as_inner() .iter() .map(|(&k, v)| { ( k, if let Value::Builtins(weak) = v { Value::AttrSet(weak.upgrade().unwrap()) } else { v.clone() }, ) }) .collect::>() .into(); let last = Some(self.into()); LetEnv { last, map } } pub fn leave(self) -> Self { self.last.unwrap().as_ref().clone() } } impl<'jit, 'vm> WithEnv<'jit, 'vm> { pub fn lookup(&self, symbol: usize) -> Option> { if let Some(val) = self.map.select(symbol) { return Some(val); } self.last.as_ref().map(|env| env.lookup(symbol)).flatten() } pub fn enter_with(self, new: Rc>) -> Self { let map = Rc::new(new .as_inner() .iter() .map(|(&k, v)| { ( k, if let Value::Builtins(weak) = v { Value::AttrSet(weak.upgrade().unwrap()) } else { v.clone() }, ) }) .collect::>() .into()); let last = Some(self.into()); WithEnv { last, map } } pub fn leave(self) -> Self { self.last.unwrap().as_ref().clone() } }