From 29bbcb019d4c47d689b72717e6240c4665149fb7 Mon Sep 17 00:00:00 2001 From: Jeff Date: Wed, 26 Jun 2024 16:24:41 -0400 Subject: [PATCH] Add and pass validation test --- dust-lang/src/abstract_tree/assignment.rs | 40 +-------------- dust-lang/src/abstract_tree/function_call.rs | 16 +++--- dust-lang/src/lib.rs | 6 ++- dust-lang/tests/statements.rs | 2 + dust-lang/tests/validation.rs | 51 ++++++++++++++++++++ dust-lang/tests/variables.rs | 21 -------- 6 files changed, 67 insertions(+), 69 deletions(-) create mode 100644 dust-lang/tests/validation.rs diff --git a/dust-lang/src/abstract_tree/assignment.rs b/dust-lang/src/abstract_tree/assignment.rs index fbc4eec..f4199a1 100644 --- a/dust-lang/src/abstract_tree/assignment.rs +++ b/dust-lang/src/abstract_tree/assignment.rs @@ -9,7 +9,7 @@ use crate::{ Context, Value, }; -use super::{AbstractNode, Evaluation, Expression, Statement, Type, TypeConstructor, WithPosition}; +use super::{AbstractNode, Evaluation, Statement, Type, TypeConstructor, WithPosition}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct Assignment { @@ -54,46 +54,10 @@ impl AbstractNode for Assignment { context.set_type(self.identifier.node.clone(), r#type)?; } else { return Err(ValidationError::CannotAssignToNone( - self.statement.position(), + self.statement.last_evaluated_statement().position(), )); }; - let relevant_statement = self.statement.last_evaluated_statement(); - - if let (Some(constructor), Statement::Expression(Expression::FunctionCall(function_call))) = - (&self.constructor, relevant_statement) - { - let declared_type = constructor.clone().construct(context)?; - let function_type = function_call - .node - .function_expression() - .expected_type(context)?; - - if let Some(Type::Function { - return_type, - type_parameters: Some(type_parameters), - .. - }) = function_type - { - if let Some(Type::Generic { identifier, .. }) = return_type.map(|r#box| *r#box) { - let returned_parameter = type_parameters - .into_iter() - .find(|parameter| parameter == &identifier); - - if let Some(parameter) = returned_parameter { - context.set_type(parameter, declared_type)?; - - return Ok(()); - } - } - } else { - return Err(ValidationError::ExpectedFunction { - actual: function_type.unwrap(), - position: function_call.position, - }); - } - } - Ok(()) } diff --git a/dust-lang/src/abstract_tree/function_call.rs b/dust-lang/src/abstract_tree/function_call.rs index 6033d16..5be7fe1 100644 --- a/dust-lang/src/abstract_tree/function_call.rs +++ b/dust-lang/src/abstract_tree/function_call.rs @@ -132,13 +132,13 @@ impl AbstractNode for FunctionCall { (None, None) => {} } - Ok(()) - } else { - Err(ValidationError::ExpectedFunction { - actual: function_node_type, - position: self.function_expression.position(), - }) + return Ok(()); } + + Err(ValidationError::ExpectedFunction { + actual: function_node_type, + position: self.function_expression.position(), + }) } fn evaluate( @@ -244,12 +244,12 @@ impl AbstractNode for FunctionCall { .map(|option| option.map(|value| Evaluation::Return(value))); } - return Err(RuntimeError::ValidationFailure( + Err(RuntimeError::ValidationFailure( ValidationError::ExpectedFunction { actual: value.r#type(context)?, position: function_position, }, - )); + )) } fn expected_type(&self, context: &Context) -> Result, ValidationError> { diff --git a/dust-lang/src/lib.rs b/dust-lang/src/lib.rs index 852283f..1603baa 100644 --- a/dust-lang/src/lib.rs +++ b/dust-lang/src/lib.rs @@ -12,7 +12,10 @@ use std::{ vec, }; -use abstract_tree::{AbstractTree, Type}; +pub use abstract_tree::Type; +pub use value::Value; + +use abstract_tree::AbstractTree; use ariadne::{Color, Fmt, Label, Report, ReportKind}; use chumsky::prelude::*; use context::Context; @@ -20,7 +23,6 @@ use error::{DustError, RuntimeError, TypeConflict, ValidationError}; use lexer::{lex, Token}; use parser::{parse, parser}; use rayon::prelude::*; -pub use value::Value; pub fn interpret(source_id: &str, source: &str) -> Result, InterpreterError> { let interpreter = Interpreter::new(Context::new(None)); diff --git a/dust-lang/tests/statements.rs b/dust-lang/tests/statements.rs index d9b30c0..429e46b 100644 --- a/dust-lang/tests/statements.rs +++ b/dust-lang/tests/statements.rs @@ -1,3 +1,5 @@ +mod validation; + use dust_lang::*; #[test] diff --git a/dust-lang/tests/validation.rs b/dust-lang/tests/validation.rs new file mode 100644 index 0000000..d1eb93c --- /dev/null +++ b/dust-lang/tests/validation.rs @@ -0,0 +1,51 @@ +use dust_lang::{ + error::{DustError, TypeConflict, ValidationError}, + *, +}; + +#[test] +fn set_variable_with_type_error() { + assert_eq!( + interpret("test", "foobar: str = true") + .unwrap_err() + .errors(), + &vec![DustError::Validation { + error: ValidationError::TypeCheck { + conflict: TypeConflict { + actual: Type::Boolean, + expected: Type::String + }, + actual_position: (14, 18).into(), + expected_position: Some((8, 11).into()) + }, + position: (0, 18).into() + }] + ); +} + +#[test] +fn function_return_type_error() { + assert_eq!( + interpret( + "test", + " + foo = fn () -> str { 'foo' } + + bar: int = 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() + }] + ); +} diff --git a/dust-lang/tests/variables.rs b/dust-lang/tests/variables.rs index cdf8707..3d43721 100644 --- a/dust-lang/tests/variables.rs +++ b/dust-lang/tests/variables.rs @@ -1,7 +1,6 @@ use dust_lang::{ abstract_tree::{Block, Expression, Statement, Type, WithPos}, context::Context, - error::{DustError, TypeConflict, ValidationError}, identifier::Identifier, *, }; @@ -22,26 +21,6 @@ fn set_variable_with_type() { ); } -#[test] -fn set_variable_with_type_error() { - assert_eq!( - interpret("test", "foobar: str = true") - .unwrap_err() - .errors(), - &vec![DustError::Validation { - error: ValidationError::TypeCheck { - conflict: TypeConflict { - actual: Type::Boolean, - expected: Type::String - }, - actual_position: (14, 18).into(), - expected_position: Some((8, 11).into()) - }, - position: (0, 18).into() - }] - ); -} - #[test] fn function_variable() { assert_eq!(