Implement new math interface for Value
This commit is contained in:
parent
c82f631524
commit
4b0910a545
@ -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()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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) => {
|
||||||
|
@ -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()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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()
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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,
|
||||||
|
184
src/value/mod.rs
184
src/value/mod.rs
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user