Improve context recursion
This commit is contained in:
parent
ecd83a17e7
commit
dce6dfbc40
@ -1,5 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
|
fmt::Debug,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -73,28 +74,36 @@ 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> {
|
||||||
|
let data = self.data.read()?;
|
||||||
|
|
||||||
|
if let Some((variable_data, _)) = data.variables.get(identifier) {
|
||||||
match variable_data {
|
match variable_data {
|
||||||
VariableData::Type(Type::Enum { .. })
|
VariableData::Type(Type::Enum { .. })
|
||||||
| VariableData::Type(Type::Function { .. })
|
| VariableData::Type(Type::Function { .. })
|
||||||
| VariableData::Type(Type::Structure { .. }) => return Ok(true),
|
| VariableData::Type(Type::Structure { .. }) => return Ok(true),
|
||||||
VariableData::Value(value) => match value.inner().as_ref() {
|
VariableData::Value(value) => match value.inner().as_ref() {
|
||||||
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => {
|
ValueInner::BuiltInFunction(_) | ValueInner::Function(_) => return Ok(true),
|
||||||
return Ok(true)
|
|
||||||
}
|
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if let Some(parent) = &data.parent {
|
||||||
|
parent.contains_inheritable(identifier)
|
||||||
|
} else {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
|
pub fn get_type(&self, identifier: &Identifier) -> Result<Option<Type>, ValidationError> {
|
||||||
log::trace!("Getting {identifier}'s type");
|
log::trace!("Getting {identifier}'s type");
|
||||||
@ -107,9 +116,21 @@ 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)
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
match r#type {
|
||||||
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
|
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
|
||||||
return Ok(Some(r#type))
|
return Ok(Some(r#type))
|
||||||
@ -117,10 +138,13 @@ impl Context {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if let Some(parent) = &data.parent {
|
||||||
|
parent.get_inheritable_type(identifier)
|
||||||
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
|
pub fn use_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
|
||||||
log::trace!("Using {identifier}'s value");
|
log::trace!("Using {identifier}'s value");
|
||||||
@ -133,19 +157,33 @@ 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()));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(parent) = &data.parent {
|
||||||
|
parent.use_inheritable_value(identifier)
|
||||||
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
|
pub fn get_value(&self, identifier: &Identifier) -> Result<Option<Value>, PoisonError> {
|
||||||
log::trace!("Getting {identifier}'s value");
|
log::trace!("Getting {identifier}'s value");
|
||||||
@ -153,21 +191,30 @@ 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)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = self.data.read()?;
|
||||||
|
|
||||||
|
if let Some(parent) = &data.parent {
|
||||||
|
parent.get_inheritable_value(identifier)
|
||||||
|
} else {
|
||||||
Ok(None)
|
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> {
|
||||||
log::debug!("Setting {identifier} to type {}", r#type);
|
log::debug!("Setting {identifier} to type {}", r#type);
|
||||||
@ -206,9 +253,19 @@ 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(
|
||||||
|
&self,
|
||||||
|
identifier: &Identifier,
|
||||||
|
) -> Result<bool, PoisonError> {
|
||||||
|
let data = self.data.read()?;
|
||||||
|
|
||||||
|
if let Some((variable_data, usage_data)) = data.variables.get(identifier) {
|
||||||
match variable_data {
|
match variable_data {
|
||||||
VariableData::Type(Type::Enum { .. })
|
VariableData::Type(Type::Enum { .. })
|
||||||
| VariableData::Type(Type::Function { .. })
|
| VariableData::Type(Type::Function { .. })
|
||||||
@ -228,10 +285,13 @@ impl Context {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
if let Some(parent) = &data.parent {
|
||||||
|
parent.add_expected_use_for_inheritable(identifier)
|
||||||
|
} else {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn clean(&self) -> Result<(), PoisonError> {
|
pub fn clean(&self) -> Result<(), PoisonError> {
|
||||||
if *self.is_clean.read()? {
|
if *self.is_clean.read()? {
|
||||||
|
Loading…
Reference in New Issue
Block a user