mod binary;
mod unary;
use crate::compiler::expr::Expr;
use crate::error::{DialogueError, Result};
use crate::value::{Value, VariableStorage};
pub fn eval<S, F>(expr: &Expr, storage: &S, fns: &F) -> Result<Value>
where
S: VariableStorage,
F: Fn(&str, Vec<Value>) -> Result<Value>,
{
match expr {
Expr::Number(n) => Ok(Value::Number(*n)),
Expr::Text(s) => Ok(Value::Text(s.clone())),
Expr::Bool(b) => Ok(Value::Bool(*b)),
Expr::Var(name) => storage
.get_ref(name)
.map(std::borrow::Cow::into_owned)
.ok_or_else(|| DialogueError::UndefinedVariable(name.clone())),
Expr::Call { name, args } => {
let evaluated: Result<Vec<Value>> =
args.iter().map(|a| eval(a, storage, fns)).collect();
fns(name, evaluated?)
}
Expr::Unary { op, expr } => unary::eval_unary(*op, expr, storage, fns),
Expr::Binary { left, op, right } => binary::eval_binary(left, *op, right, storage, fns),
}
}
#[cfg(test)]
#[path = "eval_tests.rs"]
mod tests;