This commit is contained in:
Jeff 2024-06-26 17:35:30 -04:00
parent 29bbcb019d
commit fe0bb0a0b5
5 changed files with 94 additions and 48 deletions

View File

@ -7,6 +7,7 @@ use crate::{
abstract_tree::Type,
error::{PoisonError, ValidationError},
identifier::Identifier,
value::ValueInner,
Value,
};
@ -43,22 +44,14 @@ impl Context {
Ok(())
}
pub fn contains(&self, identifier: &Identifier) -> Result<bool, PoisonError> {
log::trace!("Checking that {identifier} exists.");
pub fn contains(&self, identifier: &Identifier) -> Result<bool, ValidationError> {
log::trace!("Checking that {identifier} exists");
let data = self.data.read()?;
if data.variables.contains_key(identifier) {
Ok(true)
} else if let Some(parent) = &data.parent {
parent.contains(identifier)
} else {
Ok(false)
}
Ok(self.get_type(identifier)?.is_some())
}
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()?;
@ -68,16 +61,23 @@ impl Context {
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 {
parent.get_type(identifier)
} else {
Ok(None)
if let Some(r#type) = parent.get_type(identifier)? {
match r#type {
Type::Enum { .. } | Type::Function { .. } | Type::Structure { .. } => {
return Ok(Some(r#type))
}
_ => {}
}
}
}
Ok(None)
}
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()?;
@ -85,30 +85,44 @@ impl Context {
usage_data.inner().write()?.actual += 1;
*self.is_clean.write()? = false;
Ok(Some(value.clone()))
return Ok(Some(value.clone()));
} else if let Some(parent) = &data.parent {
parent.get_value(identifier)
} else {
Ok(None)
if let Some(value) = parent.get_value(identifier)? {
match value.inner().as_ref() {
ValueInner::EnumInstance { .. }
| ValueInner::Function(_)
| ValueInner::Structure { .. } => return Ok(Some(value)),
_ => {}
}
}
}
Ok(None)
}
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()?;
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 {
parent.get_value(identifier)
} else {
Ok(None)
if let Some(value) = parent.get_value(identifier)? {
match value.inner().as_ref() {
ValueInner::EnumInstance { .. }
| ValueInner::Function(_)
| ValueInner::Structure { .. } => return Ok(Some(value)),
_ => {}
}
}
}
Ok(None)
}
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
.write()?
@ -119,7 +133,7 @@ impl Context {
}
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 usage_data = data
@ -138,7 +152,7 @@ impl Context {
let data = self.data.read()?;
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;
@ -155,22 +169,22 @@ impl Context {
return Ok(());
}
// 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();
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}.");
if usage.actual < usage.expected {
true
} else {
log::trace!("Removing {identifier}");
// false
// }
// }
// },
// );
false
}
}
},
);
*self.is_clean.write()? = true;

View File

@ -407,7 +407,7 @@ pub fn parser<'src>(
if !allow_built_ins {
emitter.emit(Rich::custom(
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.",
))
}

View File

@ -217,7 +217,7 @@ impl Display for Value {
write!(f, " -> {return_type}")?
}
write!(f, " {{ {body} }}")
write!(f, " {body}")
}
ValueInner::Structure { name, fields } => {
write!(f, "{}\n{{", name.node)?;

View File

@ -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()
}]
);
}