dust/src/abstract_tree/math.rs

112 lines
4.1 KiB
Rust
Raw Normal View History

2024-03-07 11:33:54 +00:00
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
value::ValueInner,
Value,
};
2024-03-08 17:24:11 +00:00
use super::{AbstractTree, Action, Expression, Type};
2024-03-07 11:33:54 +00:00
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
2024-03-08 21:14:47 +00:00
pub enum Math {
Add(Expression, Expression),
Subtract(Expression, Expression),
Multiply(Expression, Expression),
Divide(Expression, Expression),
Modulo(Expression, Expression),
2024-03-07 11:33:54 +00:00
}
2024-03-08 21:14:47 +00:00
impl AbstractTree for Math {
2024-03-07 11:33:54 +00:00
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
match self {
Math::Add(left, _)
| Math::Subtract(left, _)
| Math::Multiply(left, _)
| Math::Divide(left, _)
| Math::Modulo(left, _) => left.expected_type(_context),
}
}
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
match self {
Math::Add(left, right)
| Math::Subtract(left, right)
| Math::Multiply(left, right)
| Math::Divide(left, right)
| Math::Modulo(left, right) => {
let left_type = left.expected_type(context)?;
let right_type = right.expected_type(context)?;
match (left_type, right_type) {
(Type::Integer, Type::Integer)
| (Type::Float, Type::Float)
| (Type::Integer, Type::Float)
| (Type::Float, Type::Integer) => Ok(()),
_ => Err(ValidationError::ExpectedIntegerOrFloat),
}
}
}
}
2024-03-08 17:24:11 +00:00
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let value = match self {
2024-03-07 11:33:54 +00:00
Math::Add(left, right) => {
2024-03-08 17:24:11 +00:00
let left_value = left.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?;
2024-03-07 11:33:54 +00:00
left_value.add(&right_value)?
2024-03-07 11:33:54 +00:00
}
2024-03-07 17:33:30 +00:00
Math::Subtract(left, right) => {
2024-03-08 17:24:11 +00:00
let left_value = left.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?;
2024-03-07 17:33:30 +00:00
left_value.subtract(&right_value)?
2024-03-07 17:33:30 +00:00
}
2024-03-07 11:33:54 +00:00
Math::Multiply(left, right) => {
2024-03-08 17:24:11 +00:00
let left_value = left.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?;
2024-03-07 11:33:54 +00:00
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref())
{
2024-03-08 17:24:11 +00:00
Value::integer(left * right)
2024-03-07 11:33:54 +00:00
} else {
2024-03-08 17:24:11 +00:00
return Err(RuntimeError::ValidationFailure(
2024-03-07 11:33:54 +00:00
ValidationError::ExpectedIntegerOrFloat,
2024-03-08 17:24:11 +00:00
));
2024-03-07 11:33:54 +00:00
}
}
2024-03-07 17:33:30 +00:00
Math::Divide(left, right) => {
2024-03-08 17:24:11 +00:00
let left_value = left.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?;
2024-03-07 17:33:30 +00:00
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref())
{
2024-03-08 17:24:11 +00:00
Value::integer(left / right)
2024-03-07 17:33:30 +00:00
} else {
2024-03-08 17:24:11 +00:00
return Err(RuntimeError::ValidationFailure(
2024-03-07 17:33:30 +00:00
ValidationError::ExpectedIntegerOrFloat,
2024-03-08 17:24:11 +00:00
));
2024-03-07 17:33:30 +00:00
}
}
Math::Modulo(left, right) => {
2024-03-08 17:24:11 +00:00
let left_value = left.run(_context)?.as_return_value()?;
let right_value = right.run(_context)?.as_return_value()?;
2024-03-07 17:33:30 +00:00
if let (ValueInner::Integer(left), ValueInner::Integer(right)) =
(left_value.inner().as_ref(), right_value.inner().as_ref())
{
2024-03-08 17:24:11 +00:00
Value::integer(left % right)
2024-03-07 17:33:30 +00:00
} else {
2024-03-08 17:24:11 +00:00
return Err(RuntimeError::ValidationFailure(
2024-03-07 17:33:30 +00:00
ValidationError::ExpectedIntegerOrFloat,
2024-03-08 17:24:11 +00:00
));
2024-03-07 17:33:30 +00:00
}
}
2024-03-08 17:24:11 +00:00
};
Ok(Action::Return(value))
2024-03-07 11:33:54 +00:00
}
}