Impl DynNode

This commit is contained in:
Dennis 2022-08-22 17:18:26 +02:00 committed by Keavon Chambers
parent f73836b838
commit 71f12db1e6
16 changed files with 433 additions and 84 deletions

161
node-graph/gstd/src/any.rs Normal file
View file

@ -0,0 +1,161 @@
use dyn_any::{DynAny, StaticType};
pub use graphene_core::{generic, ops /*, structural*/, Node, RefNode};
use std::marker::PhantomData;
fn fmt_error<I>() -> String {
format!("DynAnyNode: input is not of correct type, expected {}", std::any::type_name::<I>())
}
pub struct DynAnyNode<'n, N: RefNode<I>, I>(pub N, pub PhantomData<&'n I>);
/*impl<'n, I: StaticType, N: RefNode<'n, &'n I, Output = O> + 'n, O: 'n + StaticType> Node<&'n dyn DynAny<'n>> for DynAnyNode<'n, N, I> {
type Output = Box<dyn dyn_any::DynAny<'n> + 'n>;
fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output {
let output = self.0.eval_ref(dyn_any::downcast_ref(input).expect(fmt_error::<I>().as_str()));
Box::new(output)
}
}*/
/*
impl<'n, I: StaticType, N: RefNode<&'n I, Output = O> + Copy + 'n, O: 'n + StaticType> Node<&'n dyn DynAny<'n>> for &'n DynAnyNode<'n, N, I> {
type Output = Box<dyn dyn_any::DynAny<'n> + 'n>;
fn eval(self, input: &'n dyn DynAny<'n>) -> Self::Output {
let output = self.0.eval_ref(dyn_any::downcast_ref(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>())));
Box::new(output)
}
}
impl<'n, I: StaticType, N: RefNode<'n, I, Output = O> + 'n, O: 'n + StaticType> Node<Box<dyn DynAny<'n>>> for DynAnyNode<'n, N, I> {
type Output = Box<dyn dyn_any::DynAny<'n> + 'n>;
fn eval(self, input: Box<dyn DynAny<'n>>) -> Self::Output {
let input: Box<I> = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>()));
Box::new(self.0.eval_ref(*input))
}
}*/
impl<'n, I: StaticType, N: RefNode<I, Output = O> + Copy + 'n, O: 'n + StaticType> Node<Any<'n>> for &'n DynAnyNode<'n, N, I> {
type Output = Any<'n>;
fn eval(self, input: Any<'n>) -> Self::Output {
let input: Box<I> = dyn_any::downcast(input).unwrap_or_else(|| panic!("{}", fmt_error::<I>()));
Box::new(self.0.eval_ref(*input))
}
}
impl<'n, I: StaticType, N: RefNode<I, Output = O> + 'n + Copy, O: 'n + StaticType> DynAnyNode<'n, N, I>
where
N::Output: StaticType,
{
pub fn new(n: N) -> Self {
DynAnyNode(n, PhantomData)
}
pub fn into_erased(&'n self) -> impl RefNode<Any<'n>, Output = Any<'n>> {
self
}
/*pub fn as_ref(&'n self) -> &'n AnyNode<'n> {
self
}
pub fn into_ref_box(self) -> Box<dyn RefNode<Box<(dyn DynAny<'n> + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n> {
Box::new(self)
}*/
pub fn into_ref(self: &'n &'n Self) -> &'n (dyn RefNode<Any<'n>, Output = Any<'n>> + 'n) {
self
}
}
/*impl<'n: 'static, I: StaticType, N, O: 'n + StaticType> DynAnyNode<'n, N, I>
where
N: RefNode<I, Output = O> + 'n + Copy,
{
/*pub fn into_owned_erased(self) -> impl RefNode<Any<'n>, Output = Any<'n>> + 'n {
self
}*/
pub fn as_owned(&'n self) -> &'n (dyn RefNode<Any<'n>, Output = Any<'n>> + 'n) {
self
}
/*pub fn into_owned_box(&self) -> Box<dyn DynNodeOwned<'n>> {
Box::new(self)
}*/
}*/
pub type Any<'n> = Box<dyn DynAny<'n> + 'n>;
pub type AnyNode<'n> = dyn RefNode<Any<'n>, Output = Any<'n>>;
pub trait DynNodeRef<'n>: RefNode<&'n dyn DynAny<'n>, Output = Box<dyn DynAny<'n> + 'n>> + 'n {}
impl<'n, N: RefNode<&'n dyn DynAny<'n>, Output = Box<dyn DynAny<'n> + 'n>> + 'n> DynNodeRef<'n> for N {}
pub trait DynNodeOwned<'n>: RefNode<Any<'n>, Output = Any<'n>> + 'n {}
impl<'n, N: RefNode<Any<'n>, Output = Any<'n>> + 'n> DynNodeOwned<'n> for N {}
/*impl<'n> Node<Box<dyn DynAny<'n>>> for &'n Box<dyn DynNodeOwned<'n>> {
type Output = Box<dyn DynAny<'n> + 'n>;
fn eval(self, input: Box<dyn DynAny<'n>>) -> Self::Output {
(&*self as &dyn Node<Box<dyn DynAny<'n> + 'n>, Output = Box<dyn DynAny<'n> + 'n>>).eval(input)
}
}*/
#[cfg(test)]
mod test {
use super::*;
use graphene_core::ops::{AddNode, IdNode};
use graphene_core::value::ValueNode;
/*#[test]
pub fn dyn_input_compositon() {
use graphene_core::structural::After;
use graphene_core::structural::ComposeNode;
let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode);
let add: DynAnyNode<_, (u32, u32)> = DynAnyNode::new(AddNode);
let value: DynAnyNode<_, ()> = DynAnyNode::new(ValueNode((3u32, 4u32)));
let id = &id.as_owned();
let add = add.as_owned();
let value = value.as_owned();
/*let computation = ComposeNode::new(value, add);
let computation = id.after(add.after(value));
let result: u32 = *dyn_any::downcast(computation.eval(&())).unwrap();*/
}*/
#[test]
#[should_panic]
pub fn dyn_input_invalid_eval_panic() {
static ADD: &DynAnyNode<&AddNode, (u32, u32)> = &DynAnyNode(&AddNode, PhantomData);
let add = ADD.into_ref();
add.eval_ref(Box::new(&("32", 32u32)));
}
/*#[test]
pub fn dyn_input_storage() {
let mut vec: Vec<Box<dyn DynNodeRef>> = vec![];
let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode);
let add: DynAnyNode<_, (u32, u32)> = DynAnyNode::new(AddNode);
let value: DynAnyNode<_, ()> = DynAnyNode::new(ValueNode((3u32, 4u32)));
vec.push(add.into_ref_box());
vec.push(id.into_ref_box());
vec.push(value.into_ref_box());
}*/
#[test]
pub fn dyn_input_storage_composition() {
let mut vec: Vec<&(dyn RefNode<Any, Output = Any>)> = vec![];
//let id: DynAnyNode<_, u32> = DynAnyNode::new(IdNode);
let value: &DynAnyNode<&ValueNode<(u32, u32)>, ()> = &DynAnyNode(&ValueNode((3u32, 4u32)), PhantomData);
let add: &DynAnyNode<&AddNode, &(u32, u32)> = &DynAnyNode(&AddNode, PhantomData);
let value_ref = (&value).into_ref();
let add_ref = (&add).into_ref();
vec.push(value_ref);
vec.push(add_ref);
//vec.push(add.as_owned());
//vec.push(id.as_owned());
//let vec = vec.leak();
let n_value = vec[0];
let n_add = vec[1];
//let id = vec[2];
assert_eq!(*(dyn_any::downcast::<&(u32, u32)>(n_value.eval_ref(Box::new(()))).unwrap()), &(3u32, 4u32));
fn compose<'n>(
first: &'n (dyn RefNode<Box<(dyn DynAny<'n> + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n),
second: &'n (dyn RefNode<Box<(dyn DynAny<'n> + 'n)>, Output = Box<(dyn DynAny<'n> + 'n)>> + 'n),
input: Any<'n>,
) -> Any<'n> {
second.eval_ref(first.eval_ref(input))
}
let result = compose(n_value, n_add, Box::new(()));
assert_eq!(*dyn_any::downcast::<u32>(result).unwrap(), 7u32);
//let result: u32 = *dyn_any::downcast(computation.eval(Box::new(()))).unwrap();
}
}

