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

303 lines
8.8 KiB
Rust
Raw Normal View History

2024-02-25 18:49:26 +00:00
use std::{
collections::HashMap,
2024-06-22 10:36:59 +00:00
sync::{Arc, RwLock},
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-06-21 22:28:12 +00:00
error::{PoisonError, ValidationError},
2024-03-25 04:16:55 +00:00
identifier::Identifier,
standard_library::core_context,
2024-06-26 21:35:30 +00:00
value::ValueInner,
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-06-22 10:36:59 +00:00
pub struct Context {
data: Arc<RwLock<ContextData>>,
is_clean: Arc<RwLock<bool>>,
2024-02-25 18:49:26 +00:00
}
2024-06-22 10:36:59 +00:00
#[derive(Clone, Debug)]
struct ContextData {
variables: HashMap<Identifier, (VariableData, UsageData)>,
parent: Option<Context>,
}
impl Context {
pub fn new(parent: Option<Context>) -> Self {
Context {
data: Arc::new(RwLock::new(ContextData {
variables: HashMap::new(),
parent,
})),
is_clean: Arc::new(RwLock::new(true)),
2024-03-06 23:15:25 +00:00
}
}
pub fn new_with_std_core(parent: Option<Context>) -> Result<Self, PoisonError> {
let new = Context::with_variables_from(core_context())?;
if let Some(context) = parent {
new.set_parent(context)?;
}
Ok(new)
}
2024-06-28 19:35:18 +00:00
pub fn with_variables_from(other: &Context) -> Result<Self, PoisonError> {
let variables = other.data.read()?.variables.clone();
Ok(Context {
data: Arc::new(RwLock::new(ContextData {
variables,
parent: None,
})),
is_clean: Arc::new(RwLock::new(true)),
})
}
2024-06-22 10:36:59 +00:00
pub fn create_child(&self) -> Context {
Context::new(Some(self.clone()))
2024-03-20 08:42:13 +00:00
}
2024-06-24 06:01:08 +00:00
pub fn set_parent(&self, parent: Context) -> Result<(), PoisonError> {
self.data.write()?.parent = Some(parent);
Ok(())
}
2024-06-26 21:35:30 +00:00
pub fn contains(&self, identifier: &Identifier) -> Result<bool, ValidationError> {
log::trace!("Checking that {identifier} exists");
2024-04-22 07:41:21 +00:00
2024-07-02 17:45:32 +00:00
let data = self.data.read()?;
if let Some(_) = data.variables.get(identifier) {
return Ok(true);
} else if let Some(parent) = &data.parent {
let parent_data = parent.data.read()?;
if let Some((variable_data, _)) = parent_data.variables.get(identifier) {
match variable_data {
VariableData::Type(Type::Enum { .. })
| VariableData::Type(Type::Function { .. })
| VariableData::Type(Type::Structure { .. }) => return Ok(true),
VariableData::Value(value) => match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
return Ok(true)
}
_ => {}
},
_ => {}
}
}
}
Ok(false)
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-06-26 21:35:30 +00:00
log::trace!("Getting {identifier}'s type");
2024-06-22 10:36:59 +00:00
let data = self.data.read()?;
2024-06-22 10:36:59 +00:00
if let Some((data, _)) = data.variables.get(identifier) {
2024-06-18 22:54:17 +00:00
let r#type = match data {
2024-06-17 14:10:06 +00:00
VariableData::Type(r#type) => r#type.clone(),
VariableData::Value(value) => value.r#type(self)?,
2024-03-12 01:57:27 +00:00
};
2024-06-26 21:35:30 +00:00
return Ok(Some(r#type.clone()));
2024-06-22 10:36:59 +00:00
} else if let Some(parent) = &data.parent {
2024-06-26 21:35:30 +00:00
if let Some(r#type) = parent.get_type(identifier)? {
match r#type {
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
return Ok(Some(r#type))
}
_ => {}
}
}
2024-03-18 12:15:30 +00:00
}
2024-06-26 21:35:30 +00:00
Ok(None)
2024-03-06 23:15:25 +00:00
}
2024-06-21 22:28:12 +00:00
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
2024-06-26 21:35:30 +00:00
log::trace!("Using {identifier}'s value");
2024-06-22 10:36:59 +00:00
let data = self.data.read()?;
if let Some((VariableData::Value(value), usage_data)) = data.variables.get(identifier) {
2024-04-22 09:50:26 +00:00
usage_data.inner().write()?.actual += 1;
*self.is_clean.write()? = false;
2024-06-26 21:35:30 +00:00
return Ok(Some(value.clone()));
2024-06-22 10:36:59 +00:00
} else if let Some(parent) = &data.parent {
2024-06-26 21:35:30 +00:00
if let Some(value) = parent.get_value(identifier)? {
match value.inner().as_ref() {
ValueInner::EnumInstance { .. }
| ValueInner::Function(_)
2024-06-28 19:35:18 +00:00
| ValueInner::Structure { .. }
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
2024-06-26 21:35:30 +00:00
_ => {}
}
}
2024-02-25 18:49:26 +00:00
}
2024-06-26 21:35:30 +00:00
Ok(None)
2024-02-25 18:49:26 +00:00
}
2024-06-21 22:28:12 +00:00
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
2024-06-26 21:35:30 +00:00
log::trace!("Getting {identifier}'s value");
2024-04-27 07:40:05 +00:00
2024-06-22 10:36:59 +00:00
let data = self.data.read()?;
2024-04-27 07:40:05 +00:00
2024-06-22 10:36:59 +00:00
if let Some((VariableData::Value(value), _)) = data.variables.get(identifier) {
2024-06-26 21:35:30 +00:00
return Ok(Some(value.clone()));
2024-06-22 10:36:59 +00:00
} else if let Some(parent) = &data.parent {
2024-06-26 21:35:30 +00:00
if let Some(value) = parent.get_value(identifier)? {
match value.inner().as_ref() {
ValueInner::EnumInstance { .. }
| ValueInner::Function(_)
2024-06-28 19:35:18 +00:00
| ValueInner::Structure { .. }
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
2024-06-26 21:35:30 +00:00
_ => {}
}
}
2024-04-27 07:40:05 +00:00
}
2024-06-26 21:35:30 +00:00
Ok(None)
2024-04-22 11:56:03 +00:00
}
2024-06-21 22:28:12 +00:00
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), PoisonError> {
2024-06-26 21:35:30 +00:00
log::debug!("Setting {identifier} to type {}", r#type);
2024-06-22 10:36:59 +00:00
self.data
2024-03-06 23:15:25 +00:00
.write()?
2024-06-22 10:36:59 +00:00
.variables
2024-06-17 14:10:06 +00:00
.insert(identifier, (VariableData::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-06-22 03:37:25 +00:00
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), PoisonError> {
2024-06-26 21:35:30 +00:00
log::debug!("Setting {identifier} to value {value}");
2024-06-22 10:36:59 +00:00
let mut data = self.data.write()?;
let usage_data = data
.variables
2024-04-22 07:41:21 +00:00
.remove(&identifier)
2024-06-22 10:36:59 +00:00
.map(|(_, usage_data)| usage_data)
2024-06-28 19:35:18 +00:00
.unwrap_or_else(|| UsageData::new());
2024-06-22 10:36:59 +00:00
data.variables
.insert(identifier, (VariableData::Value(value), usage_data));
2024-02-25 18:49:26 +00:00
Ok(())
}
2024-03-23 12:47:57 +00:00
2024-06-22 10:36:59 +00:00
pub fn add_expected_use(&self, identifier: &Identifier) -> Result<bool, PoisonError> {
2024-07-02 17:45:32 +00:00
log::trace!("Adding expected use for variable {identifier}");
2024-06-22 10:36:59 +00:00
let data = self.data.read()?;
if let Some((_, usage_data)) = data.variables.get(identifier) {
usage_data.inner().write()?.expected += 1;
2024-06-28 19:35:18 +00:00
return Ok(true);
2024-06-22 10:36:59 +00:00
} else if let Some(parent) = &data.parent {
2024-06-28 19:35:18 +00:00
let parent_data = parent.data.read()?;
if let Some((variable_data, usage_data)) = parent_data.variables.get(identifier) {
2024-07-02 17:45:32 +00:00
match variable_data {
VariableData::Type(Type::Enum { .. })
| VariableData::Type(Type::Function { .. })
| VariableData::Type(Type::Structure { .. }) => {
2024-06-28 19:35:18 +00:00
usage_data.inner().write()?.expected += 1;
return Ok(true);
}
2024-07-02 17:45:32 +00:00
VariableData::Value(value) => match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
usage_data.inner().write()?.expected += 1;
return Ok(true);
}
_ => {}
},
_ => {}
2024-06-28 19:35:18 +00:00
}
}
2024-06-22 10:36:59 +00:00
}
2024-06-28 19:35:18 +00:00
Ok(false)
2024-06-22 10:36:59 +00:00
}
2024-06-22 03:37:25 +00:00
pub fn clean(&self) -> Result<(), PoisonError> {
if *self.is_clean.read()? {
2024-04-22 11:56:03 +00:00
return Ok(());
}
2024-06-26 21:35:30 +00:00
self.data.write()?.variables.retain(
|identifier, (value_data, usage_data)| match value_data {
VariableData::Type(_) => true,
VariableData::Value(_) => {
let usage = usage_data.inner().read().unwrap();
if usage.actual < usage.expected {
true
} else {
log::trace!("Removing {identifier}");
false
}
}
},
);
*self.is_clean.write()? = true;
2024-04-22 11:56:03 +00:00
Ok(())
}
2024-06-21 22:28:12 +00:00
pub fn is_clean(&mut self) -> Result<bool, PoisonError> {
2024-06-22 10:36:59 +00:00
Ok(*self.is_clean.read()?)
}
2024-02-25 18:49:26 +00:00
}
2024-03-17 17:36:31 +00:00
2024-06-22 17:55:43 +00:00
impl Default for Context {
fn default() -> Self {
Context::new(None)
}
}
2024-03-17 17:36:31 +00:00
#[derive(Clone, Debug, PartialEq)]
2024-06-17 14:10:06 +00:00
pub enum VariableData {
2024-03-17 17:36:31 +00:00
Type(Type),
Value(Value),
}
#[derive(Clone, Debug)]
2024-04-22 09:50:26 +00:00
pub struct UsageData(Arc<RwLock<UsageDataInner>>);
impl UsageData {
pub fn inner(&self) -> &Arc<RwLock<UsageDataInner>> {
&self.0
}
}
#[derive(Clone, Debug)]
pub struct UsageDataInner {
pub actual: u32,
pub expected: u32,
}
impl UsageData {
pub fn new() -> Self {
2024-04-22 09:50:26 +00:00
UsageData(Arc::new(RwLock::new(UsageDataInner {
actual: 0,
expected: 0,
2024-04-22 09:50:26 +00:00
})))
}
}