Move MathNumber into the library.

While this will be used for the OwnedLiterals since they must always exhibit the original DustJS behavior, I am going to keep exposing separate math functions for ContextElement instead of simply requiring them to implement Into<MathNumber> since people might want to implement math in unusual ways with unusual types.
This commit is contained in:
Tom Alexander
2020-06-13 19:13:02 -04:00
parent d9ce011113
commit d6ad7c28f3
4 changed files with 86 additions and 125 deletions

View File

@@ -7,6 +7,7 @@ use crate::renderer::context_element::CompareContextElement;
use crate::renderer::context_element::ContextElement;
use crate::renderer::context_element::IceResult;
use crate::renderer::context_element::IntoContextElement;
use crate::renderer::math::MathNumber;
use crate::renderer::walking::walk_path;
use crate::renderer::DustRenderer;
use crate::renderer::Loopable;
@@ -18,7 +19,6 @@ use crate::renderer::Walkable;
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::convert::TryInto;
#[derive(Debug)]
pub struct ParametersContext<'a> {
@@ -334,85 +334,12 @@ impl CompareContextElement for OwnedLiteral {
// type.
match other.to_any().downcast_ref::<Self>() {
None => other.math_add(self),
Some(other_literal) => {
match (self, other_literal) {
(OwnedLiteral::LString(_), _) | (_, OwnedLiteral::LString(_)) => None,
(
OwnedLiteral::LPositiveInteger(self_num),
OwnedLiteral::LPositiveInteger(other_num),
) => math_ints(*self_num, *other_num, std::ops::Add::add)
.map(IceResult::from_owned),
(
OwnedLiteral::LNegativeInteger(self_num),
OwnedLiteral::LNegativeInteger(other_num),
) => math_ints(*self_num, *other_num, std::ops::Add::add)
.map(IceResult::from_owned),
(
OwnedLiteral::LPositiveInteger(self_num),
OwnedLiteral::LNegativeInteger(other_num),
) => math_ints(*self_num, *other_num, std::ops::Add::add)
.map(IceResult::from_owned),
(
OwnedLiteral::LNegativeInteger(self_num),
OwnedLiteral::LPositiveInteger(other_num),
) => math_ints(*self_num, *other_num, std::ops::Add::add)
.map(IceResult::from_owned),
(OwnedLiteral::LFloat(self_num), OwnedLiteral::LFloat(other_num)) => Some(
IceResult::from_owned(OwnedLiteral::LFloat(self_num + other_num)),
),
(OwnedLiteral::LFloat(self_num), OwnedLiteral::LPositiveInteger(other_num)) => {
Some(IceResult::from_owned(OwnedLiteral::LFloat(
self_num + (*other_num as f64),
)))
}
(OwnedLiteral::LPositiveInteger(self_num), OwnedLiteral::LFloat(other_num)) => {
Some(IceResult::from_owned(OwnedLiteral::LFloat(
(*self_num as f64) + other_num,
)))
}
(OwnedLiteral::LFloat(self_num), OwnedLiteral::LNegativeInteger(other_num)) => {
Some(IceResult::from_owned(OwnedLiteral::LFloat(
self_num + (*other_num as f64),
)))
}
(OwnedLiteral::LNegativeInteger(self_num), OwnedLiteral::LFloat(other_num)) => {
Some(IceResult::from_owned(OwnedLiteral::LFloat(
(*self_num as f64) + other_num,
)))
}
}
}
Some(other_literal) => match (self, other_literal) {
(OwnedLiteral::LString(_), _) | (_, OwnedLiteral::LString(_)) => None,
(_, _) => (std::convert::Into::<MathNumber>::into(self)
+ std::convert::Into::<MathNumber>::into(other_literal))
.map(IceResult::from_owned),
},
}
}
}
/// 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()
// }