1
0
dust/src/abstract_tree/logic.rs

274 lines
7.6 KiB
Rust
Raw Normal View History

use crate::{
context::Context,
error::{RuntimeError, ValidationError},
Value,
};
2024-02-25 18:49:26 +00:00
2024-03-08 17:24:11 +00:00
use super::{AbstractTree, Action, Expression, Type};
2024-02-25 18:49:26 +00:00
2024-02-25 19:26:22 +00:00
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
2024-02-26 21:27:01 +00:00
pub enum Logic<'src> {
Equal(Expression<'src>, Expression<'src>),
NotEqual(Expression<'src>, Expression<'src>),
Greater(Expression<'src>, Expression<'src>),
Less(Expression<'src>, Expression<'src>),
GreaterOrEqual(Expression<'src>, Expression<'src>),
LessOrEqual(Expression<'src>, Expression<'src>),
And(Expression<'src>, Expression<'src>),
Or(Expression<'src>, Expression<'src>),
Not(Expression<'src>),
2024-02-25 18:49:26 +00:00
}
2024-02-26 21:27:01 +00:00
impl<'src> AbstractTree for Logic<'src> {
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
2024-03-07 03:15:35 +00:00
Ok(Type::Boolean)
}
2024-03-07 03:15:35 +00:00
fn validate(&self, context: &Context) -> Result<(), ValidationError> {
match self {
Logic::Equal(left, right)
| Logic::NotEqual(left, right)
| Logic::Greater(left, right)
| Logic::Less(left, right)
| Logic::GreaterOrEqual(left, right)
| Logic::LessOrEqual(left, right) => {
let left = left.expected_type(context)?;
let right = right.expected_type(context)?;
left.check(&right)?;
Ok(())
}
Logic::And(left, right) | Logic::Or(left, right) => {
let left = left.expected_type(context)?;
let right = right.expected_type(context)?;
if let (Type::Boolean, Type::Boolean) = (left, right) {
Ok(())
} else {
Err(ValidationError::ExpectedBoolean)
}
}
Logic::Not(expression) => {
if let Type::Boolean = expression.expected_type(context)? {
Ok(())
} else {
Err(ValidationError::ExpectedBoolean)
}
}
}
}
2024-03-08 17:24:11 +00:00
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
2024-02-25 19:26:22 +00:00
let boolean = match self {
2024-03-08 17:24:11 +00:00
Logic::Equal(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left == right
}
Logic::NotEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left != right
}
Logic::Greater(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left > right
}
Logic::Less(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left < right
}
Logic::GreaterOrEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left >= right
}
Logic::LessOrEqual(left, right) => {
let left = left.run(_context)?.as_return_value()?;
let right = right.run(_context)?.as_return_value()?;
left <= right
}
2024-02-25 19:26:22 +00:00
Logic::And(left, right) => {
2024-03-08 17:24:11 +00:00
let left = left.run(_context)?.as_return_value()?.as_boolean()?;
let right = right.run(_context)?.as_return_value()?.as_boolean()?;
left && right
2024-02-25 19:26:22 +00:00
}
Logic::Or(left, right) => {
2024-03-08 17:24:11 +00:00
let left = left.run(_context)?.as_return_value()?.as_boolean()?;
let right = right.run(_context)?.as_return_value()?.as_boolean()?;
left || right
}
Logic::Not(statement) => {
let boolean = statement.run(_context)?.as_return_value()?.as_boolean()?;
!boolean
2024-02-25 19:26:22 +00:00
}
};
2024-03-08 17:24:11 +00:00
Ok(Action::Return(Value::boolean(boolean)))
2024-02-25 19:26:22 +00:00
}
}
#[cfg(test)]
mod tests {
2024-02-26 21:27:01 +00:00
use crate::abstract_tree::{Expression, ValueNode};
2024-02-25 19:26:22 +00:00
use super::*;
#[test]
fn equal() {
assert!(Logic::Equal(
2024-02-26 21:27:01 +00:00
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(42)),
2024-02-25 19:26:22 +00:00
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-25 19:26:22 +00:00
.as_boolean()
.unwrap())
2024-02-25 18:49:26 +00:00
}
2024-02-28 23:36:47 +00:00
#[test]
fn not_equal() {
assert!(Logic::NotEqual(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(43)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn greater() {
assert!(Logic::Greater(
Expression::Value(ValueNode::Integer(43)),
Expression::Value(ValueNode::Integer(42)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn less() {
assert!(Logic::Less(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(43)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn greater_or_equal() {
assert!(Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(41)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap());
assert!(Logic::GreaterOrEqual(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(42)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn less_or_equal() {
assert!(Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(43)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap());
assert!(Logic::LessOrEqual(
Expression::Value(ValueNode::Integer(42)),
Expression::Value(ValueNode::Integer(42)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn and() {
assert!(Logic::And(
Expression::Value(ValueNode::Boolean(true)),
Expression::Value(ValueNode::Boolean(true)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn or() {
assert!(Logic::Or(
Expression::Value(ValueNode::Boolean(true)),
Expression::Value(ValueNode::Boolean(false)),
)
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
#[test]
fn not() {
assert!(Logic::Not(Expression::Value(ValueNode::Boolean(false)))
.run(&Context::new())
.unwrap()
2024-03-08 17:24:11 +00:00
.as_return_value()
.unwrap()
2024-02-28 23:36:47 +00:00
.as_boolean()
.unwrap())
}
2024-02-25 18:49:26 +00:00
}