From 3224c04f72afe9ad2382c09e8f8c48f71b2bbc11 Mon Sep 17 00:00:00 2001 From: Jeff Date: Sun, 17 Mar 2024 01:26:05 -0400 Subject: [PATCH] Fix everything except the parser --- src/abstract_tree/function_call.rs | 2 +- src/abstract_tree/logic.rs | 132 ++++++++++++++++------------- src/abstract_tree/loop.rs | 2 +- src/abstract_tree/statement.rs | 44 +++++----- src/abstract_tree/value_node.rs | 37 +++++--- src/value.rs | 18 ++-- 6 files changed, 131 insertions(+), 104 deletions(-) diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index 3fecf12..a1cb1a7 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -50,6 +50,6 @@ impl AbstractTree for FunctionCall { let function_context = Context::inherit_data_from(context)?; - function.call(arguments, function_context) + function.clone().call(arguments, function_context) } } diff --git a/src/abstract_tree/logic.rs b/src/abstract_tree/logic.rs index 2035b65..f86c598 100644 --- a/src/abstract_tree/logic.rs +++ b/src/abstract_tree/logic.rs @@ -4,19 +4,19 @@ use crate::{ Value, }; -use super::{AbstractTree, Action, Expression, Type}; +use super::{AbstractTree, Action, Expression, Positioned, Type}; #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub enum Logic { - Equal(Expression, Expression), - NotEqual(Expression, Expression), - Greater(Expression, Expression), - Less(Expression, Expression), - GreaterOrEqual(Expression, Expression), - LessOrEqual(Expression, Expression), - And(Expression, Expression), - Or(Expression, Expression), - Not(Expression), + Equal(Positioned, Positioned), + NotEqual(Positioned, Positioned), + Greater(Positioned, Positioned), + Less(Positioned, Positioned), + GreaterOrEqual(Positioned, Positioned), + LessOrEqual(Positioned, Positioned), + And(Positioned, Positioned), + Or(Positioned, Positioned), + Not(Positioned), } impl AbstractTree for Logic { @@ -32,16 +32,22 @@ impl AbstractTree for Logic { | Logic::Less(left, right) | Logic::GreaterOrEqual(left, right) | Logic::LessOrEqual(left, right) => { - let left = left.expected_type(context)?; - let right = right.expected_type(context)?; + let left_type = left.node.expected_type(context)?; + let right_type = right.node.expected_type(context)?; - left.check(&right)?; + left_type + .check(&right_type) + .map_err(|conflict| ValidationError::TypeCheck { + conflict, + actual_position: left.position, + expected_position: right.position, + })?; Ok(()) } Logic::And(left, right) | Logic::Or(left, right) => { - let left = left.expected_type(context)?; - let right = right.expected_type(context)?; + let left = left.node.expected_type(context)?; + let right = right.node.expected_type(context)?; if let (Type::Boolean, Type::Boolean) = (left, right) { Ok(()) @@ -50,7 +56,7 @@ impl AbstractTree for Logic { } } Logic::Not(expression) => { - if let Type::Boolean = expression.expected_type(context)? { + if let Type::Boolean = expression.node.expected_type(context)? { Ok(()) } else { Err(ValidationError::ExpectedBoolean) @@ -62,55 +68,59 @@ impl AbstractTree for Logic { fn run(self, _context: &Context) -> Result { let boolean = match self { Logic::Equal(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left == right } Logic::NotEqual(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left != right } Logic::Greater(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left > right } Logic::Less(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left < right } Logic::GreaterOrEqual(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left >= right } Logic::LessOrEqual(left, right) => { - let left = left.run(_context)?.as_return_value()?; - let right = right.run(_context)?.as_return_value()?; + let left = left.node.run(_context)?.as_return_value()?; + let right = right.node.run(_context)?.as_return_value()?; left <= right } Logic::And(left, right) => { - let left = left.run(_context)?.as_return_value()?.as_boolean()?; - let right = right.run(_context)?.as_return_value()?.as_boolean()?; + let left = left.node.run(_context)?.as_return_value()?.as_boolean()?; + let right = right.node.run(_context)?.as_return_value()?.as_boolean()?; left && right } Logic::Or(left, right) => { - let left = left.run(_context)?.as_return_value()?.as_boolean()?; - let right = right.run(_context)?.as_return_value()?.as_boolean()?; + let left = left.node.run(_context)?.as_return_value()?.as_boolean()?; + let right = right.node.run(_context)?.as_return_value()?.as_boolean()?; left || right } Logic::Not(statement) => { - let boolean = statement.run(_context)?.as_return_value()?.as_boolean()?; + let boolean = statement + .node + .run(_context)? + .as_return_value()? + .as_boolean()?; !boolean } @@ -129,8 +139,8 @@ mod tests { #[test] fn equal() { assert!(Logic::Equal( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -143,8 +153,8 @@ mod tests { #[test] fn not_equal() { assert!(Logic::NotEqual( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(43)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(43)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -157,8 +167,8 @@ mod tests { #[test] fn greater() { assert!(Logic::Greater( - Expression::Value(ValueNode::Integer(43)), - Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(43)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -171,8 +181,8 @@ mod tests { #[test] fn less() { assert!(Logic::Less( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(43)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(43)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -185,8 +195,8 @@ mod tests { #[test] fn greater_or_equal() { assert!(Logic::GreaterOrEqual( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(41)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(41)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -196,8 +206,8 @@ mod tests { .unwrap()); assert!(Logic::GreaterOrEqual( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -210,8 +220,8 @@ mod tests { #[test] fn less_or_equal() { assert!(Logic::LessOrEqual( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(43)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(43)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -221,8 +231,8 @@ mod tests { .unwrap()); assert!(Logic::LessOrEqual( - Expression::Value(ValueNode::Integer(42)), - Expression::Value(ValueNode::Integer(42)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), + Expression::Value(ValueNode::Integer(42)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -235,8 +245,8 @@ mod tests { #[test] fn and() { assert!(Logic::And( - Expression::Value(ValueNode::Boolean(true)), - Expression::Value(ValueNode::Boolean(true)), + Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)), + Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -249,8 +259,8 @@ mod tests { #[test] fn or() { assert!(Logic::Or( - Expression::Value(ValueNode::Boolean(true)), - Expression::Value(ValueNode::Boolean(false)), + Expression::Value(ValueNode::Boolean(true)).positioned((0, 0)), + Expression::Value(ValueNode::Boolean(false)).positioned((0, 0)), ) .run(&Context::new()) .unwrap() @@ -262,12 +272,14 @@ mod tests { #[test] fn not() { - assert!(Logic::Not(Expression::Value(ValueNode::Boolean(false))) - .run(&Context::new()) - .unwrap() - .as_return_value() - .unwrap() - .as_boolean() - .unwrap()) + assert!( + Logic::Not(Expression::Value(ValueNode::Boolean(false)).positioned((0, 0))) + .run(&Context::new()) + .unwrap() + .as_return_value() + .unwrap() + .as_boolean() + .unwrap() + ) } } diff --git a/src/abstract_tree/loop.rs b/src/abstract_tree/loop.rs index e3d4879..f97e31f 100644 --- a/src/abstract_tree/loop.rs +++ b/src/abstract_tree/loop.rs @@ -58,7 +58,7 @@ mod tests { #[test] fn basic_loop() { let result = Loop { - statements: vec![Statement::r#break((0..1).into())], + statements: vec![Statement::Break], } .run(&Context::new()); diff --git a/src/abstract_tree/statement.rs b/src/abstract_tree/statement.rs index ea40868..af8afd6 100644 --- a/src/abstract_tree/statement.rs +++ b/src/abstract_tree/statement.rs @@ -1,5 +1,3 @@ -use chumsky::span::{SimpleSpan, Span}; - use crate::{ context::Context, error::{RuntimeError, ValidationError}, @@ -21,37 +19,37 @@ pub enum Statement { impl AbstractTree for Statement { fn expected_type(&self, _context: &Context) -> Result { match self { - StatementInner::Assignment(assignment) => assignment.expected_type(_context), - StatementInner::Block(block) => block.expected_type(_context), - StatementInner::Break => Ok(Type::None), - StatementInner::Expression(expression) => expression.expected_type(_context), - StatementInner::IfElse(if_else) => if_else.expected_type(_context), - StatementInner::Loop(r#loop) => r#loop.expected_type(_context), - StatementInner::While(r#while) => r#while.expected_type(_context), + Statement::Assignment(assignment) => assignment.expected_type(_context), + Statement::Block(block) => block.expected_type(_context), + Statement::Break => Ok(Type::None), + Statement::Expression(expression) => expression.expected_type(_context), + Statement::IfElse(if_else) => if_else.expected_type(_context), + Statement::Loop(r#loop) => r#loop.expected_type(_context), + Statement::While(r#while) => r#while.expected_type(_context), } } fn validate(&self, _context: &Context) -> Result<(), ValidationError> { match self { - StatementInner::Assignment(assignment) => assignment.validate(_context), - StatementInner::Block(block) => block.validate(_context), - StatementInner::Break => Ok(()), - StatementInner::Expression(expression) => expression.validate(_context), - StatementInner::IfElse(if_else) => if_else.validate(_context), - StatementInner::Loop(r#loop) => r#loop.validate(_context), - StatementInner::While(r#while) => r#while.validate(_context), + Statement::Assignment(assignment) => assignment.validate(_context), + Statement::Block(block) => block.validate(_context), + Statement::Break => Ok(()), + Statement::Expression(expression) => expression.validate(_context), + Statement::IfElse(if_else) => if_else.validate(_context), + Statement::Loop(r#loop) => r#loop.validate(_context), + Statement::While(r#while) => r#while.validate(_context), } } fn run(self, _context: &Context) -> Result { match self { - StatementInner::Assignment(assignment) => assignment.run(_context), - StatementInner::Block(block) => block.run(_context), - StatementInner::Break => Ok(Action::Break), - StatementInner::Expression(expression) => expression.run(_context), - StatementInner::IfElse(if_else) => if_else.run(_context), - StatementInner::Loop(r#loop) => r#loop.run(_context), - StatementInner::While(r#while) => r#while.run(_context), + Statement::Assignment(assignment) => assignment.run(_context), + Statement::Block(block) => block.run(_context), + Statement::Break => Ok(Action::Break), + Statement::Expression(expression) => expression.run(_context), + Statement::IfElse(if_else) => if_else.run(_context), + Statement::Loop(r#loop) => r#loop.run(_context), + Statement::While(r#while) => r#while.run(_context), } } } diff --git a/src/abstract_tree/value_node.rs b/src/abstract_tree/value_node.rs index aeef960..16d7022 100644 --- a/src/abstract_tree/value_node.rs +++ b/src/abstract_tree/value_node.rs @@ -2,11 +2,11 @@ use std::{cmp::Ordering, collections::BTreeMap, ops::Range}; use crate::{ context::Context, - error::{RuntimeError, ValidationError}, + error::{RuntimeError, TypeConflict, ValidationError}, Value, }; -use super::{AbstractTree, Action, Block, Expression, Identifier, Type}; +use super::{AbstractTree, Action, Block, Expression, Identifier, Positioned, Type}; #[derive(Clone, Debug, PartialEq)] pub enum ValueNode { @@ -14,13 +14,13 @@ pub enum ValueNode { Float(f64), Integer(i64), List(Vec), - Map(Vec<(Identifier, Option, Expression)>), + Map(Vec<(Identifier, Option>, Positioned)>), Range(Range), String(String), Function { parameters: Vec<(Identifier, Type)>, - return_type: Type, - body: Block, + return_type: Positioned, + body: Positioned, }, } @@ -52,7 +52,7 @@ impl AbstractTree for ValueNode { .map(|(_, r#type)| r#type) .cloned() .collect(), - return_type: Box::new(return_type.clone()), + return_type: Box::new(return_type.node.clone()), }, }; @@ -63,9 +63,15 @@ impl AbstractTree for ValueNode { if let ValueNode::Map(map_assignments) = self { for (_identifier, r#type, expression) in map_assignments { if let Some(expected_type) = r#type { - let actual_type = expression.expected_type(context)?; + let actual_type = expression.node.expected_type(context)?; - expected_type.check(&actual_type)?; + expected_type.node.check(&actual_type).map_err(|conflict| { + ValidationError::TypeCheck { + conflict, + actual_position: expression.position, + expected_position: expected_type.position, + } + }); } } } @@ -82,11 +88,18 @@ impl AbstractTree for ValueNode { function_context.set_type(identifier.clone(), r#type.clone())?; } - body.validate(&function_context)?; + body.node.validate(&function_context)?; - let actual_return_type = body.expected_type(&function_context)?; + let actual_return_type = body.node.expected_type(&function_context)?; - return_type.check(&actual_return_type)?; + return_type + .node + .check(&actual_return_type) + .map_err(|conflict| ValidationError::TypeCheck { + conflict, + actual_position: body.position, + expected_position: return_type.position, + })?; } Ok(()) @@ -112,7 +125,7 @@ impl AbstractTree for ValueNode { let mut property_map = BTreeMap::new(); for (identifier, _type, expression) in property_list { - let value = expression.run(_context)?.as_return_value()?; + let value = expression.node.run(_context)?.as_return_value()?; property_map.insert(identifier, value); } diff --git a/src/value.rs b/src/value.rs index 018cb70..e53b7ce 100644 --- a/src/value.rs +++ b/src/value.rs @@ -13,7 +13,7 @@ use stanza::{ }; use crate::{ - abstract_tree::{AbstractTree, Action, Block, Identifier, Type}, + abstract_tree::{AbstractTree, Action, Block, Identifier, Positioned, Type}, context::Context, error::{RuntimeError, ValidationError}, }; @@ -54,7 +54,11 @@ impl Value { Value(Arc::new(ValueInner::String(string))) } - pub fn function(parameters: Vec<(Identifier, Type)>, return_type: Type, body: Block) -> Self { + pub fn function( + parameters: Vec<(Identifier, Type)>, + return_type: Positioned, + body: Positioned, + ) -> Self { Value(Arc::new(ValueInner::Function(Function::Parsed( ParsedFunction { parameters, @@ -223,7 +227,7 @@ impl Display for Value { write!(f, "{identifier}: {}", r#type)?; } - write!(f, "): {return_type} {body:?}") + write!(f, "): {} {:?}", return_type.node, body.node) } ValueInner::Function(Function::BuiltIn(built_in_function)) => { write!(f, "{built_in_function}") @@ -306,7 +310,7 @@ pub enum Function { } impl Function { - pub fn call(&self, arguments: Vec, context: Context) -> Result { + pub fn call(self, arguments: Vec, context: Context) -> Result { let action = match self { Function::Parsed(ParsedFunction { parameters, body, .. @@ -315,7 +319,7 @@ impl Function { context.set_value(identifier.clone(), value)?; } - body.clone().run(&context)? + body.node.run(&context)? } Function::BuiltIn(built_in_function) => built_in_function.call(arguments, &context)?, }; @@ -327,8 +331,8 @@ impl Function { #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct ParsedFunction { parameters: Vec<(Identifier, Type)>, - return_type: Type, - body: Block, + return_type: Positioned, + body: Positioned, } #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]