use core::marker::PhantomData; use core::ops::Add; use crate::{Node, RefNode}; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct AddNode; impl<'n, L: Add + 'n, R, O: 'n> Node<(L, R)> for AddNode { type Output = >::Output; fn eval(self, input: (L, R)) -> Self::Output { input.0 + input.1 } } impl<'n, L: Add + 'n, R, O: 'n> Node<(L, R)> for &'n AddNode { type Output = >::Output; fn eval(self, input: (L, R)) -> Self::Output { input.0 + input.1 } } impl<'n, L: Add + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for AddNode { type Output = >::Output; fn eval(self, input: &'n (L, R)) -> Self::Output { input.0 + input.1 } } impl<'n, L: Add + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for &'n AddNode { type Output = >::Output; fn eval(self, input: &'n (L, R)) -> Self::Output { input.0 + input.1 } } impl AddNode { pub fn new() -> Self { Self } } #[cfg(feature = "std")] pub mod dynamic { use super::*; // Unfortunatly we can't impl the AddNode as we get // `upstream crates may add a new impl of trait `core::ops::Add` for type `alloc::boxed::Box<(dyn dyn_any::DynAny<'_> + 'static)>` in future versions` pub struct DynamicAddNode; // Alias for a dynamic type pub type Dynamic<'a> = alloc::boxed::Box + 'a>; /// Resolves the dynamic types for a dynamic node. /// /// Macro uses format `BaseNode => (arg1: u32) (arg1: i32)` macro_rules! resolve_dynamic_types { ($node:ident => $(($($arg:ident : $t:ty),*))*) => { $( // Check for each possible set of arguments if their types match the arguments given if $(core::any::TypeId::of::<$t>() == $arg.type_id())&&* { // Cast the arguments and then call the inner node alloc::boxed::Box::new($node.eval(($(*dyn_any::downcast::<$t>($arg).unwrap()),*)) ) as Dynamic } )else* else { panic!("Unhandled type"); // TODO: Exit neatly (although this should probably not happen) } }; } impl<'n> Node<(Dynamic<'n>, Dynamic<'n>)> for DynamicAddNode { type Output = Dynamic<'n>; fn eval(self, (left, right): (Dynamic, Dynamic)) -> Self::Output { resolve_dynamic_types! { AddNode => (left: usize, right: usize) (left: u8, right: u8) (left: u16, right: u16) (left: u32, right: u32) (left: u64, right: u64) (left: u128, right: u128) (left: isize, right: isize) (left: i8, right: i8) (left: i16, right: i16) (left: i32, right: i32) (left: i64, right: i64) (left: i128, right: i128) (left: f32, right: f32) (left: f64, right: f64) } } } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct CloneNode; impl<'n, O: Clone> Node<&'n O> for CloneNode { type Output = O; fn eval(self, input: &'n O) -> Self::Output { input.clone() } } impl<'n, O: Clone> Node<&'n O> for &CloneNode { type Output = O; fn eval(self, input: &'n O) -> Self::Output { input.clone() } } #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct FstNode; impl<'n, T: 'n, U> Node<(T, U)> for FstNode { type Output = T; fn eval(self, input: (T, U)) -> Self::Output { let (a, _) = input; a } } impl<'n, T: 'n, U> Node<&'n (T, U)> for FstNode { type Output = &'n T; fn eval(self, input: &'n (T, U)) -> Self::Output { let (a, _) = input; a } } /// Destructures a Tuple of two values and returns the first one #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SndNode; impl<'n, T, U: 'n> Node<(T, U)> for SndNode { type Output = U; fn eval(self, input: (T, U)) -> Self::Output { let (_, b) = input; b } } impl<'n, T, U: 'n> Node<&'n (T, U)> for SndNode { type Output = &'n U; fn eval(self, input: &'n (T, U)) -> Self::Output { let (_, b) = input; b } } /// Destructures a Tuple of two values and returns them in reverse order #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SwapNode; impl<'n, T: 'n, U: 'n> Node<(T, U)> for SwapNode { type Output = (U, T); fn eval(self, input: (T, U)) -> Self::Output { let (a, b) = input; (b, a) } } impl<'n, T, U: 'n> Node<&'n (T, U)> for SwapNode { type Output = (&'n U, &'n T); fn eval(self, input: &'n (T, U)) -> Self::Output { let (a, b) = input; (b, a) } } /// Return a tuple with two instances of the input argument #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DupNode; impl<'n, T: Clone + 'n> Node for DupNode { type Output = (T, T); fn eval(self, input: T) -> Self::Output { (input.clone(), input) } } /// Return the Input Argument #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct IdNode; impl Node for IdNode { type Output = T; fn eval(self, input: T) -> Self::Output { input } } impl<'n, T> Node for &'n IdNode { type Output = T; fn eval(self, input: T) -> Self::Output { input } } impl RefNode for IdNode { type Output = T; fn eval_ref(&self, input: T) -> Self::Output { input } } impl IdNode { pub fn new() -> Self { Self } } /// Ascribe the node types #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct TypeNode(pub N, pub PhantomData<(I, O)>); impl, I> Node for TypeNode { type Output = N::Output; fn eval(self, input: I) -> Self::Output { self.0.eval(input) } } impl + Copy, I> Node for &TypeNode { type Output = N::Output; fn eval(self, input: I) -> Self::Output { self.0.eval(input) } } /* impl, I> Node for &TypeNode { type Output = N::Output; fn eval(self, input: I) -> Self::Output { self.0.eval_ref(input) } }*/ impl, I> TypeNode { pub fn new(node: N) -> Self { Self(node, PhantomData) } } impl + Clone, I> Clone for TypeNode { fn clone(&self) -> Self { Self(self.0.clone(), self.1) } } impl + Copy, I> Copy for TypeNode {} pub struct MapResultNode(pub MN, pub PhantomData<(I, E)>); impl, I, E> Node> for MapResultNode { type Output = Result; fn eval(self, input: Result) -> Self::Output { input.map(|x| self.0.eval(x)) } } impl<'n, MN: Node + Copy, I, E> Node> for &'n MapResultNode { type Output = Result; fn eval(self, input: Result) -> Self::Output { input.map(|x| self.0.eval(x)) } } impl MapResultNode { pub const fn new(mn: MN) -> Self { Self(mn, PhantomData) } } pub struct FlatMapResultNode, I, E>(pub MN, pub PhantomData<(I, E)>); impl<'n, MN: Node>, I, O: 'n, E: 'n> Node> for FlatMapResultNode { type Output = Result; fn eval(self, input: Result) -> Self::Output { match input.map(|x| self.0.eval(x)) { Ok(Ok(x)) => Ok(x), Ok(Err(e)) => Err(e), Err(e) => Err(e), } } } impl, I, E> FlatMapResultNode { pub const fn new(mn: MN) -> Self { Self(mn, PhantomData) } } #[cfg(test)] mod test { use super::*; use crate::{generic::*, structural::*, value::*}; #[test] pub fn dup_node() { let value = ValueNode(4u32); let dup = value.then(DupNode); assert_eq!(dup.eval(()), (4, 4)); } #[test] pub fn id_node() { let value = ValueNode(4u32).then(IdNode); assert_eq!(value.eval(()), 4); } #[test] pub fn clone_node() { let cloned = (&ValueNode(4u32)).then(CloneNode); assert_eq!(cloned.eval(()), 4); } #[test] pub fn fst_node() { let fst = ValueNode((4u32, "a")).then(FstNode); assert_eq!(fst.eval(()), 4); } #[test] pub fn snd_node() { let fst = ValueNode((4u32, "a")).then(SndNode); assert_eq!(fst.eval(()), "a"); } #[test] pub fn add_node() { let a = ValueNode(42u32); let b = ValueNode(6u32); let cons_a = ConsNode(a, PhantomData); let sum = b.then(cons_a).then(AddNode); assert_eq!(sum.eval(()), 48); } #[test] pub fn foo() { fn int(_: (), state: &u32) -> u32 { *state } fn swap(input: (u32, u32)) -> (u32, u32) { (input.1, input.0) } let fnn = FnNode::new(&swap); let fns = FnNodeWithState::new(int, 42u32); assert_eq!(fnn.eval((1u32, 2u32)), (2, 1)); let result: u32 = (&fns).eval(()); assert_eq!(result, 42); } }