dust/src/abstract_tree/if_else.rs

97 lines
2.5 KiB
Rust
Raw Normal View History

2024-03-08 19:01:05 +00:00
use crate::{
context::Context,
error::{RuntimeError, ValidationError},
};
use super::{AbstractTree, Action, Expression, Statement, Type};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
2024-03-08 21:14:47 +00:00
pub struct IfElse {
if_expression: Expression,
if_statement: Box<Statement>,
else_statement: Option<Box<Statement>>,
2024-03-08 19:01:05 +00:00
}
2024-03-08 21:14:47 +00:00
impl IfElse {
2024-03-08 19:01:05 +00:00
pub fn new(
2024-03-08 21:14:47 +00:00
if_expression: Expression,
if_statement: Statement,
else_statement: Option<Statement>,
2024-03-08 19:01:05 +00:00
) -> Self {
Self {
if_expression,
if_statement: Box::new(if_statement),
else_statement: else_statement.map(|statement| Box::new(statement)),
}
}
}
2024-03-08 21:14:47 +00:00
impl AbstractTree for IfElse {
2024-03-08 19:01:05 +00:00
fn expected_type(&self, _context: &Context) -> Result<Type, ValidationError> {
2024-03-08 19:29:53 +00:00
Ok(Type::None)
2024-03-08 19:01:05 +00:00
}
fn validate(&self, _context: &Context) -> Result<(), ValidationError> {
2024-03-08 19:29:53 +00:00
if let Type::Boolean = self.if_expression.expected_type(_context)? {
Ok(())
} else {
Err(ValidationError::ExpectedBoolean)
}
2024-03-08 19:01:05 +00:00
}
fn run(self, _context: &Context) -> Result<Action, RuntimeError> {
let if_boolean = self
.if_expression
.run(_context)?
.as_return_value()?
.as_boolean()?;
if if_boolean {
self.if_statement.run(_context)
} else if let Some(else_statement) = self.else_statement {
else_statement.run(_context)
} else {
Ok(Action::None)
}
}
}
#[cfg(test)]
mod tests {
use crate::{
abstract_tree::{Action, ValueNode},
context::Context,
Value,
};
use super::*;
#[test]
fn simple_if() {
assert_eq!(
IfElse::new(
Expression::Value(ValueNode::Boolean(true)),
2024-03-08 21:14:47 +00:00
Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))),
2024-03-08 19:01:05 +00:00
None
)
.run(&Context::new()),
Ok(Action::Return(Value::string("foo")))
)
}
#[test]
fn simple_if_else() {
assert_eq!(
IfElse::new(
Expression::Value(ValueNode::Boolean(false)),
2024-03-08 21:14:47 +00:00
Statement::Expression(Expression::Value(ValueNode::String("foo".to_string()))),
2024-03-08 19:01:05 +00:00
Some(Statement::Expression(Expression::Value(ValueNode::String(
2024-03-08 21:14:47 +00:00
"bar".to_string()
2024-03-08 19:01:05 +00:00
))))
)
.run(&Context::new()),
Ok(Action::Return(Value::string("bar")))
)
}
}