use crate::value::Value;
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
pub struct EnvironmentPool {
pool: Vec<Environment>,
max_size: usize,
}
impl EnvironmentPool {
pub fn new() -> Self {
Self::with_capacity(50)
}
pub fn with_capacity(max_size: usize) -> Self {
EnvironmentPool {
pool: Vec::with_capacity(max_size.min(50)),
max_size,
}
}
pub fn acquire(&mut self) -> Environment {
self.pool.pop().unwrap_or_default()
}
pub fn release(&mut self, mut env: Environment) {
if self.pool.len() < self.max_size {
env.clear();
env.parent = None;
self.pool.push(env);
}
}
pub fn clear(&mut self) {
self.pool.clear();
}
}
impl Default for EnvironmentPool {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Environment {
store: HashMap<String, Value>,
parent: Option<Rc<RefCell<Environment>>>,
}
impl Environment {
pub fn new() -> Self {
Environment {
store: HashMap::with_capacity(16), parent: None,
}
}
pub fn with_parent(parent: Rc<RefCell<Environment>>) -> Self {
Environment {
store: HashMap::with_capacity(8), parent: Some(parent),
}
}
pub fn set(&mut self, name: String, value: Value) {
self.store.insert(name, value);
}
pub fn get(&self, name: &str) -> Option<Value> {
if let Some(value) = self.store.get(name) {
return Some(value.clone());
}
self.get_from_parent(name)
}
#[inline(never)]
fn get_from_parent(&self, name: &str) -> Option<Value> {
self.parent.as_ref()?.borrow().get(name)
}
pub fn has(&self, name: &str) -> bool {
self.store.contains_key(name) || self.parent.as_ref().is_some_and(|p| p.borrow().has(name))
}
pub fn update(&mut self, name: &str, value: Value) -> bool {
if self.store.contains_key(name) {
self.store.insert(name.to_string(), value);
return true;
}
if let Some(parent) = &self.parent {
return parent.borrow_mut().update(name, value);
}
false
}
pub fn keys(&self) -> Vec<String> {
self.store.keys().cloned().collect()
}
pub fn clear(&mut self) {
self.store.clear();
}
}
impl Default for Environment {
fn default() -> Self {
Self::new()
}
}