Try and fail to make nodes object-safe in node graph

This commit is contained in:
Dennis 2022-04-02 20:50:53 +02:00 committed by Keavon Chambers
parent 800fb4dbc1
commit 3243b80cf2
12 changed files with 200 additions and 64 deletions

View file

@ -1,39 +0,0 @@
use std::{borrow::Borrow, marker::PhantomData};
use graphene_core::Node;
pub struct FnNode<T: Fn(&In) -> O, In, O>(T, PhantomData<In>, PhantomData<O>);
impl<T: Fn(&In) -> O, In, O> Node for FnNode<T, In, O> {
type Output<'a> = O where Self: 'a;
type Input<'a> = In where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
self.0(input.borrow())
}
}
impl<T: Fn(&In) -> O, In, O> FnNode<T, In, O> {
pub fn new(f: T) -> Self {
FnNode(f, PhantomData::default(), PhantomData::default())
}
}
pub struct FnNodeWithState<T: Fn(&In, &State) -> O, In, O, State>(
T,
State,
PhantomData<In>,
PhantomData<O>,
);
impl<T: Fn(&In, &State) -> O, In, O, State> Node for FnNodeWithState<T, In, O, State> {
type Output<'a> = O where Self: 'a;
type Input<'a> = In where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
self.0(input.borrow(), &self.1)
}
}
impl<T: Fn(&In, &State) -> O, In, O, State> FnNodeWithState<T, In, O, State> {
pub fn new(f: T, state: State) -> Self {
FnNodeWithState(f, state, PhantomData::default(), PhantomData::default())
}
}

View file

@ -2,9 +2,7 @@
#[cfg(feature = "caching")]
pub mod caching;
pub mod generic;
#[cfg(feature = "memoization")]
pub mod memo;
pub mod ops;
pub mod structural;
pub mod value;
pub use graphene_core::*;

View file

@ -1,7 +1,55 @@
use graphene_core::{Exec, Node};
#![feature(generic_associated_types)]
use graphene_std::*;
/*fn mul(a: f32, b: f32) -> f32 {
a * b
}*/
mod mul {
use graphene_std::{
value::DefaultNode, value::DefaultRefNode, ArgNode, DynamicInput, ExecPtr, Node,
};
use std::{any::Any, ops::Deref};
const A: DefaultRefNode<f32> = DefaultRefNode::new();
const B: DefaultRefNode<f32> = DefaultRefNode::new();
type F32Node<'n> = &'n dyn ExecPtr<'n, f32, Output<'n> = &'n f32, Input<'n> = ()>;
pub struct MulNode<'n> {
a: F32Node<'n>,
b: F32Node<'n>,
}
impl<'n> Node for MulNode<'n> {
type Input<'i> = () where Self: 'i;
type Output<'o> = f32 where Self: 'o;
fn eval<'a, I>(&'a self, input: I) -> <Self as graphene_std::Node>::Output<'a>
where
I: std::borrow::Borrow<Self::Input<'a>>,
{
let a = self.a.fn_ptr();
let b = self.b.fn_ptr();
a * b
}
}
impl<'n> MulNode<'n> {
pub const fn new() -> Self {
Self { a: &A, b: &B }
}
}
impl DynamicInput for MulNode<'_> {
fn set_kwarg_by_name(&mut self, _: &str, _: &(dyn std::any::Any + 'static)) {
todo!()
}
fn set_arg_by_index(&mut self, index: usize, input: &(dyn std::any::Any + 'static)) {
match index {
0 => self.a = input.downcast_ref::<&dyn ExecPtr<'_, f32>>().unwrap(),
_ => todo!(),
}
}
}
}
fn main() {
let mut mul = mul::MulNode::new();
let int = value::IntNode::<32>;
let _add: u32 = ops::AddNode::<u32>::default().eval((int.exec(), int.exec()));
let fnode = generic::FnNode::new(|(a, b): &(i32, i32)| a - b);

View file

@ -1,6 +1,6 @@
use graphene_core::Node;
use graphene_core::{ExecPtr, Node};
use once_cell::sync::OnceCell;
use std::borrow::Borrow;
use std::{any::Any, borrow::Borrow, ops::Deref};
/// Caches the output of a given Node and acts as a proxy
pub struct CacheNode<'n, 'c, CachedNode: Node + 'c> {

View file

@ -1,37 +0,0 @@
use std::{borrow::Borrow, marker::PhantomData};
use graphene_core::Node;
#[derive(Default)]
pub struct AddNode<T>(PhantomData<T>);
impl<T: std::ops::Add + 'static + Copy> Node for AddNode<T> {
type Output<'a> = <T as std::ops::Add>::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
}
}
#[derive(Default)]
/// Destructures a Tuple of two values and returns the first one
pub struct FstNode<T, U>(PhantomData<T>, PhantomData<U>);
impl<T: Copy, U> Node for FstNode<T, U> {
type Output<'a> = &'a T where Self: 'a;
type Input<'a> = &'a (T, U) where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
let &(ref a, _) = input.borrow();
a
}
}
#[derive(Default)]
/// Destructures a Tuple of two values and returns the first one
pub struct SndNode<T, U>(PhantomData<T>, PhantomData<U>);
impl<T, U: Copy> Node for SndNode<T, U> {
type Output<'a> = &'a U where Self: 'a;
type Input<'a> = &'a (T, U) where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
let &(_, ref b) = input.borrow();
b
}
}

