fix(eval): allow expressions in functions
added: - pass context to function calls fixed: - functions not evaluating expressions inside their params
This commit is contained in:
2 files changed
+33
-25
No files matched your search
+3
-3
@@ -2,7 +2,7 @@ use std::collections::HashMap;
|
||||
|
||||
use crate::math::{lexer, parser, types::Expression};
|
||||
|
||||
type FunctionCallback = Box<dyn Fn(Vec<Expression>) -> Expression>;
|
||||
type FunctionCallback = Box<dyn Fn(&Context, Vec<Expression>) -> Expression>;
|
||||
|
||||
pub struct Context {
|
||||
variables: HashMap<String, Expression>,
|
||||
@@ -26,7 +26,7 @@ impl Context {
|
||||
|
||||
pub fn register_function<F>(&mut self, name: &str, callback: F)
|
||||
where
|
||||
F: Fn(Vec<Expression>) -> Expression + 'static,
|
||||
F: Fn(&Context, Vec<Expression>) -> 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> {
|
||||
|
||||
+30
-22
@@ -8,31 +8,39 @@ use rust_decimal::prelude::ToPrimitive;
|
||||
|
||||
impl Context {
|
||||
pub fn register_builtin_functions(&mut self) {
|
||||
self.register_function("abs", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.abs())
|
||||
self.register_function("abs", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.abs())
|
||||
});
|
||||
self.register_function("sqrt", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.abs().sqrt().unwrap())
|
||||
self.register_function("sqrt", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| {
|
||||
d.abs().sqrt().unwrap()
|
||||
})
|
||||
});
|
||||
self.register_function("sin", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.sin())
|
||||
self.register_function("sin", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.sin())
|
||||
});
|
||||
self.register_function("cos", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.cos())
|
||||
self.register_function("cos", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.cos())
|
||||
});
|
||||
self.register_function("tan", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.tan())
|
||||
self.register_function("tan", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.tan())
|
||||
});
|
||||
self.register_function("asin", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| map_f64(&d, |f| f.asin()))
|
||||
self.register_function("asin", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| {
|
||||
map_f64(&d, |f| f.asin())
|
||||
})
|
||||
});
|
||||
self.register_function("acos", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| map_f64(&d, |f| f.acos()))
|
||||
self.register_function("acos", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| {
|
||||
map_f64(&d, |f| f.acos())
|
||||
})
|
||||
});
|
||||
self.register_function("atan", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| map_f64(&d, |f| f.atan()))
|
||||
self.register_function("atan", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| {
|
||||
map_f64(&d, |f| f.atan())
|
||||
})
|
||||
});
|
||||
self.register_function("round", |params: Vec<Expression>| {
|
||||
self.register_function("round", |ctx, params: Vec<Expression>| {
|
||||
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<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.floor())
|
||||
self.register_function("floor", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.floor())
|
||||
});
|
||||
self.register_function("ceil", |params: Vec<Expression>| {
|
||||
map_decimal(¶ms[0], |d| d.ceil())
|
||||
self.register_function("ceil", |ctx, params: Vec<Expression>| {
|
||||
map_decimal(&ctx.eval_expr(params[0].clone()), |d| d.ceil())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user