use std::iter::zip; use std::sync::Arc; use crate::math::{ complex::Complex, context::Context, expression::Expression, operation::Operation, function::{Function, FunctionArgument, EmptyFunction} }; #[derive(Default, Clone)] pub struct ExpressionFunction { expr: Expression, name: String, args: Vec, } impl ExpressionFunction { pub fn from_string(str: String, operations: &Vec) -> Result { let str = str.replace(' ', ""); if let Some((lhs, expr)) = str.split_once('=') { if let Some((name, a)) = lhs.split_once('(') { let args: Vec = a[0..a.len() - 1] .split(',') .map(|s| s.to_string()) .collect(); return Ok(Self { expr: Expression::from_string(expr, operations), name: name.to_string(), args, }) } } Err(()) } pub fn name(&self) -> &str { &self.name } pub fn content(&self) -> &str { &self.expr.content() } } impl Function for ExpressionFunction { fn eval(&self, args: &FunctionArgument, ctx: &Context) -> Result { if args.len() == self.args.len() { let mut nctx = ctx.clone(); let vargs = args.eval_args(ctx)?; for (n, v) in zip(self.args.iter(), vargs.iter()) { nctx.set_variable(n, *v) } nctx.set_function(self.name(), Arc::new(EmptyFunction {})); self.expr.evaluate(&nctx) } else { Err(format!( "{} takes {} parameters", self.name, self.args.len() )) } } }