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()),
|
2024-03-08 21:22:24 +00:00
|
|
|
Ok(Action::Return(Value::string("foo".to_string())))
|
2024-03-08 19:01:05 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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()),
|
2024-03-08 21:22:24 +00:00
|
|
|
Ok(Action::Return(Value::string("bar".to_string())))
|
2024-03-08 19:01:05 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|