use super::expression::Expression; use super::{complex::Complex, context::Context}; enum FunctionArgumentType { ExpressionArgument(Vec), ValueArgument(Vec), } pub struct FunctionArgument { args: FunctionArgumentType, len: usize, } impl FunctionArgument { pub fn from_expressions(args: Vec) -> Self { Self { len: args.len(), args: FunctionArgumentType::ExpressionArgument(args), } } pub fn from_values(args: Vec) -> Self { Self { len: args.len(), args: FunctionArgumentType::ValueArgument(args), } } pub fn len(&self) -> usize { self.len } pub fn is_empty(&self) -> bool { self.len == 0 } pub fn eval_args(&self, ctx: &Context) -> Result, String> { match &self.args { FunctionArgumentType::ExpressionArgument(args) => { args.iter().map(|a| a.evaluate(ctx)).collect() } FunctionArgumentType::ValueArgument(args) => Ok(args.to_vec()), } } } pub trait Function { fn eval(&self, args: &FunctionArgument, ctx: &Context) -> Result; } #[macro_export] macro_rules! functions { {$($x:expr => $y:expr), *} => { { let mut h : HashMap> = HashMap::new(); $( h.insert($x.to_string(), Arc::new($y)); )* h } }; } // Some default implementations impl Function for T where T: Fn(Complex) -> Complex, { fn eval(&self, args: &FunctionArgument, ctx: &Context) -> Result { if args.len() == 1 { match args.eval_args(ctx) { Ok(args) => Ok(self(args[0])), Err(e) => Err(e), } } else { Err("too many arguments".to_string()) } } } pub struct EmptyFunction {} impl Function for EmptyFunction { fn eval(&self, _args: &FunctionArgument, _ctx: &Context) -> Result { Err("function not implemented in this scope".to_string()) } }