🙃
This commit is contained in:
@@ -119,7 +119,6 @@ fn evaluate_expr(
|
|||||||
}
|
}
|
||||||
Expr::Group(g) => evaluate_expr(g, precs, grid)?,
|
Expr::Group(g) => evaluate_expr(g, precs, grid)?,
|
||||||
Expr::Function { name, args } => match name.as_str() {
|
Expr::Function { name, args } => match name.as_str() {
|
||||||
// "AVG" => eval_avg(args, precs, grid)?,
|
|
||||||
"AVG" => eval_numeric_func(
|
"AVG" => eval_numeric_func(
|
||||||
args,
|
args,
|
||||||
precs,
|
precs,
|
||||||
@@ -128,9 +127,15 @@ fn evaluate_expr(
|
|||||||
let mut res = 0.0;
|
let mut res = 0.0;
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
|
|
||||||
for num in nums {
|
for eval in nums {
|
||||||
res += num;
|
match eval {
|
||||||
count += 1;
|
Eval::Literal(Literal::Number(num)) => {
|
||||||
|
res += num;
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
Eval::Unset => {}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
@@ -144,7 +149,86 @@ fn evaluate_expr(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AVG".into(),
|
"AVG".into(),
|
||||||
Some(0f64),
|
)?,
|
||||||
|
"SUM" => eval_numeric_func(
|
||||||
|
args,
|
||||||
|
precs,
|
||||||
|
grid,
|
||||||
|
|nums| {
|
||||||
|
Ok(nums
|
||||||
|
.iter()
|
||||||
|
.filter_map(|e| {
|
||||||
|
if let Eval::Literal(Literal::Number(n)) = e {
|
||||||
|
Some(n)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sum())
|
||||||
|
},
|
||||||
|
"SUM".into(),
|
||||||
|
)?,
|
||||||
|
"PROD" => eval_numeric_func(
|
||||||
|
args,
|
||||||
|
precs,
|
||||||
|
grid,
|
||||||
|
|nums| {
|
||||||
|
Ok(nums
|
||||||
|
.iter()
|
||||||
|
.filter_map(|e| {
|
||||||
|
if let Eval::Literal(Literal::Number(n)) = e {
|
||||||
|
Some(n)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.product())
|
||||||
|
},
|
||||||
|
"PROD".into(),
|
||||||
|
)?,
|
||||||
|
"MAX" => eval_numeric_func(
|
||||||
|
args,
|
||||||
|
precs,
|
||||||
|
grid,
|
||||||
|
|nums| {
|
||||||
|
nums.iter()
|
||||||
|
.filter_map(|e| {
|
||||||
|
if let Eval::Literal(Literal::Number(n)) = e {
|
||||||
|
Some(*n) // deref to f64
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.max_by(|a, b| a.partial_cmp(b).unwrap())
|
||||||
|
.ok_or(LeadErr {
|
||||||
|
title: "Evaluation error.".into(),
|
||||||
|
desc: "MAX on empty set.".into(),
|
||||||
|
code: LeadErrCode::Unsupported,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"MAX".into(),
|
||||||
|
)?,
|
||||||
|
"MIN" => eval_numeric_func(
|
||||||
|
args,
|
||||||
|
precs,
|
||||||
|
grid,
|
||||||
|
|nums| {
|
||||||
|
nums.iter()
|
||||||
|
.filter_map(|e| {
|
||||||
|
if let Eval::Literal(Literal::Number(n)) = e {
|
||||||
|
Some(*n) // deref to f64
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.min_by(|a, b| a.partial_cmp(b).unwrap())
|
||||||
|
.ok_or(LeadErr {
|
||||||
|
title: "Evaluation error.".into(),
|
||||||
|
desc: "MIN on empty set.".into(),
|
||||||
|
code: LeadErrCode::Unsupported,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"MIN".into(),
|
||||||
)?,
|
)?,
|
||||||
"EXP" => eval_single_arg_numeric(args, precs, grid, |x| x.exp(), "EXP".into())?,
|
"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())?,
|
"SIN" => eval_single_arg_numeric(args, precs, grid, |x| x.sin(), "SIN".into())?,
|
||||||
|
|||||||
@@ -75,24 +75,30 @@ pub fn eval_n_arg_numeric(
|
|||||||
Ok(Eval::Literal(Literal::Number(func(numbers))))
|
Ok(Eval::Literal(Literal::Number(func(numbers))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a utility function that filters out and error handles all non literal numbers or unset
|
||||||
|
// eval types and handles ranges
|
||||||
pub fn eval_numeric_func(
|
pub fn eval_numeric_func(
|
||||||
args: &Vec<Expr>,
|
args: &Vec<Expr>,
|
||||||
precs: &mut HashSet<CellRef>,
|
precs: &mut HashSet<CellRef>,
|
||||||
grid: Option<&Grid>,
|
grid: Option<&Grid>,
|
||||||
func: fn(Vec<f64>) -> Result<f64, LeadErr>,
|
func: fn(Vec<Eval>) -> Result<f64, LeadErr>,
|
||||||
func_name: String,
|
func_name: String,
|
||||||
unset_val: Option<f64>,
|
|
||||||
) -> Result<Eval, LeadErr> {
|
) -> Result<Eval, LeadErr> {
|
||||||
let mut numeric_args = Vec::new();
|
let mut numeric_args = Vec::new();
|
||||||
|
|
||||||
for arg in args {
|
for arg in args {
|
||||||
match evaluate_expr(arg, precs, grid)? {
|
let eval = evaluate_expr(arg, precs, grid)?;
|
||||||
Eval::Literal(Literal::Number(num)) => {
|
|
||||||
numeric_args.push(num);
|
if matches!(eval, Eval::Literal(Literal::Number(_)) | Eval::Unset) {
|
||||||
}
|
numeric_args.push(eval);
|
||||||
Eval::Range(range) => {
|
} else if matches!(eval, Eval::Range(_)) {
|
||||||
|
if let Eval::Range(range) = eval {
|
||||||
for cell in range {
|
for cell in range {
|
||||||
let Eval::CellRef { eval, reference: _ } = cell else {
|
let Eval::CellRef {
|
||||||
|
eval: eval2,
|
||||||
|
reference: _,
|
||||||
|
} = cell
|
||||||
|
else {
|
||||||
return Err(LeadErr {
|
return Err(LeadErr {
|
||||||
title: "Evaluation error.".into(),
|
title: "Evaluation error.".into(),
|
||||||
desc: format!(
|
desc: format!(
|
||||||
@@ -102,18 +108,8 @@ pub fn eval_numeric_func(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Eval::Literal(Literal::Number(num)) = *eval {
|
if matches!(*eval2, Eval::Literal(Literal::Number(_)) | Eval::Unset) {
|
||||||
numeric_args.push(num);
|
numeric_args.push(*eval2);
|
||||||
} 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 {
|
} else {
|
||||||
return Err(LeadErr {
|
return Err(LeadErr {
|
||||||
title: "Evaluation error.".into(),
|
title: "Evaluation error.".into(),
|
||||||
@@ -123,18 +119,15 @@ pub fn eval_numeric_func(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
} else {
|
||||||
return Err(LeadErr {
|
return Err(LeadErr {
|
||||||
title: "Evaluation error.".into(),
|
title: "Evaluation error.".into(),
|
||||||
desc: format!("Expected numeric types for {func_name} function."),
|
desc: format!("Expected numeric types for {func_name} function."),
|
||||||
code: LeadErrCode::Unsupported,
|
code: LeadErrCode::Unsupported,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match func(numeric_args) {
|
let res = func(numeric_args)?;
|
||||||
Ok(res) => Ok(Eval::Literal(Literal::Number(res))),
|
Ok(Eval::Literal(Literal::Number(res)))
|
||||||
Err(e) => Err(e),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,21 +61,21 @@ class Grid {
|
|||||||
|
|
||||||
public setCell(pos: Position | null | undefined) {
|
public setCell(pos: Position | null | undefined) {
|
||||||
if (pos === null || pos === undefined) return;
|
if (pos === null || pos === undefined) return;
|
||||||
let data = this.data[pos.key()];
|
let cell = this.data[pos.key()];
|
||||||
if (data === undefined) return;
|
if (cell === undefined) return;
|
||||||
|
|
||||||
if (data.temp_raw === '') {
|
if (cell.temp_raw === '') {
|
||||||
delete this.data[pos.key()];
|
delete this.data[pos.key()];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.raw = data.temp_raw;
|
cell.raw = cell.temp_raw;
|
||||||
data.eval = data.temp_eval;
|
cell.eval = cell.temp_eval;
|
||||||
|
|
||||||
let msg: LeadMsg = {
|
let msg: LeadMsg = {
|
||||||
msg_type: 'set',
|
msg_type: 'set',
|
||||||
cell: pos.ref(),
|
cell: pos.ref(),
|
||||||
raw: data.temp_raw
|
raw: cell.temp_raw
|
||||||
};
|
};
|
||||||
|
|
||||||
this.socket.send(JSON.stringify(msg));
|
this.socket.send(JSON.stringify(msg));
|
||||||
@@ -178,7 +178,6 @@ class Grid {
|
|||||||
|
|
||||||
let cell = this.getCell(pos);
|
let cell = this.getCell(pos);
|
||||||
if (!cell) return;
|
if (!cell) return;
|
||||||
cell.temp_eval = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public stopEditing(pos: Position | null | undefined) {
|
public stopEditing(pos: Position | null | undefined) {
|
||||||
|
|||||||
Reference in New Issue
Block a user