From 4b0910a5453f95e521bfd7949d361b555cad1fd6 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 16 Feb 2024 15:37:07 -0500 Subject: [PATCH] Implement new math interface for Value --- src/abstract_tree/assignment.rs | 16 +-- src/abstract_tree/function_call.rs | 4 +- src/abstract_tree/identifier.rs | 4 +- src/abstract_tree/index.rs | 8 +- src/abstract_tree/index_assignment.rs | 18 +-- src/abstract_tree/math.rs | 10 +- src/error/runtime_error.rs | 5 +- src/value/mod.rs | 184 +++++++------------------- 8 files changed, 79 insertions(+), 170 deletions(-) diff --git a/src/abstract_tree/assignment.rs b/src/abstract_tree/assignment.rs index ac52999..7171d57 100644 --- a/src/abstract_tree/assignment.rs +++ b/src/abstract_tree/assignment.rs @@ -1,5 +1,3 @@ -use std::ops::AddAssign; - use serde::{Deserialize, Serialize}; use crate::{ @@ -136,19 +134,19 @@ impl AbstractTree for Assignment { let new_value = match self.operator { AssignmentOperator::PlusEqual => { if let Some(left) = context.get_value(&self.identifier)? { - left.add_assign(right)? + left.add(right)? } else { - return Err(RuntimeError::VariableIdentifierNotFound( - self.identifier.clone(), + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(self.identifier.clone()), )); } } AssignmentOperator::MinusEqual => { - if let Some(mut left) = context.get_value(&self.identifier)? { - left.sub_assign(right)? + if let Some(left) = context.get_value(&self.identifier)? { + left.subtract(right)? } else { - return Err(RuntimeError::VariableIdentifierNotFound( - self.identifier.clone(), + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(self.identifier.clone()), )); } } diff --git a/src/abstract_tree/function_call.rs b/src/abstract_tree/function_call.rs index f0d5dc2..8561b5d 100644 --- a/src/abstract_tree/function_call.rs +++ b/src/abstract_tree/function_call.rs @@ -139,7 +139,9 @@ impl AbstractTree for FunctionCall { if let Some(value) = context.get_value(identifier)? { value.clone() } else { - return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(identifier.clone()), + )); } } FunctionExpression::FunctionCall(function_call) => { diff --git a/src/abstract_tree/identifier.rs b/src/abstract_tree/identifier.rs index 0cf5a3e..87700eb 100644 --- a/src/abstract_tree/identifier.rs +++ b/src/abstract_tree/identifier.rs @@ -79,7 +79,9 @@ impl AbstractTree for Identifier { if let Some(value) = context.get_value(self)? { Ok(value.clone()) } else { - Err(RuntimeError::VariableIdentifierNotFound(self.clone())) + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(self.clone()), + )); } } } diff --git a/src/abstract_tree/index.rs b/src/abstract_tree/index.rs index ec9a9cc..0fdd5ed 100644 --- a/src/abstract_tree/index.rs +++ b/src/abstract_tree/index.rs @@ -66,7 +66,9 @@ impl AbstractTree for Index { if let Some(value) = map.get(identifier) { value } else { - return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(identifier.clone()), + )); } } else { let index_value = self.index.run(source, context)?; @@ -75,7 +77,9 @@ impl AbstractTree for Index { if let Some(value) = map.get(&identifier) { value } else { - return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(identifier.clone()), + )); } }; diff --git a/src/abstract_tree/index_assignment.rs b/src/abstract_tree/index_assignment.rs index 052df52..4bfe767 100644 --- a/src/abstract_tree/index_assignment.rs +++ b/src/abstract_tree/index_assignment.rs @@ -50,8 +50,8 @@ impl AbstractTree for IndexAssignment { let index_run = self.index.index.run(source, context)?; let expected_identifier = Identifier::new(index_run.as_string()?); - return Err(RuntimeError::VariableIdentifierNotFound( - expected_identifier, + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(expected_identifier), )); }; @@ -59,17 +59,17 @@ impl AbstractTree for IndexAssignment { let new_value = match self.operator { AssignmentOperator::PlusEqual => { - if let Some(mut previous_value) = context.get_value(index_identifier)? { - previous_value += value; - previous_value + if let Some(previous_value) = context.get_value(index_identifier)? { + previous_value.add(value)? } else { - Value::none() + return Err(RuntimeError::ValidationFailure( + ValidationError::VariableIdentifierNotFound(index_identifier.clone()), + )); } } AssignmentOperator::MinusEqual => { - if let Some(mut previous_value) = context.get_value(index_identifier)? { - previous_value -= value; - previous_value + if let Some(previous_value) = context.get_value(index_identifier)? { + previous_value.subtract(value)? } else { Value::none() } diff --git a/src/abstract_tree/math.rs b/src/abstract_tree/math.rs index 7069d6d..ccc2aa1 100644 --- a/src/abstract_tree/math.rs +++ b/src/abstract_tree/math.rs @@ -49,11 +49,11 @@ impl AbstractTree for Math { let left = self.left.run(source, context)?; let right = self.right.run(source, context)?; let value = match self.operator { - MathOperator::Add => left.add_assign(right)?, - MathOperator::Subtract => todo!(), - MathOperator::Multiply => todo!(), - MathOperator::Divide => todo!(), - MathOperator::Modulo => todo!(), + MathOperator::Add => left.add(right)?, + MathOperator::Subtract => left.subtract(right)?, + MathOperator::Multiply => left.multiply(right)?, + MathOperator::Divide => left.divide(right)?, + MathOperator::Modulo => left.modulo(right)?, }; Ok(value) diff --git a/src/error/runtime_error.rs b/src/error/runtime_error.rs index b60f493..7a483a3 100644 --- a/src/error/runtime_error.rs +++ b/src/error/runtime_error.rs @@ -7,7 +7,7 @@ use std::{ time, }; -use crate::{Identifier, Type, Value}; +use crate::{Type, Value}; use super::{rw_lock_error::RwLockError, ValidationError}; @@ -105,9 +105,6 @@ pub enum RuntimeError { Utf8(FromUtf8Error), - /// Failed to find a variable with a value for this key. - VariableIdentifierNotFound(Identifier), - /// A built-in function was called with the wrong amount of arguments. ExpectedBuiltInFunctionArgumentAmount { function_name: String, diff --git a/src/value/mod.rs b/src/value/mod.rs index 92f6bb4..c481fdf 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, Div, Mul, RangeInclusive, Rem, Sub, SubAssign}, + ops::RangeInclusive, }; pub use self::{ @@ -257,10 +257,11 @@ impl Value { } } - pub fn add_assign(self, other: Self) -> Result { + /// Return the sum of `self` and `other`. + pub fn add(self, other: Self) -> Result { match (self, other) { - (Value::Float(_), Value::Float(_)) => todo!(), - (Value::Float(_), Value::Integer(_)) => todo!(), + (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left + right)), + (Value::Float(left), Value::Integer(right)) => Ok(Value::Float(left + right as f64)), (Value::Integer(left), Value::Float(right)) => Ok(Value::Float((left as f64) + right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)), (Value::List(list), value) | (value, Value::List(list)) => { @@ -268,23 +269,54 @@ impl Value { Ok(Value::List(list)) } - (Value::Map(_), _) | (_, Value::Map(_)) => todo!(), - (Value::String(_), Value::String(_)) => todo!(), + (Value::String(left), Value::String(right)) => Ok(Value::String(left + &right)), (left, right) => Err(ValidationError::CannotAdd { left, right }), } } - pub fn sub_assign(self, other: Self) -> Result { + /// Return the difference of `self` and `other`. + pub fn subtract(self, other: Self) -> Result { match (self, other) { - (Value::Float(_), Value::Float(_)) => todo!(), - (Value::Float(_), Value::Integer(_)) => todo!(), - (Value::Integer(left), Value::Float(right)) => Ok(Value::Float((left as f64) + right)), - (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)), - (Value::Map(_), _) | (_, Value::Map(_)) => todo!(), - (Value::String(_), Value::String(_)) => todo!(), + (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left - right)), + (Value::Float(left), Value::Integer(right)) => Ok(Value::Float(left - right as f64)), + (Value::Integer(left), Value::Float(right)) => Ok(Value::Float(left as f64 - right)), + (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)), (left, right) => Err(ValidationError::CannotSubtract { left, right }), } } + + /// Return the product of `self` and `other`. + pub fn multiply(self, other: Self) -> Result { + match (self, other) { + (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left * right)), + (Value::Float(left), Value::Integer(right)) => Ok(Value::Float(left * right as f64)), + (Value::Integer(left), Value::Float(right)) => Ok(Value::Float(left as f64 * right)), + (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left * right)), + (left, right) => Err(ValidationError::CannotMultiply { left, right }), + } + } + + /// Return the quotient of `self` and `other`. + pub fn divide(self, other: Self) -> Result { + match (self, other) { + (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left / right)), + (Value::Float(left), Value::Integer(right)) => Ok(Value::Float(left / right as f64)), + (Value::Integer(left), Value::Float(right)) => Ok(Value::Float(left as f64 / right)), + (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left / right)), + (left, right) => Err(ValidationError::CannotDivide { left, right }), + } + } + + /// Return the remainder after diving `self` and `other`. + pub fn modulo(self, other: Self) -> Result { + match (self, other) { + (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left % right)), + (Value::Float(left), Value::Integer(right)) => Ok(Value::Float(left % right as f64)), + (Value::Integer(left), Value::Float(right)) => Ok(Value::Float(left as f64 % right)), + (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left % right)), + (left, right) => Err(ValidationError::CannotDivide { left, right }), + } + } } impl Default for Value { @@ -293,132 +325,6 @@ impl Default for Value { } } -impl Add for Value { - type Output = Result; - - fn add(self, other: Self) -> Self::Output { - if let (Ok(left), Ok(right)) = (self.as_integer(), other.as_integer()) { - let (sum, _) = left.overflowing_add(right); - - return Ok(Value::Integer(sum)); - } - - if let (Ok(left), Ok(right)) = (self.as_number(), other.as_number()) { - return Ok(Value::Float(left + right)); - } - - if let (Ok(left), Ok(right)) = (self.as_string(), other.as_string()) { - return Ok(Value::string(left.to_string() + right.as_str())); - } - - if self.is_string() || other.is_string() { - return Ok(Value::string(self.to_string() + &other.to_string())); - } - - let non_number_or_string = if !self.is_number() == !self.is_string() { - self - } else { - other - }; - - Err(RuntimeError::ExpectedNumberOrString { - actual: non_number_or_string, - }) - } -} - -impl Sub for Value { - type Output = Result; - - fn sub(self, other: Self) -> Self::Output { - if let (Ok(left), Ok(right)) = (self.as_integer(), other.as_integer()) { - let (difference, _) = left.overflowing_sub(right); - - return Ok(Value::Integer(difference)); - } - - if let (Ok(left), Ok(right)) = (self.as_number(), other.as_number()) { - return Ok(Value::Float(left - right)); - } - - let non_number = if !self.is_number() { self } else { other }; - - Err(RuntimeError::ExpectedNumber { actual: non_number }) - } -} - -impl Mul for Value { - type Output = Result; - - fn mul(self, other: Self) -> Self::Output { - if let (Ok(left), Ok(right)) = (self.as_integer(), other.as_integer()) { - Ok(Value::Integer(left.saturating_mul(right))) - } else if let (Ok(left), Ok(right)) = (self.as_number(), other.as_number()) { - Ok(Value::Float(left * right)) - } else { - let non_number = if !self.is_number() { self } else { other }; - - Err(RuntimeError::ExpectedNumber { actual: non_number }) - } - } -} - -impl Div for Value { - type Output = Result; - - fn div(self, other: Self) -> Self::Output { - if let (Ok(left), Ok(right)) = (self.as_number(), other.as_number()) { - let divided = left / right; - let is_even = divided % 2.0 == 0.0; - - if self.is_integer() && other.is_integer() && is_even { - Ok(Value::Integer(divided as i64)) - } else { - Ok(Value::Float(divided)) - } - } else { - let non_number = if !self.is_number() { self } else { other }; - - Err(RuntimeError::ExpectedNumber { actual: non_number }) - } - } -} - -impl Rem for Value { - type Output = Result; - - fn rem(self, other: Self) -> Self::Output { - let left = self.as_integer()?; - let right = other.as_integer()?; - let result = left % right; - - Ok(Value::Integer(result)) - } -} - -impl AddAssign for Value { - fn add_assign(&mut self, other: Self) { - match (self, other) { - (Value::Integer(left), Value::Integer(right)) => *left += right, - (Value::Float(left), Value::Float(right)) => *left += right, - (Value::Float(left), Value::Integer(right)) => *left += right as f64, - (Value::String(left), Value::String(right)) => *left += &right, - _ => {} - } - } -} - -impl SubAssign for Value { - fn sub_assign(&mut self, other: Self) { - match (self, other) { - (Value::Integer(left), Value::Integer(right)) => *left -= right, - (Value::Float(left), Value::Float(right)) => *left -= right, - (Value::Float(left), Value::Integer(right)) => *left -= right as f64, - _ => {} - } - } -} - impl Eq for Value {} impl PartialEq for Value {