2024-02-25 18:49:26 +00:00
|
|
|
use std::{
|
|
|
|
collections::BTreeMap,
|
2024-03-23 15:24:25 +00:00
|
|
|
sync::{Arc, RwLock, RwLockReadGuard},
|
2024-02-25 18:49:26 +00:00
|
|
|
};
|
|
|
|
|
2024-03-06 23:15:25 +00:00
|
|
|
use crate::{
|
2024-03-25 04:16:55 +00:00
|
|
|
abstract_tree::Type,
|
2024-03-19 22:31:52 +00:00
|
|
|
error::{RwLockPoisonError, ValidationError},
|
2024-03-25 04:16:55 +00:00
|
|
|
identifier::Identifier,
|
2024-03-24 00:36:23 +00:00
|
|
|
Value,
|
2024-03-06 23:15:25 +00:00
|
|
|
};
|
2024-02-25 18:49:26 +00:00
|
|
|
|
2024-03-12 01:57:27 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2024-03-17 17:36:31 +00:00
|
|
|
pub struct Context {
|
2024-04-22 07:41:21 +00:00
|
|
|
variables: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
2024-04-22 07:41:21 +00:00
|
|
|
variables: Arc::new(RwLock::new(BTreeMap::new())),
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-22 05:51:34 +00:00
|
|
|
pub fn with_data(data: BTreeMap<Identifier, (ValueData, UsageData)>) -> Self {
|
2024-02-25 18:49:26 +00:00
|
|
|
Self {
|
2024-04-22 07:41:21 +00:00
|
|
|
variables: Arc::new(RwLock::new(data)),
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-20 08:42:13 +00:00
|
|
|
pub fn inner(
|
|
|
|
&self,
|
2024-04-22 05:51:34 +00:00
|
|
|
) -> Result<RwLockReadGuard<BTreeMap<Identifier, (ValueData, UsageData)>>, RwLockPoisonError>
|
|
|
|
{
|
2024-04-22 07:41:21 +00:00
|
|
|
Ok(self.variables.read()?)
|
2024-03-20 08:42:13 +00:00
|
|
|
}
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
pub fn inherit_types_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
let mut self_data = self.variables.write()?;
|
2024-03-10 18:48:53 +00:00
|
|
|
|
2024-04-22 07:41:21 +00:00
|
|
|
for (identifier, (value_data, usage_data)) in other.variables.read()?.iter() {
|
2024-03-20 04:28:28 +00:00
|
|
|
if let ValueData::Type(Type::Function { .. }) = value_data {
|
2024-04-22 07:41:21 +00:00
|
|
|
log::trace!("Inheriting type of variable {identifier}.");
|
|
|
|
|
2024-04-22 05:51:34 +00:00
|
|
|
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
Ok(())
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
pub fn inherit_data_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
let mut self_data = self.variables.write()?;
|
|
|
|
|
|
|
|
for (identifier, (value_data, usage_data)) in other.variables.read()?.iter() {
|
|
|
|
log::trace!("Inheriting variable {identifier}.");
|
2024-03-10 18:48:53 +00:00
|
|
|
|
2024-04-22 05:51:34 +00:00
|
|
|
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
Ok(())
|
2024-03-10 18:48:53 +00:00
|
|
|
}
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
pub fn contains(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
log::trace!("Checking that {identifier} exists.");
|
|
|
|
|
|
|
|
Ok(self.variables.read()?.contains_key(identifier))
|
2024-03-12 01:57:27 +00:00
|
|
|
}
|
|
|
|
|
2024-03-19 22:31:52 +00:00
|
|
|
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
if let Some((value_data, _)) = self.variables.read()?.get(identifier) {
|
2024-04-22 05:51:34 +00:00
|
|
|
log::trace!("Using {identifier}'s type.");
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
let r#type = match value_data {
|
2024-03-20 12:36:18 +00:00
|
|
|
ValueData::Type(r#type) => r#type.clone(),
|
2024-03-19 22:31:52 +00:00
|
|
|
ValueData::Value(value) => value.r#type(self)?,
|
2024-03-12 01:57:27 +00:00
|
|
|
};
|
|
|
|
|
2024-03-23 12:15:48 +00:00
|
|
|
Ok(Some(r#type.clone()))
|
|
|
|
} else {
|
|
|
|
Ok(None)
|
2024-03-18 12:15:30 +00:00
|
|
|
}
|
2024-03-06 23:15:25 +00:00
|
|
|
}
|
|
|
|
|
2024-04-22 05:51:34 +00:00
|
|
|
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
if let Some((ValueData::Value(value), usage_data)) =
|
|
|
|
self.variables.write()?.get_mut(identifier)
|
2024-04-22 05:51:34 +00:00
|
|
|
{
|
|
|
|
log::trace!("Using {identifier}'s value.");
|
|
|
|
|
|
|
|
usage_data.actual += 1;
|
|
|
|
|
2024-03-17 17:36:31 +00:00
|
|
|
Ok(Some(value.clone()))
|
2024-03-12 01:57:27 +00:00
|
|
|
} else {
|
2024-03-18 12:15:30 +00:00
|
|
|
Ok(None)
|
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> {
|
2024-04-22 07:41:21 +00:00
|
|
|
log::debug!("Setting {identifier} to type {}.", r#type);
|
2024-04-22 05:51:34 +00:00
|
|
|
|
2024-04-22 07:41:21 +00:00
|
|
|
self.variables
|
2024-03-06 23:15:25 +00:00
|
|
|
.write()?
|
2024-04-22 05:51:34 +00:00
|
|
|
.insert(identifier, (ValueData::Type(r#type), UsageData::new()));
|
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-04-22 07:41:21 +00:00
|
|
|
log::debug!("Setting {identifier} to value {value}.");
|
2024-04-22 05:51:34 +00:00
|
|
|
|
2024-04-22 07:41:21 +00:00
|
|
|
let mut variables = self.variables.write()?;
|
|
|
|
let old_usage_data = variables
|
|
|
|
.remove(&identifier)
|
|
|
|
.map(|(_, usage_data)| usage_data);
|
2024-04-22 05:51:34 +00:00
|
|
|
|
|
|
|
if let Some(usage_data) = old_usage_data {
|
2024-04-22 07:41:21 +00:00
|
|
|
variables.insert(identifier, (ValueData::Value(value), usage_data));
|
2024-04-22 05:51:34 +00:00
|
|
|
} else {
|
2024-04-22 07:41:21 +00:00
|
|
|
variables.insert(identifier, (ValueData::Value(value), UsageData::new()));
|
2024-04-22 05:51:34 +00:00
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-03-23 12:47:57 +00:00
|
|
|
|
|
|
|
pub fn remove(&self, identifier: &Identifier) -> Result<Option<ValueData>, RwLockPoisonError> {
|
2024-04-22 05:51:34 +00:00
|
|
|
let removed = self
|
2024-04-22 07:41:21 +00:00
|
|
|
.variables
|
2024-04-22 05:51:34 +00:00
|
|
|
.write()?
|
|
|
|
.remove(identifier)
|
|
|
|
.map(|(value_data, _)| value_data);
|
2024-03-23 12:47:57 +00:00
|
|
|
|
|
|
|
Ok(removed)
|
|
|
|
}
|
2024-04-22 05:51:34 +00:00
|
|
|
|
|
|
|
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
self.variables
|
2024-04-22 05:51:34 +00:00
|
|
|
.write()?
|
2024-04-22 07:41:21 +00:00
|
|
|
.retain(|identifier, (_, usage_data)| {
|
2024-04-22 05:51:34 +00:00
|
|
|
if usage_data.actual < usage_data.expected {
|
|
|
|
true
|
|
|
|
} else {
|
2024-04-22 07:41:21 +00:00
|
|
|
log::trace!("Removing variable {identifier}.");
|
2024-04-22 05:51:34 +00:00
|
|
|
|
|
|
|
false
|
|
|
|
}
|
2024-04-22 07:41:21 +00:00
|
|
|
});
|
2024-04-22 05:51:34 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
|
2024-04-22 07:41:21 +00:00
|
|
|
let mut variables = self.variables.write()?;
|
2024-04-22 05:51:34 +00:00
|
|
|
|
2024-04-22 07:41:21 +00:00
|
|
|
if let Some((_, usage_data)) = variables.get_mut(identifier) {
|
2024-04-22 05:51:34 +00:00
|
|
|
log::trace!("Adding expected use for variable {identifier}.");
|
|
|
|
|
|
|
|
usage_data.expected += 1;
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
} else {
|
|
|
|
Ok(false)
|
|
|
|
}
|
|
|
|
}
|
2024-02-25 18:49:26 +00:00
|
|
|
}
|
2024-03-17 17:36:31 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum ValueData {
|
|
|
|
Type(Type),
|
|
|
|
Value(Value),
|
|
|
|
}
|
2024-04-22 05:51:34 +00:00
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub struct UsageData {
|
|
|
|
pub actual: u32,
|
|
|
|
pub expected: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UsageData {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
actual: 0,
|
|
|
|
expected: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|