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::ContextElement; | ||||
| use renderer::DustRenderer; | ||||
| use renderer::IceResult; | ||||
| use renderer::IntoContextElement; | ||||
| use renderer::Loopable; | ||||
| use renderer::RenderError; | ||||
| @ -387,6 +388,10 @@ impl CompareContextElement for serde_json::Value { | ||||
|             _ => panic!("Unimplemented comparison type."), | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn math_add<'a>(&self, other: &dyn ContextElement) -> Option<IceResult<'a>> { | ||||
|         todo!() | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug)] | ||||
|  | ||||
| @ -4,6 +4,7 @@ use crate::renderer::errors::RenderError; | ||||
| use crate::renderer::errors::WalkError; | ||||
| use crate::renderer::DustRenderer; | ||||
| use std::any::Any; | ||||
| use std::ops::Add; | ||||
| use std::rc::Rc; | ||||
| use std::{cmp::Ordering, fmt::Debug}; | ||||
| 
 | ||||
| @ -61,6 +62,8 @@ pub trait CompareContextElement: CastToAny { | ||||
|     fn equals(&self, other: &dyn ContextElement) -> bool; | ||||
| 
 | ||||
|     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 { | ||||
| @ -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 { | ||||
|     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>( | ||||
|         &'a self, | ||||
|         renderer: &DustRenderer, | ||||
|  | ||||
| @ -12,6 +12,7 @@ mod walking; | ||||
| 
 | ||||
| pub use context_element::CompareContextElement; | ||||
| pub use context_element::ContextElement; | ||||
| pub use context_element::IceResult; | ||||
| pub use context_element::IntoContextElement; | ||||
| pub use context_element::Loopable; | ||||
| pub use context_element::Renderable; | ||||
|  | ||||
| @ -18,6 +18,7 @@ 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> { | ||||
| @ -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
	 Tom Alexander
						Tom Alexander