From 65bb2c9d8478cef09efeb0923350007c0815a8e1 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 13 Oct 2023 19:56:57 -0400 Subject: [PATCH] Improve expression implementation --- src/abstract_tree/expression.rs | 41 ++++++++++++++------------ src/abstract_tree/math.rs | 34 +++++++-------------- src/error.rs | 5 +++- src/value/mod.rs | 52 ++++++++++++++++++++++++++++++++- 4 files changed, 87 insertions(+), 45 deletions(-) diff --git a/src/abstract_tree/expression.rs b/src/abstract_tree/expression.rs index 1a69c73..f74858d 100644 --- a/src/abstract_tree/expression.rs +++ b/src/abstract_tree/expression.rs @@ -18,27 +18,30 @@ impl AbstractTree for Expression { fn from_syntax_node(source: &str, node: Node) -> Result { debug_assert_eq!("expression", node.kind()); + for index in 0..node.child_count() { + let child = node.child(index).unwrap(); + let expression = match child.kind() { + "value" => Expression::Value(ValueNode::from_syntax_node(source, child)?), + "identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?), + "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), + "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), + "function_call" => { + Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?) + } + _ => continue, + }; + + return Ok(expression); + } + let child = node.child(0).unwrap(); - let expression = match child.kind() { - "value" => Expression::Value(ValueNode::from_syntax_node(source, child)?), - "identifier" => Self::Identifier(Identifier::from_syntax_node(source, child)?), - "math" => Expression::Math(Box::new(Math::from_syntax_node(source, child)?)), - "logic" => Expression::Logic(Box::new(Logic::from_syntax_node(source, child)?)), - "function_call" => { - Expression::FunctionCall(FunctionCall::from_syntax_node(source, child)?) - } - _ => { - return Err(Error::UnexpectedSyntaxNode { - expected: "value, identifier, math or function_call", - actual: child.kind(), - location: child.start_position(), - relevant_source: source[child.byte_range()].to_string(), - }) - } - }; - - Ok(expression) + Err(Error::UnexpectedSyntaxNode { + expected: "value, identifier, math or function_call", + actual: child.kind(), + location: child.start_position(), + relevant_source: source[child.byte_range()].to_string(), + }) } fn run(&self, source: &str, context: &mut VariableMap) -> Result { diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 076d79a..905a3cc 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -43,31 +43,17 @@ impl AbstractTree for Math { } fn run(&self, source: &str, context: &mut VariableMap) -> Result { - match self.operator { - MathOperator::Add | MathOperator::Subtract | MathOperator::Multiply => { - let left_value = self.left.run(source, context)?.as_int()?; - let right_value = self.right.run(source, context)?.as_int()?; - let outcome = match &self.operator { - MathOperator::Add => left_value + right_value, - MathOperator::Subtract => left_value - right_value, - MathOperator::Multiply => left_value * right_value, - _ => panic!("Unreachable"), - }; + let left = self.left.run(source, context)?; + let right = self.right.run(source, context)?; + let value = match self.operator { + MathOperator::Add => left + right, + MathOperator::Subtract => left - right, + MathOperator::Multiply => left * right, + MathOperator::Divide => left / right, + MathOperator::Modulo => left % right, + }?; - Ok(Value::Integer(outcome)) - } - MathOperator::Divide | MathOperator::Modulo => { - let left_value = self.left.run(source, context)?.as_number()?; - let right_value = self.right.run(source, context)?.as_number()?; - let outcome = match self.operator { - MathOperator::Divide => left_value / right_value, - MathOperator::Modulo => left_value % right_value, - _ => panic!("Unreachable"), - }; - - Ok(Value::Float(outcome)) - } - } + Ok(value) } } diff --git a/src/error.rs b/src/error.rs index cb1eb8b..6f3750e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -277,7 +277,10 @@ impl fmt::Display for Error { actual, location, relevant_source, - } => todo!(), + } => write!( + f, + "Expected syntax node {expected}, but got {actual} at {location}. Code: {relevant_source} ", + ), ExpectedChildNode { empty_node_sexp } => todo!(), WrongColumnAmount { expected, actual } => todo!(), ToolFailure(_) => todo!(), diff --git a/src/value/mod.rs b/src/value/mod.rs index 80e2115..2ca2222 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -16,7 +16,7 @@ use std::{ convert::TryFrom, fmt::{self, Display, Formatter}, marker::PhantomData, - ops::{Add, AddAssign, Sub, SubAssign}, + ops::{Add, AddAssign, Div, Mul, Rem, Sub, SubAssign}, }; pub mod function; @@ -260,6 +260,56 @@ impl Sub for Value { } } +impl Mul for Value { + type Output = Result; + + fn mul(self, other: Self) -> Self::Output { + if self.is_integer() && other.is_integer() { + let left = self.as_int().unwrap(); + let right = other.as_int().unwrap(); + let value = Value::Integer(left.saturating_mul(right)); + + Ok(value) + } else { + let left = self.as_number()?; + let right = other.as_number()?; + let value = Value::Float(left * right); + + Ok(value) + } + } +} + +impl Div for Value { + type Output = Result; + + fn div(self, other: Self) -> Self::Output { + let left = self.as_number()?; + let right = other.as_number()?; + let result = left / right; + + let value = if result % 2.0 == 0.0 { + Value::Integer(result as i64) + } else { + Value::Float(result) + }; + + Ok(value) + } +} + +impl Rem for Value { + type Output = Result; + + fn rem(self, other: Self) -> Self::Output { + let left = self.as_int()?; + let right = other.as_int()?; + let result = left % right; + + Ok(Value::Integer(result)) + } +} + impl AddAssign for Value { fn add_assign(&mut self, other: Self) { match (self, other) {