View file

@ -0,0 +1,94 @@
/*
use core::marker::PhantomData;
use graphene_core::{structural::After, structural::ComposeNode, value::ValueNode, Node, RefNode};
use crate::any::Any;
use crate::any::DynAnyNode;
pub trait DocumentNode<I>: RefNode<I> {
fn input_hints(&self) -> &'static [&'static str];
fn input_types(&self) -> &'static [&'static str];
fn inputs(&self) -> Vec<String> {
self.input_hints().iter().zip(self.input_types()).map(|(a, b)| format!("{}{}", a, b)).collect()
}
}
struct InjectNode<N: Node<I> + Copy, I>(N, PhantomData<I>);
impl<'n, N: Node<I> + Copy, I> Node<&'n [&'n AnyNode<'n>]> for &'n InjectNode<N, I> {
type Output = Box<dyn RefNode<Any<'n>, Output = Any<'n>> + 'n>;
fn eval(self, input: &'n [&'n AnyNode<'n>]) -> Self::Output {
assert_eq!(input.len(), 1);
Box::new(ComposeNode::new(&DynAnyNode(input[0]), &DynAnyNode(self.0)))
}
}
impl<N: Node<I> + Copy, I> InjectNode<N, I> {
const TYPES: &'static [&'static str] = &[core::any::type_name::<I>()];
const HINTS: &'static [&'static str] = &["input: "];
}
impl<'n, N: Node<I> + Copy, I> DocumentNode<&'n [&'n AnyNode<'n>]> for &'n InjectNode<N, I> {
fn input_hints(&self) -> &'static [&'static str] {
InjectNode::<N, I>::HINTS
}
fn input_types(&self) -> &'static [&'static str] {
InjectNode::<N, I>::TYPES
}
}
pub type NodeId = u32;
type AnyNode<'n> = dyn RefNode<Any<'n>, Output = Any<'n>>;
pub struct DocumentGraphNode<'n> {
pub id: NodeId,
pub inputs: Vec<NodeInput>,
pub node: NodeWrapper<'n>,
}
impl<'n> DocumentGraphNode<'n> {
pub fn new(id: NodeId, inputs: Vec<NodeInput>, node: NodeWrapper<'n>) -> Self {
Self { id, inputs, node }
}
}
pub struct NodeWrapper<'n> {
pub node: &'n (dyn Node<Any<'n>, Output = Any<'n>> + 'n),
pub path: &'static str,
}
impl<'n> NodeWrapper<'n> {
pub fn new(node: &'n (dyn Node<Any<'n>, Output = Any<'n>> + 'n), path: &'static str) -> Self {
Self { node, path }
}
}
pub enum NodeInput {
Node(NodeId),
Default(ValueNode<Any<'static>>),
}
#[cfg(test)]
mod test {
use crate::any::DynAnyNode;
use super::*;
use graphene_core::value::ValueNode;
#[test]
fn inject_node() {
let inject_node = InjectNode(&ValueNode(4u32), PhantomData);
use super::DocumentNode;
/*assert_eq!(
(&inject_node as &dyn DocumentNode<&[&AnyNode], Output = ComposeNode<&AnyNode, ValueNode<u32>, ()>>).inputs(),
vec!["input: ()"]
);*/
let any_inject = DynAnyNode(&inject_node, PhantomData);
let any_inject = Box::leak(Box::new(any_inject));
let wrapped = NodeWrapper::new((&any_inject) as &(dyn Node<&[&AnyNode], Output = Any>), "grahpene_core::document::InjectNode");
let document_node = DocumentGraphNode::new(0, vec![], wrapped);
}
}
*/

