Rewrite node graph using generic associated types

This commit is contained in:
Dennis 2022-03-29 23:34:45 +02:00 committed by Keavon Chambers
parent 1174fadfaf
commit 19b02738ca
2 changed files with 90 additions and 47 deletions

View File

@ -1,29 +1,54 @@
#![deny(rust_2018_idioms)] #![feature(generic_associated_types)]
use std::any::Any; //#![deny(rust_2018_idioms)]
use std::{any::Any, borrow::Borrow};
mod iter; mod iter;
mod nodes; pub mod nodes;
use iter::insert_after_nth; use iter::insert_after_nth;
use nodes::*; use nodes::*;
pub trait Node<'n, OUT> { pub trait Node {
fn eval(&'n self, input: impl Iterator<Item = &'n dyn Any> + Clone) -> OUT; type Out<'a>
// fn source code where
// positon Self: 'a;
type Input<'a>
where
Self: 'a;
fn eval<'a, T: Borrow<Self::Input<'a>>>(&'a self, input: T) -> Self::Out<'a>;
} }
trait After<'n, OUT, SECOND: Node<'n, OUT>> { pub trait AnyRef: Node {
fn after<INTERMEDIATE, FIRST: Node<'n, INTERMEDIATE>>( fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Out<'a>
&'n self, where
first: &'n FIRST, Self::Input<'a>: 'static + Copy;
) -> ComposeNode<'n, FIRST, SECOND, INTERMEDIATE>; }
impl<T: Node> AnyRef for T {
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Out<'a>
where
Self::Input<'a>: 'static + Copy,
{
self.eval::<&Self::Input<'a>>(input.downcast_ref::<Self::Input<'a>>().unwrap())
}
} }
/*
trait After<SECOND: Node> {
type Out<'a>
where
Self: 'a;
fn after<'a><FIRST: Node>(
&'a self,
first: &'a FIRST,
) -> ComposeNode<'a, FIRST, SECOND, INTERMEDIATE>;
}*/
fn main() { fn main() {
use std::iter;
let int = IntNode::<32>; let int = IntNode::<32>;
let add: u32 = AddNode::<u32>::default().any(&(int.eval(&()), int.eval(&())) as &dyn Any);
/*
let curry: CurryNthArgNode<'_, _, _, u32, u32, 0> = CurryNthArgNode::new(&AddNode, &int); let curry: CurryNthArgNode<'_, _, _, u32, u32, 0> = CurryNthArgNode::new(&AddNode, &int);
let composition = curry.after(&curry); let composition = curry.after(&curry);
let n = ValueNode::new(10_u32); let n = ValueNode::new(10_u32);
let curry: CurryNthArgNode<'_, _, _, u32, _, 0> = CurryNthArgNode::new(&composition, &n); let curry: CurryNthArgNode<'_, _, _, u32, _, 0> = CurryNthArgNode::new(&composition, &n);
println!("{}", curry.eval(iter::empty())) */
println!("{}", add)
} }

View File

