1
0

Implement new math interface for Value

This commit is contained in:
Jeff 2024-02-16 15:37:07 -05:00
parent c82f631524
commit 4b0910a545
8 changed files with 79 additions and 170 deletions

View File

@ -1,5 +1,3 @@
use std::ops::AddAssign;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::{ use crate::{
@ -136,19 +134,19 @@ impl AbstractTree for Assignment {
let new_value = match self.operator { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Some(left) = context.get_value(&self.identifier)? { if let Some(left) = context.get_value(&self.identifier)? {
left.add_assign(right)? left.add(right)?
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound( return Err(RuntimeError::ValidationFailure(
self.identifier.clone(), ValidationError::VariableIdentifierNotFound(self.identifier.clone()),
)); ));
} }
} }
AssignmentOperator::MinusEqual => { AssignmentOperator::MinusEqual => {
if let Some(mut left) = context.get_value(&self.identifier)? { if let Some(left) = context.get_value(&self.identifier)? {
left.sub_assign(right)? left.subtract(right)?
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound( return Err(RuntimeError::ValidationFailure(
self.identifier.clone(), ValidationError::VariableIdentifierNotFound(self.identifier.clone()),
)); ));
} }
} }

View File

@ -139,7 +139,9 @@ impl AbstractTree for FunctionCall {
if let Some(value) = context.get_value(identifier)? { if let Some(value) = context.get_value(identifier)? {
value.clone() value.clone()
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); return Err(RuntimeError::ValidationFailure(
ValidationError::VariableIdentifierNotFound(identifier.clone()),
));
} }
} }
FunctionExpression::FunctionCall(function_call) => { FunctionExpression::FunctionCall(function_call) => {

View File

@ -79,7 +79,9 @@ impl AbstractTree for Identifier {
if let Some(value) = context.get_value(self)? { if let Some(value) = context.get_value(self)? {
Ok(value.clone()) Ok(value.clone())
} else { } else {
Err(RuntimeError::VariableIdentifierNotFound(self.clone())) return Err(RuntimeError::ValidationFailure(
ValidationError::VariableIdentifierNotFound(self.clone()),
));
} }
} }
} }

View File

@ -66,7 +66,9 @@ impl AbstractTree for Index {
if let Some(value) = map.get(identifier) { if let Some(value) = map.get(identifier) {
value value
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); return Err(RuntimeError::ValidationFailure(
ValidationError::VariableIdentifierNotFound(identifier.clone()),
));
} }
} else { } else {
let index_value = self.index.run(source, context)?; let index_value = self.index.run(source, context)?;
@ -75,7 +77,9 @@ impl AbstractTree for Index {
if let Some(value) = map.get(&identifier) { if let Some(value) = map.get(&identifier) {
value value
} else { } else {
return Err(RuntimeError::VariableIdentifierNotFound(identifier.clone())); return Err(RuntimeError::ValidationFailure(
ValidationError::VariableIdentifierNotFound(identifier.clone()),
));
} }
}; };

View File