View file

@ -1,60 +0,0 @@
use std::{any::Any, borrow::Borrow};
use graphene_core::{DynamicInput, Node};
pub struct ComposeNode<'n, FIRST, SECOND> {
first: &'n FIRST,
second: &'n SECOND,
}
impl<'n, FIRST, SECOND> Node for ComposeNode<'n, FIRST, SECOND>
where
FIRST: Node,
SECOND: Node,
for<'a> FIRST::Output<'a>: Borrow<SECOND::Input<'a>>,
{
type Input<'a> = FIRST::Input<'a> where Self: 'a;
type Output<'a> = SECOND::Output<'a> where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
// evaluate the first node with the given input
// and then pipe the result from the first computation
// into the second node
let arg = self.first.eval(input);
self.second.eval(arg)
}
}
impl<'n, FIRST, SECOND> ComposeNode<'n, FIRST, SECOND>
where
FIRST: Node,
{
pub fn new(first: &'n FIRST, second: &'n SECOND) -> Self {
ComposeNode::<'n, FIRST, SECOND> { first, second }
}
}
pub trait After: Sized {
fn after<'a, First: Node>(&'a self, first: &'a First) -> ComposeNode<'a, First, Self> {
ComposeNode::new(first, self)
}
}
impl<Second: Node> After for Second {}
pub struct ProxyNode<T: DynamicInput>(T);
impl<T: DynamicInput> Node for ProxyNode<T> {
type Output<'a> = &'a T where Self: 'a;
type Input<'a> = &'a () where Self: 'a;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> Self::Output<'a> {
&self.0
}
}
impl<T: DynamicInput> DynamicInput for ProxyNode<T> {
fn set_kwarg_by_name(&mut self, name: &str, value: &dyn Any) {
self.0.set_kwarg_by_name(name, value)
}
fn set_arg_by_index(&mut self, index: usize, value: &dyn Any) {
self.0.set_arg_by_index(index, value)
}
}

View file

@ -1,38 +0,0 @@
use std::borrow::Borrow;
use graphene_core::Node;
pub struct IntNode<const N: u32>;
impl<const N: u32> Node for IntNode<N> {
type Output<'a> = u32;
type Input<'a> = ();
fn eval<'a, I: Borrow<Self::Input<'a>>>(&self, _input: I) -> u32 {
N
}
}
#[derive(Default)]
pub struct ValueNode<T>(T);
impl<T> Node for ValueNode<T> {
type Output<'o> = &'o T where T: 'o;
type Input<'i> = () where T: 'i;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> &T {
&self.0
}
}
#[rustfmt::skip]
pub trait OutputNode<'a, T>: Node<Output<'a> = T> where Self: 'a {}
impl<T: std::default::Default> DefaultNode for T {}
impl<T> ValueNode<T> {
pub fn new(value: T) -> ValueNode<T> {
ValueNode(value)
}
}
pub trait DefaultNode: Default {
fn default_node() -> ValueNode<Self> {
ValueNode::new(Self::default())
}
}