@ -1,30 +1,29 @@
use std::{ use std::{
any::Any, collections::hash_map::DefaultHasher, hash::Hasher, iter, iter::Sum, any::Any, borrow::Borrow, collections::hash_map::DefaultHasher, hash::Hasher, iter, iter::Sum,
marker::PhantomData, marker::PhantomData,
}; };
use crate::{insert_after_nth, After, Node}; use crate::{insert_after_nth, /*After,*/ Node};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
pub struct IntNode<const N: u32>; pub struct IntNode<const N: u32>;
impl<'n, const N: u32> Node<'n, u32> for IntNode<N> { impl<const N: u32> Node for IntNode<N> {
fn eval(&'n self, _input: impl Iterator<Item = &'n dyn Any>) -> u32 { type Out<'a> = u32;
type Input<'a> = ();
fn eval<'a, I: Borrow<Self::Input<'a>>>(&self, _input: I) -> u32 {
N N
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct ValueNode<T>(T); pub struct ValueNode<T>(T);
impl<'n, T> Node<'n, &'n T> for ValueNode<T> { impl<T> Node for ValueNode<T> {
fn eval(&'n self, _input: impl Iterator<Item = &'n dyn Any>) -> &T { type Out<'a> = &'a T where T: 'a;
type Input<'a> = () where T: 'a;
fn eval<'n, I: Borrow<Self::Input<'n>>>(&'n self, _input: I) -> &T {
&self.0 &self.0
} }
} }
impl<'n, T: Copy> Node<'n, T> for ValueNode<T> {
fn eval(&'n self, _input: impl Iterator<Item = &'n dyn Any>) -> T {
self.0
}
}
impl<T> ValueNode<T> { impl<T> ValueNode<T> {
pub fn new(value: T) -> ValueNode<T> { pub fn new(value: T) -> ValueNode<T> {
@ -32,29 +31,34 @@ impl<T> ValueNode<T> {
} }
} }
pub struct AddNode; #[derive(Default)]
impl<'n, T: Sum + 'static + Copy> Node<'n, T> for AddNode { pub struct AddNode<T>(PhantomData<T>);
fn eval(&'n self, input: impl Iterator<Item = &'n dyn Any>) -> T { impl<T: std::ops::Add + 'static + Copy> Node for AddNode<T> {
input.map(|x| *(x.downcast_ref::<T>().unwrap())).sum::<T>() type Out<'a> = T::Output;
type Input<'a> = (T, T);
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> T::Output {
input.borrow().0 + input.borrow().1
} }
} }
/// Caches the output of a given Node and acts as a proxy /// Caches the output of a given Node and acts as a proxy
pub struct CacheNode<'n, NODE: Node<'n, OUT>, OUT: Clone> { pub struct CacheNode<'n, 'c, CachedNode: Node + 'c> {
node: &'n NODE, node: &'n CachedNode,
cache: OnceCell<OUT>, cache: OnceCell<CachedNode::Out<'c>>,
} }
impl<'n, NODE: Node<'n, OUT>, OUT: Clone> Node<'n, &'n OUT> for CacheNode<'n, NODE, OUT> { impl<'n: 'c, 'c, CashedNode: Node> Node for CacheNode<'n, 'c, CashedNode> {
fn eval(&'n self, input: impl Iterator<Item = &'n dyn Any> + Clone) -> &'n OUT { type Out<'a> = &'a CashedNode::Out<'c> where 'c: 'a;
type Input<'a> = CashedNode::Input<'c> where 'c: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Out<'a> {
self.cache.get_or_init(|| self.node.eval(input)) self.cache.get_or_init(|| self.node.eval(input))
} }
} }
impl<'n, NODE: Node<'n, OUT>, OUT: Clone> CacheNode<'n, NODE, OUT> { impl<'n, 'c, NODE: Node> CacheNode<'n, 'c, NODE> {
fn clear(&'n mut self) { pub fn clear(&'n mut self) {
self.cache = OnceCell::new(); self.cache = OnceCell::new();
} }
fn new(node: &'n NODE) -> CacheNode<'n, NODE, OUT> { pub fn new(node: &'n NODE) -> CacheNode<'n, 'c, NODE> {
CacheNode { CacheNode {
node, node,
cache: OnceCell::new(), cache: OnceCell::new(),
@ -110,6 +114,8 @@ impl<'n, NODE: Node<'n, OUT>, OUT: Clone> SmartCacheNode<'n, NODE, OUT> {
} }
}*/ }*/
/*
pub struct CurryNthArgNode< pub struct CurryNthArgNode<
'n, 'n,
CurryNode: Node<'n, OUT>, CurryNode: Node<'n, OUT>,
@ -151,27 +157,38 @@ impl<'n, CurryNode: Node<'n, Out>, ArgNode: Node<'n, Arg>, Arg: Clone, Out, cons
} }
} }
} }
*/
pub struct ComposeNode<'n, FIRST, SECOND, INTERMEDIATE> /*
pub struct ComposeNode<'n, FIRST, SECOND>
where where
FIRST: Node<'n, INTERMEDIATE>, FIRST: Node,
{ {
first: &'n FIRST, first: &'n FIRST,
second: &'n SECOND, second: &'n SECOND,
_phantom_data: PhantomData<INTERMEDIATE>, _phantom_data: PhantomData<INTERMEDIATE>,
} }
impl<'n, FIRST, SECOND, OUT: 'n, INTERMEDIATE: 'static + Clone> Node<'n, OUT> impl<'n, FIRST, SECOND> Node for ComposeNode<'n, FIRST, SECOND>
for ComposeNode<'n, FIRST, SECOND, INTERMEDIATE>
where where
FIRST: Node<'n, INTERMEDIATE>, FIRST: Node,
SECOND: Node<'n, OUT>, SECOND: Node,
{ {
fn eval(&'n self, input: impl Iterator<Item = &'n dyn Any> + Clone) -> OUT { fn eval<'a, T: &Self::Input<'a>>(&'a self, input: T) -> &Self::Out<'a> {
let curry = CurryNthArgNode::<'_, _, _, _, _, 0>::new(self.second, self.first); self.second.eval(self.first.eval(input))
CurryNthArgNode::<'_, _, _, _, _, 0>::new(curry, ValueNode::new(input)).eval(input) //let curry = CurryNthArgNode::<'_, _, _, _, _, 0>::new(self.second, self.first);
//CurryNthArgNode::<'_, _, _, _, _, 0>::new(curry, ValueNode::new(input)).eval(input)
} }
type Out<'a> = SECOND::Out<'a>
where
Self: 'a;
type Input<'a> = FIRST::Input<'a>
where
Self: 'a;
} }
*/
/*
impl<'n, FIRST, SECOND, INTERMEDIATE: 'static> ComposeNode<'n, FIRST, SECOND, INTERMEDIATE> impl<'n, FIRST, SECOND, INTERMEDIATE: 'static> ComposeNode<'n, FIRST, SECOND, INTERMEDIATE>
where where
@ -198,3 +215,4 @@ impl<'n, OUT, SECOND: Node<'n, OUT>> After<'n, OUT, SECOND> for SECOND {
} }
} }
} }
*/