use crate::{
error::{EggError, EggResult},
expression::{Expression, Function, Value},
scope::Scope,
};
pub static mut EVALUATIONS: u64 = 0;
pub fn evaluate(expr: &Expression, scope: &mut Scope) -> EggResult<Value> {
unsafe { EVALUATIONS += 1 };
match expr {
Expression::Value { value } => Ok(value.clone()),
Expression::Word { name } => scope.get(name.as_str()).ok_or_else(|| EggError::UndefinedBinding(name.clone())).cloned(),
Expression::FnCall { function: identifier, parameters } => match identifier {
Function::Script(name) => {
let idx = scope.get_function(name).ok_or_else(|| EggError::FunctionNotFound(name.clone()))?;
scope.call_function(idx, parameters)
}
Function::Host(op) => {
let op = unsafe { op.as_ref().unwrap_unchecked() };
op.evaluate(parameters, scope)
}
},
}
}