Add math-parser library (#2033)

* start of parser

* ops forgot

* reorder files and work on executer

* start of parser

* ops forgot

* reorder files and work on executer

* Cleanup and fix tests

* Integrate into the editor

* added unit checking at parse time

* fix tests

* fix issues

* fix editor intergration

* update pest grammer to support units

* units should be working, need to set up tests to know

* make unit type store exponants as i32

* remove scale, insted just multiply the literal by the scale

* unit now contains empty unit,remove options

* add more tests and implement almost all unary operators

* add evaluation context and variables

* function calling, api might be refined later

* add constants, change function call to not be as built into the parser
and add tests

* add function definitions

* remove meval

* remove raw-rs from workspace

* add support for numberless units

* fix unit handleing logic, add some "unit" tests(haha)

* make it so units cant do implcit mul with idents

* add bench and better tests

* fix editor api

* remove old test

* change hashmap context to use deref

* change constants to use hashmap instad of function

---------

Co-authored-by: hypercube <0hypercube@gmail.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
urisinger
2024-11-21 10:24:01 -08:00
committed by GitHub
co-authored by hypercube Keavon Chambers
parent 51ce51ea8c
commit 9fb494764c
14 changed files with 1260 additions and 94 deletions
+121
View File
@@ -0,0 +1,121 @@
use std::{collections::HashMap, f64::consts::PI};
use lazy_static::lazy_static;
use num_complex::{Complex, ComplexFloat};
use crate::value::{Number, Value};
lazy_static! {
pub static ref DEFAULT_FUNCTIONS: HashMap<&'static str, Box<dyn Fn(&[Value]) -> Option<Value> + Send + Sync>> = {
let mut map: HashMap<&'static str, Box<dyn Fn(&[Value]) -> Option<Value> + Send + Sync>> = HashMap::new();
map.insert(
"sin",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sin()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sin()))),
_ => None,
}),
);
map.insert(
"cos",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.cos()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.cos()))),
_ => None,
}),
);
map.insert(
"tan",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.tan()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.tan()))),
_ => None,
}),
);
map.insert(
"csc",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.sin().recip()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.sin().recip()))),
_ => None,
}),
);
map.insert(
"sec",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.cos().recip()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.cos().recip()))),
_ => None,
}),
);
map.insert(
"cot",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.tan().recip()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.tan().recip()))),
_ => None,
}),
);
map.insert(
"invsin",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.asin()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.asin()))),
_ => None,
}),
);
map.insert(
"invcos",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.acos()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.acos()))),
_ => None,
}),
);
map.insert(
"invtan",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.atan()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.atan()))),
_ => None,
}),
);
map.insert(
"invcsc",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().asin()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().asin()))),
_ => None,
}),
);
map.insert(
"invsec",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real(real.recip().acos()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex(complex.recip().acos()))),
_ => None,
}),
);
map.insert(
"invcot",
Box::new(|values| match values {
[Value::Number(Number::Real(real))] => Some(Value::Number(Number::Real((PI / 2.0 - real).atan()))),
[Value::Number(Number::Complex(complex))] => Some(Value::Number(Number::Complex((Complex::new(PI / 2.0, 0.0) - complex).atan()))),
_ => None,
}),
);
map
};
}