Implement addition for OwnedLiterals.
This commit is contained in:
parent
8ef3949a65
commit
db11677b22
@ -8,6 +8,7 @@ use renderer::compile_template;
|
|||||||
use renderer::CompileError;
|
use renderer::CompileError;
|
||||||
use renderer::ContextElement;
|
use renderer::ContextElement;
|
||||||
use renderer::DustRenderer;
|
use renderer::DustRenderer;
|
||||||
|
use renderer::IceResult;
|
||||||
use renderer::IntoContextElement;
|
use renderer::IntoContextElement;
|
||||||
use renderer::Loopable;
|
use renderer::Loopable;
|
||||||
use renderer::RenderError;
|
use renderer::RenderError;
|
||||||
@ -387,6 +388,10 @@ impl CompareContextElement for serde_json::Value {
|
|||||||
_ => panic!("Unimplemented comparison type."),
|
_ => panic!("Unimplemented comparison type."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn math_add<'a>(&self, other: &dyn ContextElement) -> Option<IceResult<'a>> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -4,6 +4,7 @@ use crate::renderer::errors::RenderError;
|
|||||||
use crate::renderer::errors::WalkError;
|
use crate::renderer::errors::WalkError;
|
||||||
use crate::renderer::DustRenderer;
|
use crate::renderer::DustRenderer;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::ops::Add;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::{cmp::Ordering, fmt::Debug};
|
use std::{cmp::Ordering, fmt::Debug};
|
||||||
|
|
||||||
@ -61,6 +62,8 @@ pub trait CompareContextElement: CastToAny {
|
|||||||
fn equals(&self, other: &dyn ContextElement) -> bool;
|
fn equals(&self, other: &dyn ContextElement) -> bool;
|
||||||
|
|
||||||
fn partial_compare(&self, other: &dyn ContextElement) -> Option<Ordering>;
|
fn partial_compare(&self, other: &dyn ContextElement) -> Option<Ordering>;
|
||||||
|
|
||||||
|
fn math_add<'a>(&self, other: &dyn ContextElement) -> Option<IceResult<'a>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: 'static + ContextElement> CastToAny for C {
|
impl<C: 'static + ContextElement> CastToAny for C {
|
||||||
@ -81,6 +84,14 @@ impl<'a, 'b> PartialOrd<&'b dyn ContextElement> for &'a dyn ContextElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> Add<&'a dyn ContextElement> for &'a dyn ContextElement {
|
||||||
|
type Output = Option<IceResult<'a>>;
|
||||||
|
|
||||||
|
fn add(self, other: &'a dyn ContextElement) -> Self::Output {
|
||||||
|
self.math_add(other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FromContextElement {
|
pub trait FromContextElement {
|
||||||
fn from_context_element(&self) -> &dyn IntoContextElement;
|
fn from_context_element(&self) -> &dyn IntoContextElement;
|
||||||
}
|
}
|
||||||
@ -91,7 +102,7 @@ impl<C: ContextElement> FromContextElement for C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait IntoContextElement: Debug + Walkable /* + CloneIntoBoxedContextElement*/ {
|
pub trait IntoContextElement: Debug + Walkable {
|
||||||
fn into_context_element<'a>(
|
fn into_context_element<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
renderer: &DustRenderer,
|
renderer: &DustRenderer,
|
||||||
|
@ -12,6 +12,7 @@ mod walking;
|
|||||||
|
|
||||||
pub use context_element::CompareContextElement;
|
pub use context_element::CompareContextElement;
|
||||||
pub use context_element::ContextElement;
|
pub use context_element::ContextElement;
|
||||||
|
pub use context_element::IceResult;
|
||||||
pub use context_element::IntoContextElement;
|
pub use context_element::IntoContextElement;
|
||||||
pub use context_element::Loopable;
|
pub use context_element::Loopable;
|
||||||
pub use context_element::Renderable;
|
pub use context_element::Renderable;
|
||||||
|
@ -18,6 +18,7 @@ use crate::renderer::Walkable;
|
|||||||
use std::borrow::Borrow;
|
use std::borrow::Borrow;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParametersContext<'a> {
|
pub struct ParametersContext<'a> {
|
||||||
@ -325,4 +326,93 @@ impl CompareContextElement for OwnedLiteral {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn math_add<'a>(&self, other: &dyn ContextElement) -> Option<IceResult<'a>> {
|
||||||
|
// If its an OwnedLiteral then add them directly, otherwise
|
||||||
|
// defer to the other type's implementation of
|
||||||
|
// CompareContextElement since the end user could add any
|
||||||
|
// 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,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For math operations that take in integers and return integers
|
||||||
|
/// (add, subtract, multiply)
|
||||||
|
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()
|
||||||
|
// }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user