This commit is contained in:
2025-09-14 21:04:07 +10:00
parent 15e57d4624
commit 2470f402e9
2 changed files with 92 additions and 2 deletions

View File

@@ -119,7 +119,33 @@ fn evaluate_expr(
}
Expr::Group(g) => evaluate_expr(g, precs, grid)?,
Expr::Function { name, args } => match name.as_str() {
"AVG" => eval_avg(args, precs, grid)?,
// "AVG" => eval_avg(args, precs, grid)?,
"AVG" => eval_numeric_func(
args,
precs,
grid,
|nums| {
let mut res = 0.0;
let mut count = 0;
for num in nums {
res += num;
count += 1;
}
if count == 0 {
Err(LeadErr {
title: "Evaluation error.".into(),
desc: "Attempted to divide by zero.".into(),
code: LeadErrCode::DivZero,
})
} else {
Ok(res / count as f64)
}
},
"AVG".into(),
Some(0f64),
)?,
"EXP" => eval_single_arg_numeric(args, precs, grid, |x| x.exp(), "EXP".into())?,
"SIN" => eval_single_arg_numeric(args, precs, grid, |x| x.sin(), "SIN".into())?,
"COS" => eval_single_arg_numeric(args, precs, grid, |x| x.cos(), "COS".into())?,

View File

@@ -1,4 +1,4 @@
use std::collections::HashSet;
use std::{collections::HashSet, default};
use crate::{
cell::CellRef,
@@ -74,3 +74,67 @@ pub fn eval_n_arg_numeric(
Ok(Eval::Literal(Literal::Number(func(numbers))))
}
pub fn eval_numeric_func(
args: &Vec<Expr>,
precs: &mut HashSet<CellRef>,
grid: Option<&Grid>,
func: fn(Vec<f64>) -> Result<f64, LeadErr>,
func_name: String,
unset_val: Option<f64>,
) -> Result<Eval, LeadErr> {
let mut numeric_args = Vec::new();
for arg in args {
match evaluate_expr(arg, precs, grid)? {
Eval::Literal(Literal::Number(num)) => {
numeric_args.push(num);
}
Eval::Range(range) => {
for cell in range {
let Eval::CellRef { eval, reference: _ } = cell else {
return Err(LeadErr {
title: "Evaluation error.".into(),
desc: format!(
"Found non-cellref in RANGE during {func_name} evaluation."
),
code: LeadErrCode::Server,
});
};
if let Eval::Literal(Literal::Number(num)) = *eval {
numeric_args.push(num);
} else if matches!(*eval, Eval::Unset) {
if let Some(default) = unset_val {
numeric_args.push(default);
} else {
return Err(LeadErr {
title: "Evaluation error.".into(),
desc: format!("{func_name} does not support unset cells."),
code: LeadErrCode::Unsupported,
});
}
} else {
return Err(LeadErr {
title: "Evaluation error.".into(),
desc: format!("Expected numeric types for {func_name} function."),
code: LeadErrCode::Unsupported,
});
}
}
}
_ => {
return Err(LeadErr {
title: "Evaluation error.".into(),
desc: format!("Expected numeric types for {func_name} function."),
code: LeadErrCode::Unsupported,
});
}
}
}
match func(numeric_args) {
Ok(res) => Ok(Eval::Literal(Literal::Number(res))),
Err(e) => Err(e),
}
}