@ -50,8 +50,8 @@ impl AbstractTree for IndexAssignment {
let index_run = self.index.index.run(source, context)?; let index_run = self.index.index.run(source, context)?;
let expected_identifier = Identifier::new(index_run.as_string()?); let expected_identifier = Identifier::new(index_run.as_string()?);
return Err(RuntimeError::VariableIdentifierNotFound( return Err(RuntimeError::ValidationFailure(
expected_identifier, ValidationError::VariableIdentifierNotFound(expected_identifier),
)); ));
}; };
@ -59,17 +59,17 @@ impl AbstractTree for IndexAssignment {
let new_value = match self.operator { let new_value = match self.operator {
AssignmentOperator::PlusEqual => { AssignmentOperator::PlusEqual => {
if let Some(mut previous_value) = context.get_value(index_identifier)? { if let Some(previous_value) = context.get_value(index_identifier)? {
previous_value += value; previous_value.add(value)?
previous_value
} else { } else {
Value::none() return Err(RuntimeError::ValidationFailure(
ValidationError::VariableIdentifierNotFound(index_identifier.clone()),
));
} }
} }
AssignmentOperator::MinusEqual => { AssignmentOperator::MinusEqual => {
if let Some(mut previous_value) = context.get_value(index_identifier)? { if let Some(previous_value) = context.get_value(index_identifier)? {
previous_value -= value; previous_value.subtract(value)?
previous_value
} else { } else {
Value::none() Value::none()
} }

View File

@ -49,11 +49,11 @@ impl AbstractTree for Math {
let left = self.left.run(source, context)?; let left = self.left.run(source, context)?;
let right = self.right.run(source, context)?; let right = self.right.run(source, context)?;
let value = match self.operator { let value = match self.operator {
MathOperator::Add => left.add_assign(right)?, MathOperator::Add => left.add(right)?,
MathOperator::Subtract => todo!(), MathOperator::Subtract => left.subtract(right)?,
MathOperator::Multiply => todo!(), MathOperator::Multiply => left.multiply(right)?,
MathOperator::Divide => todo!(), MathOperator::Divide => left.divide(right)?,
MathOperator::Modulo => todo!(), MathOperator::Modulo => left.modulo(right)?,
}; };
Ok(value) Ok(value)

View File

@ -7,7 +7,7 @@ use std::{
time, time,
}; };
use crate::{Identifier, Type, Value}; use crate::{Type, Value};
use super::{rw_lock_error::RwLockError, ValidationError}; use super::{rw_lock_error::RwLockError, ValidationError};
@ -105,9 +105,6 @@ pub enum RuntimeError {
Utf8(FromUtf8Error), 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. /// A built-in function was called with the wrong amount of arguments.
ExpectedBuiltInFunctionArgumentAmount { ExpectedBuiltInFunctionArgumentAmount {
function_name: String, function_name: String,

View File

@ -16,7 +16,7 @@ use std::{
convert::TryFrom, convert::TryFrom,
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
marker::PhantomData, marker::PhantomData,
ops::{Add, AddAssign, Div, Mul, RangeInclusive, Rem, Sub, SubAssign}, ops::RangeInclusive,
}; };
pub use self::{ pub use self::{
@ -257,10 +257,11 @@ impl Value {
} }
} }
pub fn add_assign(self, other: Self) -> Result<Value, ValidationError> { /// Return the sum of `self` and `other`.
pub fn add(self, other: Self) -> Result<Value, ValidationError> {
match (self, other) { match (self, other) {
(Value::Float(_), Value::Float(_)) => todo!(), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left + right)),
(Value::Float(_), Value::Integer(_)) => todo!(), (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::Float(right)) => Ok(Value::Float((left as f64) + right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)),
(Value::List(list), value) | (value, Value::List(list)) => { (Value::List(list), value) | (value, Value::List(list)) => {
@ -268,23 +269,54 @@ impl Value {
Ok(Value::List(list)) Ok(Value::List(list))
} }
(Value::Map(_), _) | (_, Value::Map(_)) => todo!(), (Value::String(left), Value::String(right)) => Ok(Value::String(left + &right)),
(Value::String(_), Value::String(_)) => todo!(),
(left, right) => Err(ValidationError::CannotAdd { left, right }), (left, right) => Err(ValidationError::CannotAdd { left, right }),
} }
} }
pub fn sub_assign(self, other: Self) -> Result<Value, ValidationError> { /// Return the difference of `self` and `other`.
pub fn subtract(self, other: Self) -> Result<Value, ValidationError> {
match (self, other) { match (self, other) {
(Value::Float(_), Value::Float(_)) => todo!(), (Value::Float(left), Value::Float(right)) => Ok(Value::Float(left - right)),
(Value::Float(_), Value::Integer(_)) => todo!(), (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::Float(right)) => Ok(Value::Float(left as f64 - right)),
(Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left + right)), (Value::Integer(left), Value::Integer(right)) => Ok(Value::Integer(left - right)),
(Value::Map(_), _) | (_, Value::Map(_)) => todo!(),
(Value::String(_), Value::String(_)) => todo!(),
(left, right) => Err(ValidationError::CannotSubtract { left, right }), (left, right) => Err(ValidationError::CannotSubtract { left, right }),
} }
} }
/// Return the product of `self` and `other`.
pub fn multiply(self, other: Self) -> Result<Value, ValidationError> {
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<Value, ValidationError> {
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<Value, ValidationError> {
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 { impl Default for Value {
@ -293,132 +325,6 @@ impl Default for Value {
} }
} }
impl Add for Value {
type Output = Result<Value, RuntimeError>;
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<Self, RuntimeError>;
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<Self, RuntimeError>;
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<Self, RuntimeError>;
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<Self, RuntimeError>;
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 Eq for Value {}
impl PartialEq for Value { impl PartialEq for Value {