From 52bae6b03460883ddf6f7fd533b3080c1a13b14d Mon Sep 17 00:00:00 2001 From: ozzy <2+ozzy@noreply.localhost> Date: Mon, 28 Sep 2026 20:32:43 -0500 Subject: [PATCH] fix(eval): allow expressions in functions added: - pass context to function calls fixed: - functions not evaluating expressions inside their params --- src/math/context.rs | 6 ++--- src/math/functions.rs | 52 +++++++++++++++++++++++++------------------ 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/math/context.rs b/src/math/context.rs index caabdcc..bee8d49 100644 --- a/src/math/context.rs +++ b/src/math/context.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use crate::math::{lexer, parser, types::Expression}; -type FunctionCallback = Box) -> Expression>; +type FunctionCallback = Box) -> Expression>; pub struct Context { variables: HashMap, @@ -26,7 +26,7 @@ impl Context { pub fn register_function(&mut self, name: &str, callback: F) where - F: Fn(Vec) -> Expression + 'static, + F: Fn(&Context, Vec) -> Expression + 'static, { self.functions.insert(name.to_owned(), Box::new(callback)); } @@ -38,7 +38,7 @@ impl Context { } let func = func.unwrap(); - func(params) + func(self, params) } pub fn get_variable(&self, name: &str) -> Option<&Expression> { diff --git a/src/math/functions.rs b/src/math/functions.rs index b69dc94..d94023e 100644 --- a/src/math/functions.rs +++ b/src/math/functions.rs @@ -8,31 +8,39 @@ use rust_decimal::prelude::ToPrimitive; impl Context { pub fn register_builtin_functions(&mut self) { - self.register_function("abs", |params: Vec| { - map_decimal(¶ms[0], |d| d.abs()) + self.register_function("abs", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.abs()) }); - self.register_function("sqrt", |params: Vec| { - map_decimal(¶ms[0], |d| d.abs().sqrt().unwrap()) + self.register_function("sqrt", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| { + d.abs().sqrt().unwrap() + }) }); - self.register_function("sin", |params: Vec| { - map_decimal(¶ms[0], |d| d.sin()) + self.register_function("sin", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.sin()) }); - self.register_function("cos", |params: Vec| { - map_decimal(¶ms[0], |d| d.cos()) + self.register_function("cos", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.cos()) }); - self.register_function("tan", |params: Vec| { - map_decimal(¶ms[0], |d| d.tan()) + self.register_function("tan", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.tan()) }); - self.register_function("asin", |params: Vec| { - map_decimal(¶ms[0], |d| map_f64(&d, |f| f.asin())) + self.register_function("asin", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| { + map_f64(&d, |f| f.asin()) + }) }); - self.register_function("acos", |params: Vec| { - map_decimal(¶ms[0], |d| map_f64(&d, |f| f.acos())) + self.register_function("acos", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| { + map_f64(&d, |f| f.acos()) + }) }); - self.register_function("atan", |params: Vec| { - map_decimal(¶ms[0], |d| map_f64(&d, |f| f.atan())) + self.register_function("atan", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| { + map_f64(&d, |f| f.atan()) + }) }); - self.register_function("round", |params: Vec| { + self.register_function("round", |ctx, params: Vec| { let decimal = if params.len() == 2 { if let Some(d) = get_decimal(¶ms[1]) { d @@ -45,15 +53,15 @@ impl Context { .to_u32() .expect("unable to parse decimal number"); - map_decimal(¶ms[0], |d| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| { d.round_dp_with_strategy(decimal, RoundingStrategy::MidpointAwayFromZero) }) }); - self.register_function("floor", |params: Vec| { - map_decimal(¶ms[0], |d| d.floor()) + self.register_function("floor", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.floor()) }); - self.register_function("ceil", |params: Vec| { - map_decimal(¶ms[0], |d| d.ceil()) + self.register_function("ceil", |ctx, params: Vec| { + map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.ceil()) }); } }