Improve context recursion

This commit is contained in:
Jeff 2024-07-02 20:25:47 -04:00
parent ecd83a17e7
commit dce6dfbc40

View File

@ -1,5 +1,6 @@
use std::{ use std::{
collections::HashMap, collections::HashMap,
fmt::Debug,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
@ -73,27 +74,35 @@ impl Context {
let data = self.data.read()?; let data = self.data.read()?;
if let Some(_) = data.variables.get(identifier) { if let Some(_) = data.variables.get(identifier) {
return Ok(true); Ok(true)
} else if let Some(parent) = &data.parent { } else if let Some(parent) = &data.parent {
let parent_data = parent.data.read()?; parent.contains_inheritable(identifier)
} else {
Ok(false)
}
}
if let Some((variable_data, _)) = parent_data.variables.get(identifier) { fn contains_inheritable(&self, identifier: &Identifier) -> Result<bool, ValidationError> {
match variable_data { let data = self.data.read()?;
VariableData::Type(Type::Enum { .. })
| VariableData::Type(Type::Function { .. }) if let Some((variable_data, _)) = data.variables.get(identifier) {
| VariableData::Type(Type::Structure { .. }) => return Ok(true), match variable_data {
VariableData::Value(value) => match value.inner().as_ref() { VariableData::Type(Type::Enum { .. })
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => { | VariableData::Type(Type::Function { .. })
return Ok(true) | VariableData::Type(Type::Structure { .. }) => return Ok(true),
} VariableData::Value(value) => match value.inner().as_ref() {
_ => {} ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => return Ok(true),
},
_ => {} _ => {}
} },
_ => {}
} }
} }
Ok(false) if let Some(parent) = &data.parent {
parent.contains_inheritable(identifier)
} else {
Ok(false)
}
} }
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> { pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
@ -107,19 +116,34 @@ impl Context {
VariableData::Value(value) => value.r#type(self)?, VariableData::Value(value) => value.r#type(self)?,
}; };
return Ok(Some(r#type.clone())); Ok(Some(r#type.clone()))
} else if let Some(parent) = &data.parent { } else if let Some(parent) = &data.parent {
if let Some(r#type) = parent.get_type(identifier)? { parent.get_inheritable_type(identifier)
match r#type { } else {
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => { Ok(None)
return Ok(Some(r#type)) }
} }
_ => {}
fn get_inheritable_type(
&self,
identifier: &Identifier,
) -> Result<Option<Type>, ValidationError> {
let data = self.data.read()?;
if let Some(r#type) = self.get_type(identifier)? {
match r#type {
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
return Ok(Some(r#type))
} }
_ => {}
} }
} }
Ok(None) if let Some(parent) = &data.parent {
parent.get_inheritable_type(identifier)
} else {
Ok(None)
}
} }
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> { pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
@ -133,18 +157,32 @@ impl Context {
return Ok(Some(value.clone())); return Ok(Some(value.clone()));
} else if let Some(parent) = &data.parent { } else if let Some(parent) = &data.parent {
if let Some(value) = parent.get_value(identifier)? { parent.use_inheritable_value(identifier)
match value.inner().as_ref() { } else {
ValueInner::EnumInstance { .. } Ok(None)
| ValueInner::Function(_) }
| ValueInner::Structure { .. } }
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
_ => {} fn use_inheritable_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
let data = self.data.read()?;
if let Some((VariableData::Value(value), usage_data)) = data.variables.get(identifier) {
match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
usage_data.inner().write()?.actual += 1;
*self.is_clean.write()? = false;
return Ok(Some(value.clone()));
} }
_ => {}
} }
} }
Ok(None) if let Some(parent) = &data.parent {
parent.use_inheritable_value(identifier)
} else {
Ok(None)
}
} }
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> { pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
@ -153,20 +191,29 @@ impl Context {
let data = self.data.read()?; let data = self.data.read()?;
if let Some((VariableData::Value(value), _)) = data.variables.get(identifier) { if let Some((VariableData::Value(value), _)) = data.variables.get(identifier) {
return Ok(Some(value.clone())); Ok(Some(value.clone()))
} else if let Some(parent) = &data.parent { } else if let Some(parent) = &data.parent {
if let Some(value) = parent.get_value(identifier)? { parent.get_inheritable_value(identifier)
match value.inner().as_ref() { } else {
ValueInner::EnumInstance { .. } Ok(None)
| ValueInner::Function(_) }
| ValueInner::Structure { .. } }
| ValueInner::BuiltInFunction(_) => return Ok(Some(value)),
_ => {} fn get_inheritable_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
} if let Some(value) = self.get_value(identifier)? {
match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => return Ok(Some(value)),
_ => {}
} }
} }
Ok(None) let data = self.data.read()?;
if let Some(parent) = &data.parent {
parent.get_inheritable_value(identifier)
} else {
Ok(None)
}
} }
pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), PoisonError> { pub fn set_type(&self, identifier: Identifier, r#type: Type) -> Result<(), PoisonError> {
@ -206,31 +253,44 @@ impl Context {
return Ok(true); return Ok(true);
} else if let Some(parent) = &data.parent { } else if let Some(parent) = &data.parent {
let parent_data = parent.data.read()?; parent.add_expected_use_for_inheritable(identifier)
} else {
Ok(false)
}
}
if let Some((variable_data, usage_data)) = parent_data.variables.get(identifier) { fn add_expected_use_for_inheritable(
match variable_data { &self,
VariableData::Type(Type::Enum { .. }) identifier: &Identifier,
| VariableData::Type(Type::Function { .. }) ) -> Result<bool, PoisonError> {
| VariableData::Type(Type::Structure { .. }) => { let data = self.data.read()?;
if let Some((variable_data, usage_data)) = data.variables.get(identifier) {
match variable_data {
VariableData::Type(Type::Enum { .. })
| VariableData::Type(Type::Function { .. })
| VariableData::Type(Type::Structure { .. }) => {
usage_data.inner().write()?.expected += 1;
return Ok(true);
}
VariableData::Value(value) => match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
usage_data.inner().write()?.expected += 1; usage_data.inner().write()?.expected += 1;
return Ok(true); return Ok(true);
} }
VariableData::Value(value) => match value.inner().as_ref() {
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
usage_data.inner().write()?.expected += 1;
return Ok(true);
}
_ => {}
},
_ => {} _ => {}
} },
_ => {}
} }
} }
Ok(false) if let Some(parent) = &data.parent {
parent.add_expected_use_for_inheritable(identifier)
} else {
Ok(false)
}
} }
pub fn clean(&self) -> Result<(), PoisonError> { pub fn clean(&self) -> Result<(), PoisonError> {