mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-24 08:05:04 +00:00
Replace GAT with lifetime on trait in node graph
This commit is contained in:
parent
3243b80cf2
commit
cb337fd338
10 changed files with 185 additions and 217 deletions
9
node-graph/Cargo.lock
generated
9
node-graph/Cargo.lock
generated
|
@ -93,12 +93,6 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const-default"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b396d1f76d455557e1218ec8066ae14bba60b4b36ecd55577ba979f5db7ecaa"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "countme"
|
name = "countme"
|
||||||
version = "3.0.1"
|
version = "3.0.1"
|
||||||
|
@ -241,9 +235,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "graphene-core"
|
name = "graphene-core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
|
||||||
"const-default",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "graphene-std"
|
name = "graphene-std"
|
||||||
|
|
|
@ -6,9 +6,5 @@ description = "Api definitions for graphene"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[features]
|
|
||||||
const_default = ["const-default"]
|
|
||||||
default = ["const_default"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
const-default = { version = "1.0", optional = true }
|
|
||||||
|
|
|
@ -2,11 +2,10 @@ use std::{borrow::Borrow, marker::PhantomData};
|
||||||
|
|
||||||
use crate::Node;
|
use crate::Node;
|
||||||
pub struct FnNode<T: Fn(&In) -> O, In, O>(T, PhantomData<In>, PhantomData<O>);
|
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> {
|
impl<'n, T: Fn(&In) -> O, In, O: 'n> Node<'n, In> for FnNode<T, In, O> {
|
||||||
type Output<'a> = O where Self: 'a;
|
type Output = O;
|
||||||
type Input<'a> = In where Self: 'a;
|
|
||||||
|
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
fn eval(&'n self, input: &'n In) -> Self::Output {
|
||||||
self.0(input.borrow())
|
self.0(input.borrow())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,11 +22,12 @@ pub struct FnNodeWithState<T: Fn(&In, &State) -> O, In, O, State>(
|
||||||
PhantomData<In>,
|
PhantomData<In>,
|
||||||
PhantomData<O>,
|
PhantomData<O>,
|
||||||
);
|
);
|
||||||
impl<T: Fn(&In, &State) -> O, In, O, State> Node for FnNodeWithState<T, In, O, State> {
|
impl<'n, T: Fn(&In, &State) -> O, In, O: 'n, State> Node<'n, In>
|
||||||
type Output<'a> = O where Self: 'a;
|
for FnNodeWithState<T, In, O, State>
|
||||||
type Input<'a> = In where Self: 'a;
|
{
|
||||||
|
type Output = O;
|
||||||
|
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
fn eval(&'n self, input: &'n In) -> Self::Output {
|
||||||
self.0(input.borrow(), &self.1)
|
self.0(input.borrow(), &self.1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,90 +1,57 @@
|
||||||
#![feature(generic_associated_types)]
|
|
||||||
pub mod generic;
|
pub mod generic;
|
||||||
pub mod ops;
|
pub mod ops;
|
||||||
pub mod structural;
|
pub mod structural;
|
||||||
pub mod value;
|
pub mod value;
|
||||||
|
|
||||||
use std::{any::Any, borrow::Borrow, ops::Deref};
|
use std::any::Any;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub trait Node {
|
pub trait Node< 'n, Input> {
|
||||||
// Self: 'a means that Self has to live at least as long as 'a (the input and output)
|
type Output : 'n;
|
||||||
// this ensures that the node does not spontaneously disappear during evaluation
|
|
||||||
type Input<'i> where Self: 'i;
|
|
||||||
type Output<'o> where Self: 'o;
|
|
||||||
|
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a>;
|
fn eval(&'n self, input: &'n Input) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SimpleNode<'n, I, O> {
|
pub trait Exec<'n> {
|
||||||
fn eval_simple(&self, input: &I) -> &O;
|
type Output: 'n;
|
||||||
|
fn exec(&'n self) -> Self::Output;
|
||||||
}
|
}
|
||||||
|
impl<'n, T: Exec<'n>> Node<'n, ()> for T {
|
||||||
impl<T: for<'n> SimpleNode<'n, I, O>, I, O> Node for T {
|
type Output = <Self as Exec<'n>>::Output;
|
||||||
type Input<'i> = &'i I where Self: 'i;
|
fn eval(&'n self, _input: &()) -> Self::Output {
|
||||||
type Output<'o> = &'o O where Self: 'o;
|
self.exec()
|
||||||
|
|
||||||
fn eval<'a, In: Borrow<Self::Input<'a>>>(&'a self, input: In) -> Self::Output<'a> {
|
|
||||||
self.eval_simple(input.borrow())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
pub trait DynamicInput<'n> {
|
||||||
pub trait OutputNode<'a, T>: Node<Output<'a> = T> where Self: 'a {}
|
fn set_kwarg_by_name(
|
||||||
#[rustfmt::skip]
|
&mut self,
|
||||||
pub trait ArgNode<'a, T>: OutputNode<'a, T> + Node<Input<'a> = ()> where Self: 'a {}
|
name: &str,
|
||||||
|
value: &'n dyn Node<'n, (), Output = &'n (dyn Any + 'static)>,
|
||||||
pub trait AnyRef: Node {
|
);
|
||||||
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
|
fn set_arg_by_index(
|
||||||
where
|
&mut self,
|
||||||
Self::Input<'a>: 'static + Copy;
|
index: usize,
|
||||||
|
value: &'n dyn Node<'n, (), Output = &'n (dyn Any + 'static)>,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Node> AnyRef for T {
|
pub trait AnyRef<'n, I>: Node<'n, I> {
|
||||||
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
|
fn any(&'n self, input: &'n dyn Any) -> Self::Output
|
||||||
where
|
where
|
||||||
Self::Input<'a>: 'static + Copy,
|
I: 'static + Copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'n, T: Node<'n, I>, I> AnyRef<'n, I> for T {
|
||||||
|
fn any(&'n self, input: &'n dyn Any) -> Self::Output
|
||||||
|
where
|
||||||
|
I: 'static + Copy,
|
||||||
{
|
{
|
||||||
self.eval::<&Self::Input<'a>>(input.downcast_ref::<Self::Input<'a>>().unwrap_or_else(
|
self.eval(input.downcast_ref::<I>().unwrap_or_else(|| {
|
||||||
|| {
|
panic!(
|
||||||
panic!(
|
"Node was evaluated with wrong input. The input has to be of type: {}",
|
||||||
"Node was evaluated with wrong input. The input has to be of type: {}",
|
std::any::type_name::<I>(),
|
||||||
std::any::type_name::<Self::Input<'a>>(),
|
)
|
||||||
)
|
}))
|
||||||
},
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Ref<T>: Node {}
|
|
||||||
impl<'a, T: 'a, N: Node<Output<'a> = &'a T> + 'a> Ref<T> for N {}
|
|
||||||
|
|
||||||
pub trait ExecPtr<'n, T>: Node {
|
|
||||||
fn fn_ptr(&self) -> &T;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'n, T: 'n, N: Ref<T>> ExecPtr<'n, T> for N
|
|
||||||
where
|
|
||||||
for<'a> &'a (): Borrow<<Self as Node>::Input<'a>>,
|
|
||||||
for<'a> &'a T: From<N::Output<'a>>,
|
|
||||||
{
|
|
||||||
fn fn_ptr(&self) -> &T {
|
|
||||||
let value: &T = self.eval(&()).into();
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Exec: Node
|
|
||||||
where
|
|
||||||
for<'a> &'a (): Borrow<<Self as Node>::Input<'a>>,
|
|
||||||
{
|
|
||||||
fn exec(&self) -> Self::Output<'_> {
|
|
||||||
self.eval(&())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl<T: Node> Exec for T where for<'a> &'a (): Borrow<<T as Node>::Input<'a>> {}
|
|
||||||
|
|
||||||
pub trait DynamicInput {
|
|
||||||
fn set_kwarg_by_name(&mut self, name: &str, value: &dyn Any);
|
|
||||||
fn set_arg_by_index(&mut self, index: usize, value: &dyn Any);
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,21 +4,20 @@ use crate::Node;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct AddNode<T>(PhantomData<T>);
|
pub struct AddNode<T>(PhantomData<T>);
|
||||||
impl<T: std::ops::Add + 'static + Copy> Node for AddNode<T> {
|
impl<'n, T: std::ops::Add + Copy + 'n> Node<'n, (T, T)> for AddNode<T> {
|
||||||
type Output<'a> = <T as std::ops::Add>::Output;
|
type Output = <T as std::ops::Add>::Output;
|
||||||
type Input<'a> = (T, T);
|
fn eval(&'n self, input: &'n (T, T)) -> T::Output {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> T::Output {
|
let (ref a, ref b) = input.borrow();
|
||||||
input.borrow().0 + input.borrow().1
|
*a + *b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
/// Destructures a Tuple of two values and returns the first one
|
/// Destructures a Tuple of two values and returns the first one
|
||||||
pub struct FstNode<T, U>(PhantomData<T>, PhantomData<U>);
|
pub struct FstNode<T, U>(PhantomData<T>, PhantomData<U>);
|
||||||
impl<T: Copy, U> Node for FstNode<T, U> {
|
impl<'n, T: Copy + 'n, U> Node<'n, (T, U)> for FstNode<T, U> {
|
||||||
type Output<'a> = &'a T where Self: 'a;
|
type Output = &'n T;
|
||||||
type Input<'a> = &'a (T, U) where Self: 'a;
|
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
|
||||||
let &(ref a, _) = input.borrow();
|
let &(ref a, _) = input.borrow();
|
||||||
a
|
a
|
||||||
}
|
}
|
||||||
|
@ -27,10 +26,9 @@ impl<T: Copy, U> Node for FstNode<T, U> {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
/// Destructures a Tuple of two values and returns the first one
|
/// Destructures a Tuple of two values and returns the first one
|
||||||
pub struct SndNode<T, U>(PhantomData<T>, PhantomData<U>);
|
pub struct SndNode<T, U>(PhantomData<T>, PhantomData<U>);
|
||||||
impl<T, U: Copy> Node for SndNode<T, U> {
|
impl<'n, T, U: Copy + 'n> Node<'n, (T, U)> for SndNode<T, U> {
|
||||||
type Output<'a> = &'a U where Self: 'a;
|
type Output = &'n U;
|
||||||
type Input<'a> = &'a (T, U) where Self: 'a;
|
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
|
||||||
let &(_, ref b) = input.borrow();
|
let &(_, ref b) = input.borrow();
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,51 @@
|
||||||
use std::{any::Any, borrow::Borrow};
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use crate::{DynamicInput, Node};
|
use crate::Node;
|
||||||
pub struct ComposeNode<'n, FIRST, SECOND> {
|
|
||||||
|
pub struct ComposeNode<'n, Input, Inter, FIRST, SECOND> {
|
||||||
first: &'n FIRST,
|
first: &'n FIRST,
|
||||||
second: &'n SECOND,
|
second: &'n SECOND,
|
||||||
|
_phantom: PhantomData<&'n Input>,
|
||||||
|
_phantom2: PhantomData<Inter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, FIRST, SECOND> Node for ComposeNode<'n, FIRST, SECOND>
|
impl<'n, Input: 'n, Inter: 'n, First, Second> Node<'n, Input>
|
||||||
|
for ComposeNode<'n, Input, Inter, First, Second>
|
||||||
where
|
where
|
||||||
FIRST: Node,
|
First: Node<'n, Input, Output = &'n Inter>,
|
||||||
SECOND: Node,
|
Second: Node<'n, Inter>, /*+ Node<<First as Node<Input>>::Output<'n>>*/
|
||||||
for<'a> FIRST::Output<'a>: Borrow<SECOND::Input<'a>>,
|
|
||||||
{
|
{
|
||||||
type Input<'a> = FIRST::Input<'a> where Self: 'a;
|
type Output = <Second as Node<'n, Inter>>::Output;
|
||||||
type Output<'a> = SECOND::Output<'a> where Self: 'a;
|
|
||||||
|
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
fn eval(&'n self, input: &'n Input) -> Self::Output {
|
||||||
// evaluate the first node with the given input
|
// evaluate the first node with the given input
|
||||||
// and then pipe the result from the first computation
|
// and then pipe the result from the first computation
|
||||||
// into the second node
|
// into the second node
|
||||||
let arg = self.first.eval(input);
|
let arg: &Inter = self.first.eval(input);
|
||||||
self.second.eval(arg)
|
self.second.eval(arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, FIRST, SECOND> ComposeNode<'n, FIRST, SECOND>
|
impl<'n, Input, Inter, FIRST, SECOND> ComposeNode<'n, Input, Inter, FIRST, SECOND>
|
||||||
where
|
where
|
||||||
FIRST: Node,
|
FIRST: Node<'n, Input>,
|
||||||
{
|
{
|
||||||
pub fn new(first: &'n FIRST, second: &'n SECOND) -> Self {
|
pub fn new(first: &'n FIRST, second: &'n SECOND) -> Self {
|
||||||
ComposeNode::<'n, FIRST, SECOND> { first, second }
|
ComposeNode::<'n, Input, Inter, FIRST, SECOND> {
|
||||||
|
first,
|
||||||
|
second,
|
||||||
|
_phantom: PhantomData,
|
||||||
|
_phantom2: PhantomData,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait After: Sized {
|
pub trait After<I>: Sized {
|
||||||
fn after<'a, First: Node>(&'a self, first: &'a First) -> ComposeNode<'a, First, Self> {
|
fn after<'n, First: Node<'n, I>>(
|
||||||
|
&'n self,
|
||||||
|
first: &'n First,
|
||||||
|
) -> ComposeNode<'n, I, <First as Node<'n, I>>::Output, First, Self> {
|
||||||
ComposeNode::new(first, self)
|
ComposeNode::new(first, self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<Second: Node> After for Second {}
|
impl<Second: for<'n> Node<'n, I>, I> After<I> 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,39 +1,34 @@
|
||||||
use std::{borrow::Borrow, marker::PhantomData};
|
use std::{any::Any, marker::PhantomData};
|
||||||
|
|
||||||
use const_default::ConstDefault;
|
|
||||||
|
|
||||||
use crate::{Exec, Node};
|
use crate::{Exec, Node};
|
||||||
|
|
||||||
pub struct IntNode<const N: u32>;
|
pub struct IntNode<const N: u32>;
|
||||||
impl<const N: u32> Node for IntNode<N> {
|
impl<'n, const N: u32> Exec<'n> for IntNode<N> {
|
||||||
type Input<'o> = ();
|
type Output = u32;
|
||||||
type Output<'i> = u32;
|
fn exec(&self) -> u32 {
|
||||||
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<'n, T>(T, PhantomData<&'n ()>);
|
||||||
impl<T> Node for ValueNode<T> {
|
impl<'n, T: 'n> Exec<'n> for ValueNode<'n, T> {
|
||||||
type Input<'i> = () where T: 'i;
|
type Output = &'n T;
|
||||||
type Output<'o> = &'o T where T: 'o;
|
fn exec(&'n self) -> &'n T {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> &T {
|
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<T> ValueNode<T> {
|
impl<'n, T> ValueNode<'n, T> {
|
||||||
pub const fn new(value: T) -> ValueNode<T> {
|
pub const fn new(value: T) -> ValueNode<'n, T> {
|
||||||
ValueNode(value)
|
ValueNode(value, PhantomData)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DefaultNode<T>(PhantomData<T>);
|
pub struct DefaultNode<T>(PhantomData<T>);
|
||||||
impl<T: Default> Node for DefaultNode<T> {
|
impl<'n, T: Default + 'n> Exec<'n> for DefaultNode<T> {
|
||||||
type Input<'i> = () where T: 'i;
|
type Output = T;
|
||||||
type Output<'o> = T where T: 'o;
|
fn exec(&self) -> T {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> T {
|
|
||||||
T::default()
|
T::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,23 +38,33 @@ impl<T> DefaultNode<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DefaultRefNode<T>(ValueNode<T>);
|
pub struct AnyRefNode<'n, N: Node<'n, I, Output = &'n O>, I, O>(
|
||||||
impl<T: 'static> Node for DefaultRefNode<T> {
|
&'n N,
|
||||||
type Input<'i> = () where T: 'i;
|
PhantomData<&'n I>,
|
||||||
type Output<'o> = &'o T where T: 'o;
|
PhantomData<&'n O>,
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> &'a T {
|
);
|
||||||
|
impl<'n, N: Node<'n, I, Output = &'n O>, I, O: 'static> Node<'n, I> for AnyRefNode<'n, N, I, O> {
|
||||||
|
type Output = &'n (dyn Any + 'static);
|
||||||
|
fn eval(&'n self, input: &'n I) -> Self::Output {
|
||||||
|
let value: &O = self.0.eval(input);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'n, N: Node<'n, I, Output = &'n O>, I, O: 'static> AnyRefNode<'n, N, I, O> {
|
||||||
|
pub fn new(n: &'n N) -> AnyRefNode<'n, N, I, O> {
|
||||||
|
AnyRefNode(n, PhantomData, PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DefaultRefNode<'n, T>(ValueNode<'n, T>);
|
||||||
|
impl<'n, T: 'n> Exec<'n> for DefaultRefNode<'n, T> {
|
||||||
|
type Output = &'n T;
|
||||||
|
fn exec(&'n self) -> &'n T {
|
||||||
self.0.exec()
|
self.0.exec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(feature = "const_default")]
|
impl<'n, T: Default> Default for DefaultRefNode<'n, T> {
|
||||||
impl<T: ConstDefault> DefaultRefNode<T> {
|
fn default() -> DefaultRefNode<'n, T> {
|
||||||
pub const fn new() -> DefaultRefNode<T> {
|
|
||||||
DefaultRefNode(ValueNode::new(T::DEFAULT))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "const_default"))]
|
|
||||||
impl<T: Default> DefaultRefNode<T> {
|
|
||||||
pub fn new() -> DefaultRefNode<T> {
|
|
||||||
DefaultRefNode(ValueNode::new(T::default()))
|
DefaultRefNode(ValueNode::new(T::default()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(generic_associated_types)]
|
//#![feature(generic_associated_types)]
|
||||||
|
|
||||||
#[cfg(feature = "caching")]
|
#[cfg(feature = "caching")]
|
||||||
pub mod caching;
|
pub mod caching;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#![feature(generic_associated_types)]
|
//#![feature(generic_associated_types)]
|
||||||
|
use graphene_std::value::{AnyRefNode, ValueNode};
|
||||||
use graphene_std::*;
|
use graphene_std::*;
|
||||||
|
|
||||||
/*fn mul(a: f32, b: f32) -> f32 {
|
/*fn mul(a: f32, b: f32) -> f32 {
|
||||||
|
@ -6,41 +7,50 @@ use graphene_std::*;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
mod mul {
|
mod mul {
|
||||||
use graphene_std::{
|
use graphene_std::{DynamicInput, Node};
|
||||||
value::DefaultNode, value::DefaultRefNode, ArgNode, DynamicInput, ExecPtr, Node,
|
use std::any::Any;
|
||||||
};
|
type F32Node<'n> = &'n (dyn Node<'n, (), Output = &'n (dyn Any + 'static)> + 'n);
|
||||||
use std::{any::Any, ops::Deref};
|
#[derive(Copy, Clone)]
|
||||||
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> {
|
pub struct MulNode<'n> {
|
||||||
a: F32Node<'n>,
|
pub a: Option<F32Node<'n>>,
|
||||||
b: F32Node<'n>,
|
pub b: Option<F32Node<'n>>,
|
||||||
}
|
}
|
||||||
impl<'n> Node for MulNode<'n> {
|
impl<'n> Node<'n, ()> for MulNode<'n> {
|
||||||
type Input<'i> = () where Self: 'i;
|
type Output = f32;
|
||||||
type Output<'o> = f32 where Self: 'o;
|
fn eval(&'n self, _input: &'n ()) -> <Self as graphene_std::Node<'n, ()>>::Output {
|
||||||
fn eval<'a, I>(&'a self, input: I) -> <Self as graphene_std::Node>::Output<'a>
|
let a: &f32 = self
|
||||||
where
|
.a
|
||||||
I: std::borrow::Borrow<Self::Input<'a>>,
|
.map(|v| v.eval(&()).downcast_ref().unwrap())
|
||||||
{
|
.unwrap_or(&2.);
|
||||||
let a = self.a.fn_ptr();
|
let b: &f32 = self
|
||||||
let b = self.b.fn_ptr();
|
.b
|
||||||
|
.map(|v| v.eval(&()).downcast_ref().unwrap())
|
||||||
|
.unwrap_or(&1.);
|
||||||
a * b
|
a * b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'n> MulNode<'n> {
|
macro_rules! new {
|
||||||
pub const fn new() -> Self {
|
() => {
|
||||||
Self { a: &A, b: &B }
|
mul::MulNode { a: None, b: None }
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
impl DynamicInput for MulNode<'_> {
|
pub(crate) use new;
|
||||||
fn set_kwarg_by_name(&mut self, _: &str, _: &(dyn std::any::Any + 'static)) {
|
|
||||||
|
impl<'i: 'f, 'f> DynamicInput<'f> for MulNode<'f> {
|
||||||
|
fn set_kwarg_by_name(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
value: &'f dyn Node<'f, (), Output = &'f (dyn Any + 'static)>,
|
||||||
|
) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
fn set_arg_by_index(&mut self, index: usize, input: &(dyn std::any::Any + 'static)) {
|
fn set_arg_by_index(
|
||||||
|
&mut self,
|
||||||
|
index: usize,
|
||||||
|
value: &'f dyn Node<'f, (), Output = &'f (dyn Any + 'static)>,
|
||||||
|
) {
|
||||||
match index {
|
match index {
|
||||||
0 => self.a = input.downcast_ref::<&dyn ExecPtr<'_, f32>>().unwrap(),
|
0 => self.a = Some(value),
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,14 +58,26 @@ mod mul {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut mul = mul::MulNode::new();
|
//let mut mul = mul::MulNode::new();
|
||||||
|
let a = ValueNode::new(3.4f32);
|
||||||
|
let any_a = AnyRefNode::new(&a);
|
||||||
|
let _mul2 = mul::MulNode {
|
||||||
|
a: None,
|
||||||
|
b: Some(&any_a),
|
||||||
|
};
|
||||||
|
let mut mul2 = mul::new!();
|
||||||
|
//let cached = memo::CacheNode::new(&mul1);
|
||||||
|
//let foo = value::AnyRefNode::new(&cached);
|
||||||
|
mul2.set_arg_by_index(0, &any_a);
|
||||||
|
|
||||||
let int = value::IntNode::<32>;
|
let int = value::IntNode::<32>;
|
||||||
let _add: u32 = ops::AddNode::<u32>::default().eval((int.exec(), int.exec()));
|
int.eval(&());
|
||||||
let fnode = generic::FnNode::new(|(a, b): &(i32, i32)| a - b);
|
println!("{}", mul2.eval(&()));
|
||||||
|
//let _add: u32 = ops::AddNode::<u32>::default().eval((int.exec(), int.exec()));
|
||||||
|
//let fnode = generic::FnNode::new(|(a, b): &(i32, i32)| a - b);
|
||||||
//let sub = fnode.any(&("a", 2));
|
//let sub = fnode.any(&("a", 2));
|
||||||
let cache = memo::CacheNode::new(&fnode);
|
//let cache = memo::CacheNode::new(&fnode);
|
||||||
let cached_result = cache.eval(&(2, 3));
|
//let cached_result = cache.eval(&(2, 3));
|
||||||
|
|
||||||
println!("{}", cached_result)
|
//println!("{}", cached_result)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,23 @@
|
||||||
use graphene_core::{ExecPtr, Node};
|
use graphene_core::Node;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::{any::Any, borrow::Borrow, ops::Deref};
|
|
||||||
|
|
||||||
/// 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, 'c, CachedNode: Node + 'c> {
|
pub struct CacheNode<'n, CachedNode: Node<'n, Input>, Input> {
|
||||||
node: &'n CachedNode,
|
node: &'n CachedNode,
|
||||||
cache: OnceCell<CachedNode::Output<'c>>,
|
cache: OnceCell<CachedNode::Output>,
|
||||||
}
|
}
|
||||||
impl<'n: 'c, 'c, CashedNode: Node> Node for CacheNode<'n, 'c, CashedNode> {
|
impl<'n, CashedNode: Node<'n, Input>, Input> Node<'n, Input> for CacheNode<'n, CashedNode, Input> {
|
||||||
type Output<'a> = &'a CashedNode::Output<'c> where 'c: 'a;
|
type Output = &'n CashedNode::Output;
|
||||||
type Input<'a> = CashedNode::Input<'c> where 'c: 'a;
|
fn eval(&'n self, input: &'n Input) -> Self::Output {
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
|
||||||
self.cache.get_or_init(|| self.node.eval(input))
|
self.cache.get_or_init(|| self.node.eval(input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, 'c, CachedNode: Node> CacheNode<'n, 'c, CachedNode> {
|
impl<'n, CachedNode: Node<'n, Input>, Input> CacheNode<'n, CachedNode, Input> {
|
||||||
pub fn clear(&'n mut self) {
|
pub fn clear(&'n mut self) {
|
||||||
self.cache = OnceCell::new();
|
self.cache = OnceCell::new();
|
||||||
}
|
}
|
||||||
pub fn new(node: &'n CachedNode) -> CacheNode<'n, 'c, CachedNode> {
|
pub fn new(node: &'n CachedNode) -> CacheNode<'n, CachedNode, Input> {
|
||||||
CacheNode {
|
CacheNode {
|
||||||
node,
|
node,
|
||||||
cache: OnceCell::new(),
|
cache: OnceCell::new(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue