🙃
This commit is contained in:
@@ -19,6 +19,7 @@ pub enum LeadErrCode {
|
||||
Syntax,
|
||||
Server,
|
||||
Unsupported,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
|
||||
@@ -7,6 +7,7 @@ use crate::common::Literal;
|
||||
use crate::grid::Grid;
|
||||
use crate::parser::*;
|
||||
use std::collections::HashSet;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
|
||||
@@ -117,6 +118,15 @@ 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)?,
|
||||
"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())?,
|
||||
"TAN" => eval_single_arg_numeric(args, precs, grid, |x| x.tan(), "TAN".into())?,
|
||||
"ASIN" => eval_single_arg_numeric(args, precs, grid, |x| x.asin(), "ASIN".into())?,
|
||||
"ACOS" => eval_single_arg_numeric(args, precs, grid, |x| x.acos(), "ACOS".into())?,
|
||||
"ATAN" => eval_single_arg_numeric(args, precs, grid, |x| x.atan(), "ATAN".into())?,
|
||||
"PI" => eval_const(args, Eval::Literal(Literal::Number(f64::consts::PI)))?,
|
||||
"TAU" => eval_const(args, Eval::Literal(Literal::Number(f64::consts::TAU)))?,
|
||||
it => {
|
||||
return Err(LeadErr {
|
||||
title: "Evaluation error.".into(),
|
||||
@@ -256,6 +266,49 @@ fn eval_avg(
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_single_arg_numeric(
|
||||
args: &Vec<Expr>,
|
||||
precs: &mut HashSet<CellRef>,
|
||||
grid: Option<&Grid>,
|
||||
func: fn(f64) -> f64,
|
||||
func_name: String,
|
||||
) -> Result<Eval, LeadErr> {
|
||||
if args.len() != 1 {
|
||||
return Err(LeadErr {
|
||||
title: "Evaluation error.".into(),
|
||||
desc: format!("{func_name} function requires a single argument."),
|
||||
code: LeadErrCode::Invalid,
|
||||
});
|
||||
}
|
||||
|
||||
let err = LeadErr {
|
||||
title: "Evaluation error.".into(),
|
||||
desc: format!("{func_name} function requires a numeric argument."),
|
||||
code: LeadErrCode::TypeErr,
|
||||
};
|
||||
|
||||
match evaluate_expr(&args[0], precs, grid)? {
|
||||
Eval::Literal(Literal::Number(num)) => Ok(Eval::Literal(Literal::Number(func(num)))),
|
||||
Eval::CellRef { eval, .. } => match *eval {
|
||||
Eval::Literal(Literal::Number(n)) => Ok(Eval::Literal(Literal::Number(func(n)))),
|
||||
_ => Err(err),
|
||||
},
|
||||
_ => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
fn eval_const(args: &Vec<Expr>, value: Eval) -> Result<Eval, LeadErr> {
|
||||
if args.len() != 0 {
|
||||
return Err(LeadErr {
|
||||
title: "Evaluation error.".into(),
|
||||
desc: format!("PI function requires no arguments."),
|
||||
code: LeadErrCode::Invalid,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn eval_add(lval: &Eval, rval: &Eval) -> Result<Eval, LeadErr> {
|
||||
match (lval, rval) {
|
||||
(Eval::Literal(a), Eval::Literal(b)) => {
|
||||
|
||||
@@ -79,17 +79,23 @@ async fn accept_connection(stream: TcpStream) {
|
||||
}
|
||||
}
|
||||
|
||||
let msg = LeadMsg {
|
||||
cell: None,
|
||||
raw: None,
|
||||
eval: None,
|
||||
bulk_msgs: Some(msgs),
|
||||
msg_type: MsgType::Bulk,
|
||||
};
|
||||
if msgs.len() == 1 {
|
||||
let _ = write
|
||||
.send(serde_json::to_string(&msgs.get(0)).unwrap().into())
|
||||
.await;
|
||||
} else if msgs.len() > 1 {
|
||||
let msg = LeadMsg {
|
||||
cell: None,
|
||||
raw: None,
|
||||
eval: None,
|
||||
bulk_msgs: Some(msgs),
|
||||
msg_type: MsgType::Bulk,
|
||||
};
|
||||
|
||||
let _ = write
|
||||
.send(serde_json::to_string(&msg).unwrap().into())
|
||||
.await;
|
||||
let _ = write
|
||||
.send(serde_json::to_string(&msg).unwrap().into())
|
||||
.await;
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
let res = LeadMsg {
|
||||
|
||||
@@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{cell::CellRef, evaluator::Eval};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum MsgType {
|
||||
Set,
|
||||
@@ -11,7 +11,7 @@ pub enum MsgType {
|
||||
Bulk,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct LeadMsg {
|
||||
pub msg_type: MsgType,
|
||||
pub cell: Option<CellRef>,
|
||||
|
||||
Reference in New Issue
Block a user