1
0
dust/dust-lang/src/context.rs

186 lines
5.0 KiB
Rust
Raw Normal View History

2024-02-25 18:49:26 +00:00
use std::{
collections::BTreeMap,
sync::{Arc, RwLock, RwLockReadGuard},
2024-02-25 18:49:26 +00:00
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};
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 {
inner: Arc<RwLock<BTreeMap<Identifier, (ValueData, UsageData)>>>,
2024-02-25 18:49:26 +00:00
}
impl Context {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(BTreeMap::new())),
}
}
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-20 08:42:13 +00:00
pub fn inner(
&self,
) -> Result<RwLockReadGuard<BTreeMap<Identifier, (ValueData, UsageData)>>, RwLockPoisonError>
{
2024-03-20 08:42:13 +00:00
Ok(self.inner.read()?)
}
2024-03-17 17:36:31 +00:00
pub fn inherit_types_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
let mut self_data = self.inner.write()?;
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
if let ValueData::Type(Type::Function { .. }) = value_data {
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
}
}
2024-03-17 17:36:31 +00:00
Ok(())
}
2024-03-17 17:36:31 +00:00
pub fn inherit_data_from(&self, other: &Context) -> Result<(), RwLockPoisonError> {
let mut self_data = self.inner.write()?;
for (identifier, (value_data, usage_data)) in other.inner.read()?.iter() {
self_data.insert(identifier.clone(), (value_data.clone(), usage_data.clone()));
}
2024-03-17 17:36:31 +00:00
Ok(())
}
2024-03-17 17:36:31 +00:00
pub fn contains(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
2024-03-24 13:10:49 +00:00
Ok(self.inner.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> {
if let Some((value_data, _)) = self.inner.read()?.get(identifier) {
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
}
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, RwLockPoisonError> {
if let Some((ValueData::Value(value), usage_data)) = self.inner.write()?.get_mut(identifier)
{
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> {
log::info!("Setting {identifier} to type {}.", r#type);
2024-03-06 23:15:25 +00:00
self.inner
.write()?
.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> {
log::info!("Setting {identifier} to value {value}.");
let mut inner = self.inner.write()?;
let old_usage_data = inner.remove(&identifier).map(|(_, usage_data)| usage_data);
if let Some(usage_data) = old_usage_data {
inner.insert(identifier, (ValueData::Value(value), usage_data));
} else {
inner.insert(identifier, (ValueData::Value(value), UsageData::new()));
}
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> {
let removed = self
.inner
.write()?
.remove(identifier)
.map(|(value_data, _)| value_data);
2024-03-23 12:47:57 +00:00
Ok(removed)
}
pub fn clean(&mut self) -> Result<(), RwLockPoisonError> {
let clean_variables = self
.inner
.write()?
.clone()
.into_par_iter()
.filter(|(identifier, (_, usage_data))| {
if usage_data.actual < usage_data.expected {
true
} else {
log::debug!("Removing variable {identifier}.");
false
}
})
.collect();
self.inner = Arc::new(RwLock::new(clean_variables));
Ok(())
}
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, RwLockPoisonError> {
let mut inner = self.inner.write()?;
if let Some((_, usage_data)) = inner.get_mut(identifier) {
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),
}
#[derive(Clone, Debug)]
pub struct UsageData {
pub actual: u32,
pub expected: u32,
}
impl UsageData {
pub fn new() -> Self {
Self {
actual: 0,
expected: 0,
}
}
}