Clean up
This commit is contained in:
parent
29bbcb019d
commit
fe0bb0a0b5
@ -7,6 +7,7 @@ use crate::{
|
|||||||
abstract_tree::Type,
|
abstract_tree::Type,
|
||||||
error::{PoisonError, ValidationError},
|
error::{PoisonError, ValidationError},
|
||||||
identifier::Identifier,
|
identifier::Identifier,
|
||||||
|
value::ValueInner,
|
||||||
Value,
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -43,22 +44,14 @@ impl Context {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, identifier: &Identifier) -> Result<bool, PoisonError> {
|
pub fn contains(&self, identifier: &Identifier) -> Result<bool, ValidationError> {
|
||||||
log::trace!("Checking that {identifier} exists.");
|
log::trace!("Checking that {identifier} exists");
|
||||||
|
|
||||||
let data = self.data.read()?;
|
Ok(self.get_type(identifier)?.is_some())
|
||||||
|
|
||||||
if data.variables.contains_key(identifier) {
|
|
||||||
Ok(true)
|
|
||||||
} else if let Some(parent) = &data.parent {
|
|
||||||
parent.contains(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> {
|
||||||
log::trace!("Getting {identifier}'s type.");
|
log::trace!("Getting {identifier}'s type");
|
||||||
|
|
||||||
let data = self.data.read()?;
|
let data = self.data.read()?;
|
||||||
|
|
||||||
@ -68,16 +61,23 @@ impl Context {
|
|||||||
VariableData::Value(value) => value.r#type(self)?,
|
VariableData::Value(value) => value.r#type(self)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(r#type.clone()))
|
return Ok(Some(r#type.clone()));
|
||||||
} else if let Some(parent) = &data.parent {
|
} else if let Some(parent) = &data.parent {
|
||||||
parent.get_type(identifier)
|
if let Some(r#type) = parent.get_type(identifier)? {
|
||||||
} else {
|
match r#type {
|
||||||
Ok(None)
|
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
|
||||||
|
return Ok(Some(r#type))
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
let data = self.data.read()?;
|
let data = self.data.read()?;
|
||||||
|
|
||||||
@ -85,30 +85,44 @@ impl Context {
|
|||||||
usage_data.inner().write()?.actual += 1;
|
usage_data.inner().write()?.actual += 1;
|
||||||
*self.is_clean.write()? = false;
|
*self.is_clean.write()? = false;
|
||||||
|
|
||||||
Ok(Some(value.clone()))
|
return Ok(Some(value.clone()));
|
||||||
} else if let Some(parent) = &data.parent {
|
} else if let Some(parent) = &data.parent {
|
||||||
parent.get_value(identifier)
|
if let Some(value) = parent.get_value(identifier)? {
|
||||||
} else {
|
match value.inner().as_ref() {
|
||||||
Ok(None)
|
ValueInner::EnumInstance { .. }
|
||||||
|
| ValueInner::Function(_)
|
||||||
|
| ValueInner::Structure { .. } => return Ok(Some(value)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
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) {
|
||||||
Ok(Some(value.clone()))
|
return Ok(Some(value.clone()));
|
||||||
} else if let Some(parent) = &data.parent {
|
} else if let Some(parent) = &data.parent {
|
||||||
parent.get_value(identifier)
|
if let Some(value) = parent.get_value(identifier)? {
|
||||||
} else {
|
match value.inner().as_ref() {
|
||||||
Ok(None)
|
ValueInner::EnumInstance { .. }
|
||||||
|
| ValueInner::Function(_)
|
||||||
|
| ValueInner::Structure { .. } => return Ok(Some(value)),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
self.data
|
self.data
|
||||||
.write()?
|
.write()?
|
||||||
@ -119,7 +133,7 @@ impl Context {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), PoisonError> {
|
pub fn set_value(&self, identifier: Identifier, value: Value) -> Result<(), PoisonError> {
|
||||||
log::debug!("Setting {identifier} to value {value}.");
|
log::debug!("Setting {identifier} to value {value}");
|
||||||
|
|
||||||
let mut data = self.data.write()?;
|
let mut data = self.data.write()?;
|
||||||
let usage_data = data
|
let usage_data = data
|
||||||
@ -138,7 +152,7 @@ impl Context {
|
|||||||
let data = self.data.read()?;
|
let data = self.data.read()?;
|
||||||
|
|
||||||
if let Some((_, usage_data)) = data.variables.get(identifier) {
|
if let Some((_, usage_data)) = data.variables.get(identifier) {
|
||||||
log::trace!("Adding expected use for variable {identifier}.");
|
log::trace!("Adding expected use for variable {identifier}");
|
||||||
|
|
||||||
usage_data.inner().write()?.expected += 1;
|
usage_data.inner().write()?.expected += 1;
|
||||||
|
|
||||||
@ -155,22 +169,22 @@ impl Context {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// self.data.write()?.variables.retain(
|
self.data.write()?.variables.retain(
|
||||||
// |identifier, (value_data, usage_data)| match value_data {
|
|identifier, (value_data, usage_data)| match value_data {
|
||||||
// VariableData::Type(_) => true,
|
VariableData::Type(_) => true,
|
||||||
// VariableData::Value(_) => {
|
VariableData::Value(_) => {
|
||||||
// let usage = usage_data.inner().read().unwrap();
|
let usage = usage_data.inner().read().unwrap();
|
||||||
|
|
||||||
// if usage.actual < usage.expected {
|
if usage.actual < usage.expected {
|
||||||
// true
|
true
|
||||||
// } else {
|
} else {
|
||||||
// log::trace!("Removing {identifier}.");
|
log::trace!("Removing {identifier}");
|
||||||
|
|
||||||
// false
|
false
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// },
|
},
|
||||||
// );
|
);
|
||||||
|
|
||||||
*self.is_clean.write()? = true;
|
*self.is_clean.write()? = true;
|
||||||
|
|
||||||
|
@ -407,7 +407,7 @@ pub fn parser<'src>(
|
|||||||
if !allow_built_ins {
|
if !allow_built_ins {
|
||||||
emitter.emit(Rich::custom(
|
emitter.emit(Rich::custom(
|
||||||
state.span(),
|
state.span(),
|
||||||
"Built-in function calls can only be used by the standard library.",
|
"Built-in functions can only be used by the standard library.",
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ impl Display for Value {
|
|||||||
write!(f, " -> {return_type}")?
|
write!(f, " -> {return_type}")?
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(f, " {{ {body} }}")
|
write!(f, " {body}")
|
||||||
}
|
}
|
||||||
ValueInner::Structure { name, fields } => {
|
ValueInner::Structure { name, fields } => {
|
||||||
write!(f, "{}\n{{", name.node)?;
|
write!(f, "{}\n{{", name.node)?;
|
||||||
|
@ -49,3 +49,35 @@ fn function_return_type_error() {
|
|||||||
}]
|
}]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn scope() {
|
||||||
|
assert_eq!(
|
||||||
|
interpret(
|
||||||
|
"test",
|
||||||
|
"
|
||||||
|
x = 1
|
||||||
|
|
||||||
|
foo = fn () -> int {
|
||||||
|
x
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
foo()
|
||||||
|
"
|
||||||
|
)
|
||||||
|
.unwrap_err()
|
||||||
|
.errors(),
|
||||||
|
&vec![DustError::Validation {
|
||||||
|
error: ValidationError::TypeCheck {
|
||||||
|
conflict: TypeConflict {
|
||||||
|
actual: Type::String,
|
||||||
|
expected: Type::Integer
|
||||||
|
},
|
||||||
|
actual_position: (66, 71).into(),
|
||||||
|
expected_position: Some((60, 63).into())
|
||||||
|
},
|
||||||
|
position: (55, 71).into()
|
||||||
|
}]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user