From fe0bb0a0b5ee234d7b31885f01bb800b97ad84f2 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 26 Jun 2024 17:35:30 -0400 Subject: [PATCH] Clean up --- dust-lang/src/abstract_tree/block.rs | 4 +- dust-lang/src/context.rs | 100 +++++++++++++++------------ dust-lang/src/parser/mod.rs | 2 +- dust-lang/src/value.rs | 4 +- dust-lang/tests/validation.rs | 32 +++++++++ 5 files changed, 94 insertions(+), 48 deletions(-) diff --git a/dust-lang/src/abstract_tree/block.rs b/dust-lang/src/abstract_tree/block.rs index 11dffd0..2ca57a3 100644 --- a/dust-lang/src/abstract_tree/block.rs +++ b/dust-lang/src/abstract_tree/block.rs @@ -66,10 +66,10 @@ impl AbstractNode for Block { impl Display for Block { fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!(f, "{{")?; + write!(f, "{{ ")?; for statement in &self.statements { - write!(f, "{statement}")?; + write!(f, "{statement} ")?; } write!(f, "}}") diff --git a/dust-lang/src/context.rs b/dust-lang/src/context.rs index 1800592..59c13d1 100644 --- a/dust-lang/src/context.rs +++ b/dust-lang/src/context.rs @@ -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 { - log::trace!("Checking that {identifier} exists."); + pub fn contains(&self, identifier: &Identifier) -> Result { + 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, 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, 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, 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; diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index c341bef..e45073a 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -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.", )) } diff --git a/dust-lang/src/value.rs b/dust-lang/src/value.rs index 459d9cd..750aa8d 100644 --- a/dust-lang/src/value.rs +++ b/dust-lang/src/value.rs @@ -214,10 +214,10 @@ impl Display for Value { write!(f, ")")?; if let Some(return_type) = return_type { - write!(f, "-> {return_type}")? + write!(f, " -> {return_type}")? } - write!(f, " {{ {body} }}") + write!(f, " {body}") } ValueInner::Structure { name, fields } => { write!(f, "{}\n{{", name.node)?; diff --git a/dust-lang/tests/validation.rs b/dust-lang/tests/validation.rs index d1eb93c..6dbb426 100644 --- a/dust-lang/tests/validation.rs +++ b/dust-lang/tests/validation.rs @@ -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() + }] + ); +}