use crate::parser::OwnedLiteral; use std::convert::TryInto; use std::ops::Add; use std::ops::Div; use std::ops::Mul; use std::ops::Rem; use std::ops::Sub; #[derive(Debug)] pub enum MathNumber { Integer(i128), Decimal(f64), Failure, } impl From<&OwnedLiteral> for MathNumber { fn from(original: &OwnedLiteral) -> Self { match original { OwnedLiteral::LString(_) => panic!("Strings should not be cast to numbers for math"), OwnedLiteral::LPositiveInteger(num) => { return MathNumber::Integer((*num).try_into().unwrap()) } OwnedLiteral::LNegativeInteger(num) => return MathNumber::Integer((*num).into()), OwnedLiteral::LFloat(num) => return MathNumber::Decimal(*num), } } } impl Add for MathNumber { type Output = Option; fn add(self, other: MathNumber) -> Self::Output { match (self, other) { (MathNumber::Failure, _) | (_, MathNumber::Failure) => None, (MathNumber::Integer(self_num), MathNumber::Integer(other_num)) => { math_ints(self_num, other_num, std::ops::Add::add) } (MathNumber::Decimal(self_num), MathNumber::Decimal(other_num)) => { Some(OwnedLiteral::LFloat(self_num + other_num)) } (MathNumber::Integer(self_num), MathNumber::Decimal(other_num)) => { Some(OwnedLiteral::LFloat((self_num as f64) + other_num)) } (MathNumber::Decimal(self_num), MathNumber::Integer(other_num)) => { Some(OwnedLiteral::LFloat(self_num + (other_num as f64))) } } } } impl Sub for MathNumber { type Output = Option; fn sub(self, other: MathNumber) -> Self::Output { todo!() } } impl Mul for MathNumber { type Output = Option; fn mul(self, other: MathNumber) -> Self::Output { todo!() } } impl Div for MathNumber { type Output = Option; fn div(self, other: MathNumber) -> Self::Output { todo!() } } impl Rem for MathNumber { type Output = Option; fn rem(self, other: MathNumber) -> Self::Output { todo!() } } impl MathNumber { fn math_abs(&self) -> Option { todo!() } fn math_floor(&self) -> Option { todo!() } fn math_ceil(&self) -> Option { todo!() } } /// For math operations that take in integers and return integers /// (add, subtract, multiply) pub fn math_ints(left: L, right: R, operation: F) -> Option where L: Into, R: Into, F: Fn(i128, i128) -> i128, { let result = operation(left.into(), right.into()); std::convert::TryInto::::try_into(result) .map(OwnedLiteral::LPositiveInteger) .ok() .or(std::convert::TryInto::::try_into(result) .map(OwnedLiteral::LNegativeInteger) .ok()) } // /// For math operations that take in integers and return integers // /// (add, subtract, multiply) // fn math_floats(left: L, right: R, operation: F) -> Option // where // L: Into, // R: Into, // F: Fn(f64, f64) -> f64, // { // let result = operation(left.into(), right.into()); // std::convert::TryInto::::try_into(result) // .map(OwnedLiteral::LFloat) // .ok() // }