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 20:24:01 +02:00
committed by GitHub
parent 51ce51ea8c
commit 9fb494764c
14 changed files with 1260 additions and 94 deletions

View File

@@ -0,0 +1,128 @@
use std::f64::consts::PI;
use num_complex::ComplexFloat;
use crate::ast::{BinaryOp, UnaryOp};
pub type Complex = num_complex::Complex<f64>;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Value {
Number(Number),
}
impl Value {
pub fn from_f64(x: f64) -> Self {
Self::Number(Number::Real(x))
}
pub fn as_real(&self) -> Option<f64> {
match self {
Self::Number(Number::Real(val)) => Some(*val),
_ => None,
}
}
}
impl From<f64> for Value {
fn from(x: f64) -> Self {
Self::from_f64(x)
}
}
impl core::fmt::Display for Value {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Value::Number(num) => num.fmt(f),
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Number {
Real(f64),
Complex(Complex),
}
impl std::fmt::Display for Number {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Number::Real(real) => real.fmt(f),
Number::Complex(complex) => complex.fmt(f),
}
}
}
impl Number {
pub fn binary_op(self, op: BinaryOp, other: Number) -> Number {
match (self, other) {
(Number::Real(lhs), Number::Real(rhs)) => {
let result = match op {
BinaryOp::Add => lhs + rhs,
BinaryOp::Sub => lhs - rhs,
BinaryOp::Mul => lhs * rhs,
BinaryOp::Div => lhs / rhs,
BinaryOp::Pow => lhs.powf(rhs),
};
Number::Real(result)
}
(Number::Complex(lhs), Number::Complex(rhs)) => {
let result = match op {
BinaryOp::Add => lhs + rhs,
BinaryOp::Sub => lhs - rhs,
BinaryOp::Mul => lhs * rhs,
BinaryOp::Div => lhs / rhs,
BinaryOp::Pow => lhs.powc(rhs),
};
Number::Complex(result)
}
(Number::Real(lhs), Number::Complex(rhs)) => {
let lhs_complex = Complex::new(lhs, 0.0);
let result = match op {
BinaryOp::Add => lhs_complex + rhs,
BinaryOp::Sub => lhs_complex - rhs,
BinaryOp::Mul => lhs_complex * rhs,
BinaryOp::Div => lhs_complex / rhs,
BinaryOp::Pow => lhs_complex.powc(rhs),
};
Number::Complex(result)
}
(Number::Complex(lhs), Number::Real(rhs)) => {
let rhs_complex = Complex::new(rhs, 0.0);
let result = match op {
BinaryOp::Add => lhs + rhs_complex,
BinaryOp::Sub => lhs - rhs_complex,
BinaryOp::Mul => lhs * rhs_complex,
BinaryOp::Div => lhs / rhs_complex,
BinaryOp::Pow => lhs.powf(rhs),
};
Number::Complex(result)
}
}
}
pub fn unary_op(self, op: UnaryOp) -> Number {
match self {
Number::Real(real) => match op {
UnaryOp::Neg => Number::Real(-real),
UnaryOp::Sqrt => Number::Real(real.sqrt()),
UnaryOp::Fac => todo!("Implement factorial"),
},
Number::Complex(complex) => match op {
UnaryOp::Neg => Number::Complex(-complex),
UnaryOp::Sqrt => Number::Complex(complex.sqrt()),
UnaryOp::Fac => todo!("Implement factorial"),
},
}
}
pub fn from_f64(x: f64) -> Self {
Self::Real(x)
}
}