mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Make node trait consume self
This commit is contained in:
@@ -1,31 +1,45 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
pub struct FnNode<'n, T: Fn(I) -> O, I, O>(T, PhantomData<&'n (I, O)>);
|
||||
impl<'n, T: Fn(I) -> O, O, I> Node<'n, I> for FnNode<'n, T, I, O> {
|
||||
pub struct FnNode<T: Fn(I) -> O, I, O>(T, PhantomData<(I, O)>);
|
||||
impl<T: Fn(I) -> O, O, I> Node<I> for FnNode<T, I, O> {
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self, input: I) -> Self::Output {
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0(input)
|
||||
}
|
||||
}
|
||||
impl<'n, T: Fn(I) -> O, O, I> Node<I> for &'n FnNode<T, I, O> {
|
||||
type Output = O;
|
||||
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T: Fn(I) -> O, I, O> FnNode<'n, T, I, O> {
|
||||
impl<T: Fn(I) -> O, I, O> FnNode<T, I, O> {
|
||||
pub fn new(f: T) -> Self {
|
||||
FnNode(f, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FnNodeWithState<'n, T: Fn(I, &'n State) -> O, I, O, State: 'n>(T, State, PhantomData<&'n (O, I)>);
|
||||
impl<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n> Node<'n, I> for FnNodeWithState<'n, T, I, O, State> {
|
||||
pub struct FnNodeWithState<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n>(T, State, PhantomData<&'n (O, I)>);
|
||||
impl<'n, T: Fn(I, &State) -> O, I, O: 'n, State: 'n> Node<I> for &'n FnNodeWithState<'n, T, I, O, State> {
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self, input: I) -> Self::Output {
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0(input, &self.1)
|
||||
}
|
||||
}
|
||||
impl<'n, T: Fn(I, &State) -> O, I, O: 'n, State: 'n> Node<I> for FnNodeWithState<'n, T, I, O, State> {
|
||||
type Output = O;
|
||||
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0(input, &self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T: Fn(I, &'n State) -> O, I, O: 'n, State: 'n> FnNodeWithState<'n, T, I, O, State> {
|
||||
impl<'n, T: Fn(I, &State) -> O, I, O, State> FnNodeWithState<'n, T, I, O, State> {
|
||||
pub fn new(f: T, state: State) -> Self {
|
||||
FnNodeWithState(f, state, PhantomData)
|
||||
}
|
||||
|
||||
@@ -14,18 +14,10 @@ pub mod raster;
|
||||
pub mod structural;
|
||||
pub mod value;
|
||||
|
||||
pub trait Node<'n, T> {
|
||||
type Output; // TODO: replace with generic associated type
|
||||
pub trait Node<T> {
|
||||
type Output;
|
||||
|
||||
fn eval(&'n self, input: T) -> Self::Output;
|
||||
}
|
||||
|
||||
impl<'n, N: Node<'n, T>, T> Node<'n, T> for &'n N {
|
||||
type Output = N::Output;
|
||||
|
||||
fn eval(&'n self, input: T) -> Self::Output {
|
||||
Node::eval(*self, input)
|
||||
}
|
||||
fn eval(self, input: T) -> Self::Output;
|
||||
}
|
||||
|
||||
trait Input<I> {
|
||||
@@ -34,21 +26,21 @@ trait Input<I> {
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
pub trait AsyncNode<'n, T> {
|
||||
type Output; // TODO: replace with generic associated type
|
||||
pub trait AsyncNode<T> {
|
||||
type Output;
|
||||
|
||||
async fn eval_async(&'n self, input: T) -> Self::Output;
|
||||
async fn eval_async(self, input: T) -> Self::Output;
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
/*#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
impl<'n, N: Node<'n, T> + Sync, T: Send + 'n> AsyncNode<'n, T> for N {
|
||||
impl<'n, N: Node<T> + Send + Sync + 'n, T: Send + 'n> AsyncNode<T> for N {
|
||||
type Output = N::Output;
|
||||
|
||||
async fn eval_async(&'n self, input: T) -> Self::Output {
|
||||
async fn eval_async(self, input: T) -> Self::Output {
|
||||
Node::eval(self, input)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
pub trait Cache {
|
||||
fn clear(&mut self);
|
||||
|
||||
@@ -3,111 +3,124 @@ use core::ops::Add;
|
||||
|
||||
use crate::Node;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct AddNode;
|
||||
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<'n, (L, R)> for AddNode {
|
||||
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<(L, R)> for AddNode {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(&'n self, input: (L, R)) -> Self::Output {
|
||||
fn eval(self, input: (L, R)) -> Self::Output {
|
||||
input.0 + input.1
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CloneNode;
|
||||
impl<'n, O: Clone> Node<'n, &'n O> for CloneNode {
|
||||
impl<'n, O: Clone> Node<&'n O> for CloneNode {
|
||||
type Output = O;
|
||||
fn eval(&'n self, input: &'n O) -> Self::Output {
|
||||
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<'n, (T, U)> for FstNode {
|
||||
impl<'n, T: 'n, U> Node<(T, U)> for FstNode {
|
||||
type Output = T;
|
||||
fn eval(&'n self, input: (T, U)) -> Self::Output {
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (a, _) = input;
|
||||
a
|
||||
}
|
||||
}
|
||||
impl<'n, T: 'n, U> Node<'n, &'n (T, U)> for FstNode {
|
||||
impl<'n, T: 'n, U> Node<&'n (T, U)> for FstNode {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
|
||||
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<'n, (T, U)> for SndNode {
|
||||
impl<'n, T, U: 'n> Node<(T, U)> for SndNode {
|
||||
type Output = U;
|
||||
fn eval(&'n self, input: (T, U)) -> Self::Output {
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (_, b) = input;
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T, U: 'n> Node<'n, &'n (T, U)> for SndNode {
|
||||
impl<'n, T, U: 'n> Node<&'n (T, U)> for SndNode {
|
||||
type Output = &'n U;
|
||||
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
|
||||
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<'n, (T, U)> for SwapNode {
|
||||
impl<'n, T: 'n, U: 'n> Node<(T, U)> for SwapNode {
|
||||
type Output = (U, T);
|
||||
fn eval(&'n self, input: (T, U)) -> Self::Output {
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (a, b) = input;
|
||||
(b, a)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T, U: 'n> Node<'n, &'n (T, U)> for SwapNode {
|
||||
impl<'n, T, U: 'n> Node<&'n (T, U)> for SwapNode {
|
||||
type Output = (&'n U, &'n T);
|
||||
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
|
||||
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<'n, T> for DupNode {
|
||||
impl<'n, T: Clone + 'n> Node<T> for DupNode {
|
||||
type Output = (T, T);
|
||||
fn eval(&'n self, input: T) -> Self::Output {
|
||||
fn eval(self, input: T) -> Self::Output {
|
||||
(input.clone(), input) //TODO: use Copy/Clone implementation
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the Input Argument
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct IdNode;
|
||||
impl<'n, T: 'n> Node<'n, T> for IdNode {
|
||||
impl<'n, T: 'n> Node<T> for IdNode {
|
||||
type Output = T;
|
||||
fn eval(&'n self, input: T) -> Self::Output {
|
||||
fn eval(self, input: T) -> Self::Output {
|
||||
input
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MapResultNode<'n, MN: Node<'n, I>, I, E>(pub MN, pub PhantomData<&'n (I, E)>);
|
||||
pub struct MapResultNode<MN, I, E>(pub MN, pub PhantomData<(I, E)>);
|
||||
|
||||
impl<'n, MN: Node<'n, I>, I, E> Node<'n, Result<I, E>> for MapResultNode<'n, MN, I, E> {
|
||||
impl<MN: Node<I>, I, E> Node<Result<I, E>> for MapResultNode<MN, I, E> {
|
||||
type Output = Result<MN::Output, E>;
|
||||
fn eval(&'n self, input: Result<I, E>) -> Self::Output {
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
input.map(|x| self.0.eval(x))
|
||||
}
|
||||
}
|
||||
impl<'n, MN: Node<I> + Copy, I, E> Node<Result<I, E>> for &'n MapResultNode<MN, I, E> {
|
||||
type Output = Result<MN::Output, E>;
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
input.map(|x| (&self.0).eval(x))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, MN: Node<'n, I>, I, E> MapResultNode<'n, MN, I, E> {
|
||||
impl<MN, I, E> MapResultNode<MN, I, E> {
|
||||
pub const fn new(mn: MN) -> Self {
|
||||
Self(mn, PhantomData)
|
||||
}
|
||||
}
|
||||
pub struct FlatMapResultNode<'n, MN: Node<'n, I>, I, E>(pub MN, pub PhantomData<&'n (I, E)>);
|
||||
pub struct FlatMapResultNode<MN: Node<I>, I, E>(pub MN, pub PhantomData<(I, E)>);
|
||||
|
||||
impl<'n, MN: Node<'n, I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<'n, Result<I, E>> for FlatMapResultNode<'n, MN, I, E> {
|
||||
impl<'n, MN: Node<I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<Result<I, E>> for FlatMapResultNode<MN, I, E> {
|
||||
type Output = Result<O, E>;
|
||||
fn eval(&'n self, input: Result<I, E>) -> Self::Output {
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
match input.map(|x| self.0.eval(x)) {
|
||||
Ok(Ok(x)) => Ok(x),
|
||||
Ok(Err(e)) => Err(e),
|
||||
@@ -116,7 +129,7 @@ impl<'n, MN: Node<'n, I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<'n, Resul
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, MN: Node<'n, I>, I, E> FlatMapResultNode<'n, MN, I, E> {
|
||||
impl<MN: Node<I>, I, E> FlatMapResultNode<MN, I, E> {
|
||||
pub const fn new(mn: MN) -> Self {
|
||||
Self(mn, PhantomData)
|
||||
}
|
||||
@@ -131,26 +144,26 @@ mod test {
|
||||
pub fn dup_node() {
|
||||
let value = ValueNode(4u32);
|
||||
let dup = DupNode.after(value);
|
||||
assert_eq!(dup.eval(()), (&4, &4));
|
||||
assert_eq!(dup.eval(()), (4, 4));
|
||||
}
|
||||
#[test]
|
||||
pub fn id_node() {
|
||||
let value = IdNode.after(ValueNode(4u32));
|
||||
assert_eq!(value.eval(()), &4);
|
||||
assert_eq!(value.eval(()), 4);
|
||||
}
|
||||
#[test]
|
||||
pub fn clone_node() {
|
||||
let cloned = CloneNode.after(ValueNode(4u32));
|
||||
let cloned = CloneNode.after(&ValueNode(4u32));
|
||||
assert_eq!(cloned.eval(()), 4);
|
||||
}
|
||||
#[test]
|
||||
pub fn fst_node() {
|
||||
let fst = FstNode.after(ValueNode((4u32, "a")).clone());
|
||||
let fst = FstNode.after(ValueNode((4u32, "a")));
|
||||
assert_eq!(fst.eval(()), 4);
|
||||
}
|
||||
#[test]
|
||||
pub fn snd_node() {
|
||||
let fst = SndNode.after(ValueNode((4u32, "a")).clone());
|
||||
let fst = SndNode.after(ValueNode((4u32, "a")));
|
||||
assert_eq!(fst.eval(()), "a");
|
||||
}
|
||||
#[test]
|
||||
@@ -164,8 +177,8 @@ mod test {
|
||||
}
|
||||
#[test]
|
||||
pub fn foo() {
|
||||
fn int(_: (), state: &u32) -> &u32 {
|
||||
state
|
||||
fn int(_: (), state: &u32) -> u32 {
|
||||
*state
|
||||
}
|
||||
fn swap(input: (u32, u32)) -> (u32, u32) {
|
||||
(input.1, input.0)
|
||||
@@ -173,6 +186,7 @@ mod test {
|
||||
let fnn = FnNode::new(&swap);
|
||||
let fns = FnNodeWithState::new(int, 42u32);
|
||||
assert_eq!(fnn.eval((1u32, 2u32)), (2, 1));
|
||||
assert_eq!(fns.eval(()), &42);
|
||||
let result: u32 = (&fns).eval(());
|
||||
assert_eq!(result, 42);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,48 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
|
||||
use self::color::Color;
|
||||
|
||||
pub mod color;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct GrayscaleNode;
|
||||
|
||||
impl<'n> Node<'n, Color> for GrayscaleNode {
|
||||
impl Node<Color> for GrayscaleNode {
|
||||
type Output = Color;
|
||||
fn eval(&'n self, color: Color) -> Color {
|
||||
fn eval(self, color: Color) -> Color {
|
||||
let avg = (color.r() + color.g() + color.b()) / 3.0;
|
||||
Color::from_rgbaf32(avg, avg, avg, color.a()).expect("Grayscale node created an invalid color")
|
||||
Color::from_rgbaf32_unchecked(avg, avg, avg, color.a())
|
||||
}
|
||||
}
|
||||
impl<'n> Node<Color> for &'n GrayscaleNode {
|
||||
type Output = Color;
|
||||
fn eval(self, color: Color) -> Color {
|
||||
let avg = (color.r() + color.g() + color.b()) / 3.0;
|
||||
Color::from_rgbaf32_unchecked(avg, avg, avg, color.a())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ForEachNode<'n, I: Iterator<Item = S>, MN: Node<'n, S>, S>(pub MN, PhantomData<&'n (I, S)>);
|
||||
pub struct ForEachNode<MN>(pub MN);
|
||||
|
||||
impl<'n, I: Iterator<Item = S>, MN: Node<'n, S, Output = ()>, S> Node<'n, I> for ForEachNode<'n, I, MN, S> {
|
||||
impl<'n, I: Iterator<Item = S>, MN: 'n, S> Node<I> for &'n ForEachNode<MN>
|
||||
where
|
||||
&'n MN: Node<S, Output = ()>,
|
||||
{
|
||||
type Output = ();
|
||||
fn eval(&'n self, input: I) -> Self::Output {
|
||||
input.for_each(|x| self.0.eval(x))
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
input.for_each(|x| (&self.0).eval(x))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MutWrapper<'n, N: Node<'n, T, Output = T>, T: Clone>(pub N, PhantomData<&'n T>);
|
||||
pub struct MutWrapper<N>(pub N);
|
||||
|
||||
impl<'n, T: Clone, N: Node<'n, T, Output = T>> Node<'n, &'n mut T> for MutWrapper<'n, N, T> {
|
||||
impl<'n, T: Clone, N> Node<&'n mut T> for &'n MutWrapper<N>
|
||||
where
|
||||
&'n N: Node<T, Output = T>,
|
||||
{
|
||||
type Output = ();
|
||||
fn eval(&'n self, value: &'n mut T) {
|
||||
*value = self.0.eval(value.clone());
|
||||
fn eval(self, value: &'n mut T) {
|
||||
*value = (&self.0).eval(value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +53,9 @@ mod test {
|
||||
#[test]
|
||||
fn map_node() {
|
||||
let array = &mut [Color::from_rgbaf32(1.0, 0.0, 0.0, 1.0).unwrap()];
|
||||
let map = ForEachNode(MutWrapper(GrayscaleNode, PhantomData), PhantomData);
|
||||
map.eval(array.iter_mut());
|
||||
(&GrayscaleNode).eval(Color::from_rgbf32_unchecked(1., 0., 0.));
|
||||
let map = ForEachNode(MutWrapper(GrayscaleNode));
|
||||
(&map).eval(array.iter_mut());
|
||||
assert_eq!(array[0], Color::from_rgbaf32(0.33333334, 0.33333334, 0.33333334, 1.0).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@ pub struct Color {
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub const BLACK: Color = Color::from_unsafe(0., 0., 0.);
|
||||
pub const WHITE: Color = Color::from_unsafe(1., 1., 1.);
|
||||
pub const RED: Color = Color::from_unsafe(1., 0., 0.);
|
||||
pub const GREEN: Color = Color::from_unsafe(0., 1., 0.);
|
||||
pub const BLUE: Color = Color::from_unsafe(0., 0., 1.);
|
||||
pub const BLACK: Color = Color::from_rgbf32_unchecked(0., 0., 0.);
|
||||
pub const WHITE: Color = Color::from_rgbf32_unchecked(1., 1., 1.);
|
||||
pub const RED: Color = Color::from_rgbf32_unchecked(1., 0., 0.);
|
||||
pub const GREEN: Color = Color::from_rgbf32_unchecked(0., 1., 0.);
|
||||
pub const BLUE: Color = Color::from_rgbf32_unchecked(0., 0., 1.);
|
||||
|
||||
/// Returns `Some(Color)` if `red`, `green`, `blue` and `alpha` have a valid value. Negative numbers (including `-0.0`), NaN, and infinity are not valid values and return `None`.
|
||||
/// Alpha values greater than `1.0` are not valid.
|
||||
@@ -40,7 +40,12 @@ impl Color {
|
||||
}
|
||||
|
||||
/// Return an opaque `Color` from given `f32` RGB channels.
|
||||
pub const fn from_unsafe(red: f32, green: f32, blue: f32) -> Color {
|
||||
pub const fn from_rgbaf32_unchecked(red: f32, green: f32, blue: f32, alpha: f32) -> Color {
|
||||
Color { red, green, blue, alpha }
|
||||
}
|
||||
|
||||
/// Return an opaque `Color` from given `f32` RGB channels.
|
||||
pub const fn from_rgbf32_unchecked(red: f32, green: f32, blue: f32) -> Color {
|
||||
Color { red, green, blue, alpha: 1. }
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,20 @@ use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
|
||||
pub struct ComposeNode<'n, Input, First: Node<'n, Input>, Second> {
|
||||
pub struct ComposeNode<First, Second, Input> {
|
||||
first: First,
|
||||
second: Second,
|
||||
_phantom: PhantomData<&'n Input>,
|
||||
_phantom: PhantomData<Input>,
|
||||
}
|
||||
|
||||
impl<'n, Input, Inter, First, Second> Node<'n, Input> for ComposeNode<'n, Input, First, Second>
|
||||
impl<Input, Inter, First, Second> Node<Input> for ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: Node<'n, Input, Output = Inter>,
|
||||
Second: Node<'n, Inter>,
|
||||
First: Node<Input, Output = Inter>,
|
||||
Second: Node<Inter>,
|
||||
{
|
||||
type Output = <Second as Node<'n, Inter>>::Output;
|
||||
type Output = <Second as Node<Inter>>::Output;
|
||||
|
||||
fn eval(&'n self, input: Input) -> Self::Output {
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
// evaluate the first node with the given input
|
||||
// and then pipe the result from the first computation
|
||||
// into the second node
|
||||
@@ -23,52 +23,105 @@ where
|
||||
self.second.eval(arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, Input, First, Second> ComposeNode<'n, Input, First, Second>
|
||||
impl<'n, Input, Inter, First, Second> Node<Input> for &'n ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: Node<'n, Input>,
|
||||
Second: Node<'n, First::Output>,
|
||||
First: Node<Input, Output = Inter> + Copy,
|
||||
Second: Node<Inter> + Copy,
|
||||
{
|
||||
type Output = Second::Output;
|
||||
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
// evaluate the first node with the given input
|
||||
// and then pipe the result from the first computation
|
||||
// into the second node
|
||||
let arg: Inter = self.first.eval(input);
|
||||
(&self.second).eval(arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, Input, First: 'n, Second: 'n> ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: Node<Input>,
|
||||
Second: Node<First::Output>,
|
||||
{
|
||||
pub const fn new(first: First, second: Second) -> Self {
|
||||
ComposeNode::<'n, Input, First, Second> { first, second, _phantom: PhantomData }
|
||||
ComposeNode::<First, Second, Input> { first, second, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait After<Inter>: Sized {
|
||||
fn after<'n, First, Input>(self, first: First) -> ComposeNode<'n, Input, First, Self>
|
||||
fn after<First, Input>(self, first: First) -> ComposeNode<First, Self, Input>
|
||||
where
|
||||
First: Node<'n, Input, Output = Inter>,
|
||||
Self: Node<'n, Inter>,
|
||||
First: Node<Input, Output = Inter>,
|
||||
Self: Node<Inter>,
|
||||
{
|
||||
ComposeNode::new(first, self)
|
||||
ComposeNode::<First, Self, Input> {
|
||||
first,
|
||||
second: self,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'n, Second: Node<'n, I>, I> After<I> for Second {}
|
||||
impl<Second: Node<I>, I> After<I> for Second {}
|
||||
|
||||
pub trait AfterRef<Inter>: Sized {
|
||||
fn after<'n, First: 'n, Input>(&'n self, first: First) -> ComposeNode<First, &'n Self, Input>
|
||||
where
|
||||
First: Node<Input, Output = Inter> + Copy,
|
||||
&'n Self: Node<Inter>,
|
||||
Self: 'n,
|
||||
{
|
||||
ComposeNode::<First, &'n Self, Input> {
|
||||
first,
|
||||
second: self,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'n, Second: 'n, I> AfterRef<I> for Second where &'n Second: Node<I> {}
|
||||
|
||||
pub struct ConsNode<Root>(pub Root);
|
||||
|
||||
impl<'n, Root, Input> Node<'n, Input> for ConsNode<Root>
|
||||
impl<Root, Input> Node<Input> for ConsNode<Root>
|
||||
where
|
||||
Root: Node<'n, ()>,
|
||||
Root: Node<()>,
|
||||
{
|
||||
type Output = (Input, <Root as Node<'n, ()>>::Output);
|
||||
type Output = (Input, <Root as Node<()>>::Output);
|
||||
|
||||
fn eval(&'n self, input: Input) -> Self::Output {
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
let arg = self.0.eval(());
|
||||
(input, arg)
|
||||
}
|
||||
}
|
||||
impl<'n, Root: Node<()> + Copy, Input> Node<Input> for &'n ConsNode<Root> {
|
||||
type Output = (Input, Root::Output);
|
||||
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
let arg = (&self.0).eval(());
|
||||
(input, arg)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConsPassInputNode<Root>(pub Root);
|
||||
|
||||
impl<'n, Root, L, R> Node<'n, (L, R)> for ConsPassInputNode<Root>
|
||||
impl<Root, L, R> Node<(L, R)> for ConsPassInputNode<Root>
|
||||
where
|
||||
Root: Node<'n, R>,
|
||||
Root: Node<R>,
|
||||
{
|
||||
type Output = (L, <Root as Node<'n, R>>::Output);
|
||||
type Output = (L, <Root as Node<R>>::Output);
|
||||
|
||||
fn eval(&'n self, input: (L, R)) -> Self::Output {
|
||||
fn eval(self, input: (L, R)) -> Self::Output {
|
||||
let arg = self.0.eval(input.1);
|
||||
(input.0, arg)
|
||||
}
|
||||
}
|
||||
impl<'n, Root, L, R> Node<(L, R)> for &'n ConsPassInputNode<Root>
|
||||
where
|
||||
&'n Root: Node<R>,
|
||||
{
|
||||
type Output = (L, <&'n Root as Node<R>>::Output);
|
||||
|
||||
fn eval(self, input: (L, R)) -> Self::Output {
|
||||
let arg = (&self.0).eval(input.1);
|
||||
(input.0, arg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,23 +2,28 @@ use core::marker::PhantomData;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::sync::atomic::AtomicBool;
|
||||
|
||||
use crate::ops::CloneNode;
|
||||
use crate::structural::ComposeNode;
|
||||
use crate::Node;
|
||||
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct IntNode<const N: u32>;
|
||||
impl<'n, const N: u32> Node<'n, ()> for IntNode<N> {
|
||||
impl<const N: u32> Node<()> for IntNode<N> {
|
||||
type Output = u32;
|
||||
fn eval(&self, _: ()) -> u32 {
|
||||
fn eval(self, _: ()) -> u32 {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Debug)]
|
||||
pub struct ValueNode<T>(pub T);
|
||||
impl<'n, T: 'n> Node<'n, ()> for ValueNode<T> {
|
||||
impl<'n, T: 'n> Node<()> for ValueNode<T> {
|
||||
type Output = T;
|
||||
fn eval(self, _: ()) -> Self::Output {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
impl<'n, T: 'n> Node<()> for &'n ValueNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self, _: ()) -> Self::Output {
|
||||
fn eval(self, _: ()) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
@@ -29,39 +34,60 @@ impl<T> ValueNode<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T: Clone + 'n> ValueNode<T> {
|
||||
pub const fn clone(self) -> ComposeNode<'n, (), ValueNode<T>, CloneNode> {
|
||||
ComposeNode::new(self, CloneNode)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<T> for ValueNode<T> {
|
||||
fn from(value: T) -> Self {
|
||||
ValueNode::new(value)
|
||||
}
|
||||
}
|
||||
impl<T: Clone> Clone for ValueNode<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
impl<T: Clone + Copy> Copy for ValueNode<T> {}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DefaultNode<T>(PhantomData<T>);
|
||||
impl<'n, T: Default + 'n> Node<'n, ()> for DefaultNode<T> {
|
||||
impl<T: Default> Node<()> for DefaultNode<T> {
|
||||
type Output = T;
|
||||
fn eval(&self, _: ()) -> T {
|
||||
fn eval(self, _: ()) -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
impl<'n, T: Default + 'n> Node<()> for &'n DefaultNode<T> {
|
||||
type Output = T;
|
||||
fn eval(self, _: ()) -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return the unit value
|
||||
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct UnitNode;
|
||||
impl<'n> Node<'n, ()> for UnitNode {
|
||||
impl Node<()> for UnitNode {
|
||||
type Output = ();
|
||||
fn eval(&'n self, _: ()) -> Self::Output {}
|
||||
fn eval(self, _: ()) -> Self::Output {}
|
||||
}
|
||||
impl<'n> Node<()> for &'n UnitNode {
|
||||
type Output = ();
|
||||
fn eval(self, _: ()) -> Self::Output {}
|
||||
}
|
||||
|
||||
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
|
||||
impl<'n, T: 'n> Node<'n, ()> for InputNode<T> {
|
||||
impl<'n, T: 'n> Node<()> for InputNode<T> {
|
||||
type Output = T;
|
||||
fn eval(self, _: ()) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init() }
|
||||
} else {
|
||||
panic!("tried to access an input before setting it")
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'n, T: 'n> Node<()> for &'n InputNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self, _: ()) -> Self::Output {
|
||||
fn eval(self, _: ()) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user