use std::{ collections::HashMap, sync::{Arc, RwLock, RwLockReadGuard}, }; use crate::{error::rw_lock_error::RwLockError, Type, Value}; #[derive(Clone)] pub enum ValueData { Value { inner: Value, runtime_uses: Arc>, }, ExpectedType { inner: Type, }, } pub struct Context { inner: Arc>>, } impl Context { pub fn new() -> Self { Self { inner: Arc::new(RwLock::new(HashMap::new())), } } pub fn inherit_from(other: &Context) -> Result { let mut new_variables = HashMap::new(); for (identifier, value_data) in other.variables()?.iter() { new_variables.insert(identifier.clone(), value_data.clone()); } Ok(Context { inner: Arc::new(RwLock::new(new_variables)), }) } pub fn variables(&self) -> Result>, RwLockError> { Ok(self.inner.read()?) } pub fn get_value(&self, key: &str) -> Result, RwLockError> { if let Some(value_data) = self.inner.read()?.get(key) { if let ValueData::Value { inner, .. } = value_data { Ok(Some(inner)) } else { Ok(None) } } else { Ok(None) } } pub fn get_type(&self, key: &str) -> Result, RwLockError> { if let Some(value_data) = self.inner.read()?.get(key) { match value_data { ValueData::Value { inner, .. } => Ok(Some(inner.r#type())), ValueData::ExpectedType { inner, .. } => Ok(Some(inner.clone())), } } else { Ok(None) } } pub fn set_value(&self, key: String, value: Value) -> Result<(), RwLockError> { self.inner.write()?.insert( key, ValueData::Value { inner: value, runtime_uses: Arc::new(RwLock::new(0)), }, ); Ok(()) } pub fn set_type(&self, key: String, r#type: Type) -> Result<(), RwLockError> { self.inner .write()? .insert(key, ValueData::ExpectedType { inner: r#type }); Ok(()) } }