pub mod financial;
pub mod logical;
pub mod math;
pub mod operator;
pub mod statistical;
pub mod text;
use std::collections::HashMap;
use crate::eval::context::Context;
use crate::parser::ast::Expr;
use crate::types::{ErrorKind, Value};
pub struct EvalCtx<'r> {
pub ctx: Context,
pub registry: &'r Registry,
}
impl<'r> EvalCtx<'r> {
pub fn new(ctx: Context, registry: &'r Registry) -> Self {
Self { ctx, registry }
}
}
pub type EagerFn = fn(&[Value]) -> Value;
pub type LazyFn = fn(&[Expr], &mut EvalCtx<'_>) -> Value;
pub enum FunctionKind {
Eager(EagerFn),
Lazy(LazyFn),
}
pub struct Registry {
functions: HashMap<String, FunctionKind>,
}
impl Registry {
pub fn new() -> Self {
let mut r = Self { functions: HashMap::new() };
math::register_math(&mut r);
logical::register_logical(&mut r);
text::register_text(&mut r);
financial::register_financial(&mut r);
statistical::register_statistical(&mut r);
operator::register_operator(&mut r);
r
}
pub fn register_eager(&mut self, name: &str, f: EagerFn) {
self.functions.insert(name.to_uppercase(), FunctionKind::Eager(f));
}
pub fn register_lazy(&mut self, name: &str, f: LazyFn) {
self.functions.insert(name.to_uppercase(), FunctionKind::Lazy(f));
}
pub fn get(&self, name: &str) -> Option<&FunctionKind> {
self.functions.get(&name.to_uppercase())
}
}
impl Default for Registry {
fn default() -> Self {
Self::new()
}
}
pub fn check_arity(args: &[Value], min: usize, max: usize) -> Option<Value> {
if args.len() < min || args.len() > max {
Some(Value::Error(ErrorKind::NA))
} else {
None
}
}
pub fn check_arity_len(count: usize, min: usize, max: usize) -> Option<Value> {
if count < min || count > max {
Some(Value::Error(ErrorKind::NA))
} else {
None
}
}