Acord/core/src/interp/eval/mod.rs

51 lines
1.5 KiB
Rust

mod binop;
mod call;
mod expr;
mod stmt;
use std::rc::Rc;
use crate::interp::ast::Expr;
use crate::interp::builtins;
use crate::interp::hooks::InterpreterHook;
use crate::interp::value::Value;
use crate::interp::{Interpreter, MAX_CALL_DEPTH};
impl Interpreter {
pub(crate) fn eval_call(&mut self, name: &str, args: &[Expr], depth: u32) -> Result<Value, String> {
if depth >= MAX_CALL_DEPTH {
return Err("maximum call depth exceeded".into());
}
if let Some(handler) = self.custom_builtins.get(name).cloned() {
let mut arg_vals = Vec::with_capacity(args.len());
for a in args {
arg_vals.push(self.eval_expr(a, depth)?);
}
return handler(self, &arg_vals);
}
if self.fns.contains_key(name) {
return self.call_user_fn(name, args, depth);
}
if self.solved_fns.contains_key(name) {
return self.call_solved_fn(name, args, depth);
}
let hooks_snapshot: Vec<Rc<dyn InterpreterHook>> = self.hooks.hooks.clone();
for hook in &hooks_snapshot {
if let Some(result) = hook.try_call(self, name, args, depth) {
return result;
}
}
// case-insensitive hardcoded builtin lookup
let canon = name.to_ascii_lowercase();
if let Some(r) = builtins::dispatch(self, &canon, args, depth) {
return r;
}
Err(format!("undefined function '{}'", name))
}
}