View file

@ -1,22 +1,17 @@
//pub mod value;
pub use graphene_core::{generic, ops /*, structural*/};
//#![feature(const_type_name)]
#[cfg(feature = "memoization")]
pub mod memo;
pub mod raster;
pub mod any;
pub mod document;
pub use graphene_core::*;
/*use dyn_any::DynAny;
pub type DynNode<'n, T> = &'n (dyn Node<'n, Output = T> + 'n);
pub type DynAnyNode<'n> = &'n (dyn Node<'n, Output = &'n dyn DynAny<'n>> + 'n);
pub trait DynamicInput<'n> {
fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>);
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>);
}
*/
use quote::quote;
use syn::{Expr, ExprPath, Type};
@ -31,6 +26,7 @@ pub struct NodeGraph {
pub output: Type,
pub input: Type,
}
pub enum NodeKind {
Value(Expr),
Input,

View file

@ -99,6 +99,7 @@ fn main() {
];
//println!("{}", node_graph(1));
//
let _nodegraph = NodeGraph {
nodes,

View file

@ -1,6 +1,5 @@
use graphene_core::{Cache, Node};
use once_cell::sync::OnceCell;
use std::marker::PhantomData;
/// Caches the output of a given Node and acts as a proxy
pub struct CacheNode<CachedNode: Node<I>, I> {

View file

@ -2,13 +2,7 @@ use core::marker::PhantomData;
use graphene_core::ops::FlatMapResultNode;
use graphene_core::raster::color::Color;
use graphene_core::structural::{ComposeNode, ConsNode};
use graphene_core::{
generic::FnNode,
ops::MapResultNode,
structural::{After, AfterRef},
value::ValueNode,
Node,
};
use graphene_core::{generic::FnNode, ops::MapResultNode, structural::After, value::ValueNode, Node};
use image::Pixel;
use std::path::Path;