51 lines
1.5 KiB
Rust
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))
|
|
}
|
|
}
|