2024-02-25 18:49:26 +00:00
|
|
|
use std::{
|
|
|
|
collections::BTreeMap,
|
|
|
|
sync::{Arc, RwLock},
|
|
|
|
};
|
|
|
|
|
2024-03-06 23:15:25 +00:00
|
|
|
use crate::{
|
|
|
|
abstract_tree::{Identifier, Type},
|
|
|
|
error::RwLockPoisonError,
|
2024-03-11 18:49:44 +00:00
|
|
|
value::{BuiltInFunction, ValueInner},
|
2024-03-06 23:15:25 +00:00
|
|
|
Value,
|
|
|
|
};
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
pub struct Context {
|
2024-03-12 01:57:27 +00:00
|
|
|
inner: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct UsageData(Arc<RwLock<UsageDataInner>>);
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct UsageDataInner {
|
|
|
|
pub allowances: usize,
|
|
|
|
pub uses: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for UsageData {
|
|
|
|
fn default() -> Self {
|
|
|
|
UsageData(Arc::new(RwLock::new(UsageDataInner {
|
|
|
|
allowances: 0,
|
|
|
|
uses: 0,
|
|
|
|
})))
|
|
|
|
}
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum ValueData {
|
|
|
|
Type(Type),
|
|
|
|
Value(Value),
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
inner: Arc::new(RwLock::new(BTreeMap::new())),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-12 01:57:27 +00:00
|
|
|
pub fn with_data(data: BTreeMap<Identifier, (ValueData, UsageData)>) -> Self {
|
2024-02-25 18:49:26 +00:00
|
|
|
Self {
|
2024-03-06 23:15:25 +00:00
|
|
|
inner: Arc::new(RwLock::new(data)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-11 18:51:02 +00:00
|
|
|
pub fn inherit_types_from(other: &Context) -> Result<Self, RwLockPoisonError> {
|
2024-03-10 18:48:53 +00:00
|
|
|
let mut new_data = BTreeMap::new();
|
|
|
|
|
2024-03-12 01:57:27 +00:00
|
|
|
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
|
2024-03-11 18:49:44 +00:00
|
|
|
if let ValueData::Type(r#type) = value_data {
|
|
|
|
if let Type::Function { .. } = r#type {
|
2024-03-12 01:57:27 +00:00
|
|
|
new_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
|
2024-03-11 18:49:44 +00:00
|
|
|
}
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Self::with_data(new_data))
|
|
|
|
}
|
|
|
|
|
2024-03-11 18:51:02 +00:00
|
|
|
pub fn inherit_data_from(other: &Context) -> Result<Self, RwLockPoisonError> {
|
2024-03-10 18:48:53 +00:00
|
|
|
let mut new_data = BTreeMap::new();
|
|
|
|
|
2024-03-12 01:57:27 +00:00
|
|
|
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
|
2024-03-11 18:49:44 +00:00
|
|
|
if let ValueData::Type(r#type) = value_data {
|
|
|
|
if let Type::Function { .. } = r#type {
|
2024-03-12 01:57:27 +00:00
|
|
|
new_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
|
2024-03-11 18:49:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if let ValueData::Value(value) = value_data {
|
|
|
|
if let ValueInner::Function { .. } = value.inner().as_ref() {
|
2024-03-12 01:57:27 +00:00
|
|
|
new_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
|
2024-03-11 18:49:44 +00:00
|
|
|
}
|
|
|
|
}
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Self::with_data(new_data))
|
|
|
|
}
|
|
|
|
|
2024-03-12 01:57:27 +00:00
|
|
|
pub fn add_allowance(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
|
|
|
if let Some((_, usage_data)) = self.inner.read()?.get(identifier) {
|
|
|
|
usage_data.0.write()?.allowances += 1;
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
} else {
|
|
|
|
Ok(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-14 15:49:10 +00:00
|
|
|
pub fn use_data(
|
2024-03-06 23:15:25 +00:00
|
|
|
&self,
|
|
|
|
identifier: &Identifier,
|
|
|
|
) -> Result<Option<ValueData>, RwLockPoisonError> {
|
2024-03-12 01:57:27 +00:00
|
|
|
let should_remove =
|
|
|
|
if let Some((value_data, usage_data)) = self.inner.read()?.get(identifier) {
|
|
|
|
let mut usage_data = usage_data.0.write()?;
|
|
|
|
|
|
|
|
log::trace!("Adding use for variable: {identifier}");
|
|
|
|
|
|
|
|
usage_data.uses += 1;
|
|
|
|
|
|
|
|
if usage_data.uses == usage_data.allowances {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
return Ok(Some(value_data.clone()));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
if should_remove {
|
|
|
|
log::trace!("Removing varialble: {identifier}");
|
|
|
|
|
|
|
|
self.inner.write()?.remove(identifier);
|
2024-03-09 11:55:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let value_data = match identifier.as_str() {
|
|
|
|
"output" => ValueData::Value(BuiltInFunction::output()),
|
|
|
|
_ => return Ok(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Some(value_data))
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
|
|
|
|
2024-03-14 15:49:10 +00:00
|
|
|
pub fn use_type(&self, identifier: &Identifier) -> Result<Option<Type>, RwLockPoisonError> {
|
2024-03-12 01:57:27 +00:00
|
|
|
if let Some((ValueData::Type(r#type), usage_data)) = self.inner.read()?.get(identifier) {
|
|
|
|
log::trace!("Adding use for variable: {identifier}");
|
|
|
|
|
|
|
|
usage_data.0.write()?.uses += 1;
|
|
|
|
|
2024-03-09 11:55:19 +00:00
|
|
|
return Ok(Some(r#type.clone()));
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
2024-03-09 11:55:19 +00:00
|
|
|
|
|
|
|
let r#type = match identifier.as_str() {
|
|
|
|
"output" => BuiltInFunction::Output.r#type(),
|
|
|
|
_ => return Ok(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Some(r#type))
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
|
|
|
|
2024-03-14 15:49:10 +00:00
|
|
|
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
|
2024-03-12 01:57:27 +00:00
|
|
|
let should_remove = if let Some((ValueData::Value(value), usage_data)) =
|
|
|
|
self.inner.read()?.get(identifier)
|
|
|
|
{
|
|
|
|
let mut usage_data = usage_data.0.write()?;
|
|
|
|
|
|
|
|
log::trace!("Adding use for variable: {identifier}");
|
|
|
|
|
|
|
|
usage_data.uses += 1;
|
|
|
|
|
|
|
|
if usage_data.uses == usage_data.allowances {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
return Ok(Some(value.clone()));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
if should_remove {
|
|
|
|
log::trace!("Removing varialble: {identifier}");
|
|
|
|
|
|
|
|
self.inner.write()?.remove(identifier);
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
2024-03-09 11:55:19 +00:00
|
|
|
|
|
|
|
let value = match identifier.as_str() {
|
|
|
|
"output" => BuiltInFunction::output(),
|
|
|
|
_ => return Ok(None),
|
|
|
|
};
|
|
|
|
|
|
|
|
Ok(Some(value))
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-03-06 23:15:25 +00:00
|
|
|
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), RwLockPoisonError> {
|
|
|
|
self.inner
|
|
|
|
.write()?
|
2024-03-12 01:57:27 +00:00
|
|
|
.insert(identifier, (ValueData::Type(r#type), UsageData::default()));
|
2024-02-25 18:49:26 +00:00
|
|
|
|
2024-03-06 23:15:25 +00:00
|
|
|
Ok(())
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
2024-03-06 23:15:25 +00:00
|
|
|
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), RwLockPoisonError> {
|
2024-03-12 01:57:27 +00:00
|
|
|
let mut inner = self.inner.write()?;
|
|
|
|
|
|
|
|
if let Some((_value_data, usage_data)) = inner.remove(&identifier) {
|
|
|
|
inner.insert(identifier, (ValueData::Value(value), usage_data));
|
|
|
|
} else {
|
|
|
|
inner.insert(identifier, (ValueData::Value(value), UsageData::default()));
|
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|