use std::{collections::HashMap, sync::{Arc, RwLock}}; use crate::value::Value; #[derive(Debug, Clone)] pub struct Env<'env> { values: Arc>>, parent: Option<&'env Env<'env>>, } impl Env<'_> { pub fn new() -> Self { Env { values: Default::default(), parent: None, } } pub fn get(&self, name: &str) -> Option { if let Some(v) = self.values.read().unwrap().get(name) { Some(v.clone()) } else if let Some(parent) = &self.parent { parent.get(name) } else { None } } pub fn set(&self, name: &str, value: impl Into) { let value = value.into(); if !self.set_recursive(name, &value) { self.values.write().unwrap().insert(name.to_string(), value); } } fn set_recursive(&self, name: &str, value: &Value) -> bool { if let Some(v) = self.values.write().unwrap().get_mut(name) { *v = value.clone(); true } else if let Some(parent) = self.parent { parent.set_recursive(name, value) } else { false } } pub fn update(&self, name: &str, f: impl FnOnce(&Value) -> Value) { if let Some(v) = self.values.write().unwrap().get_mut(name) { *v = f(v); } else if let Some(parent) = self.parent { parent.update(name, f); } } } impl<'env> Env<'env> { pub fn new_with_parent(parent: &'env Env<'env>) -> Self { Env { values: Default::default(), parent: Some(parent), } } }