use mathexpr::Expression as MathExpr;
use crate::value::Value;
pub(super) fn evaluate_math_expr_internal(expr_string: &str, var_values: &[f64]) -> Value {
let parsed = match MathExpr::parse(expr_string) {
Ok(p) => p,
Err(_) => return Value::Null,
};
static VAR_NAMES: &[&str] = &["a", "b", "c", "d", "e", "f", "g", "h"];
let uses_current = {
let test_compile = parsed.clone().compile(&[]);
test_compile.is_ok()
&& test_compile
.as_ref()
.map(|c| c.uses_current_value())
.unwrap_or(false)
&& var_values.len() <= 1
};
if uses_current && !var_values.is_empty() {
let compiled = match parsed.compile(&[]) {
Ok(c) => c,
Err(_) => return Value::Null,
};
let result = compiled.eval_with_current(var_values[0], &[]);
return match result {
Ok(r) if !r.is_nan() && !r.is_infinite() => Value::Float(r),
_ => Value::Null,
};
}
let var_names: Vec<&str> = VAR_NAMES.iter().take(var_values.len()).copied().collect();
let compiled = match parsed.compile(&var_names) {
Ok(c) => c,
Err(_) => return Value::Null,
};
let result = if var_values.is_empty() {
compiled.eval(&[])
} else if compiled.uses_current_value() {
compiled.eval_with_current(var_values[0], &var_values[1..])
} else {
compiled.eval(var_values)
};
match result {
Ok(r) if !r.is_nan() && !r.is_infinite() => Value::Float(r),
_ => Value::Null,
}
}