You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
2.6 KiB
Rust

use crate::parser::OwnedLiteral;
use std::convert::TryInto;
use std::ops::Add;
#[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<MathNumber> for MathNumber {
type Output = Option<OwnedLiteral>;
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)))
}
}
}
}
/// For math operations that take in integers and return integers
/// (add, subtract, multiply)
pub fn math_ints<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
where
L: Into<i128>,
R: Into<i128>,
F: Fn(i128, i128) -> i128,
{
let result = operation(left.into(), right.into());
std::convert::TryInto::<u64>::try_into(result)
.map(OwnedLiteral::LPositiveInteger)
.ok()
.or(std::convert::TryInto::<i64>::try_into(result)
.map(OwnedLiteral::LNegativeInteger)
.ok())
}
// /// For math operations that take in integers and return integers
// /// (add, subtract, multiply)
// fn math_floats<L, R, F>(left: L, right: R, operation: F) -> Option<OwnedLiteral>
// where
// L: Into<f64>,
// R: Into<f64>,
// F: Fn(f64, f64) -> f64,
// {
// let result = operation(left.into(), right.into());
// std::convert::TryInto::<f64>::try_into(result)
// .map(OwnedLiteral::LFloat)
// .ok()
// }