Replace GAT with lifetime on trait in node graph

This commit is contained in:
Dennis
2022-04-03 10:44:02 +02:00
committed by Keavon Chambers
parent 3243b80cf2
commit cb337fd338
10 changed files with 185 additions and 217 deletions

View File

@@ -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
[features]
const_default = ["const-default"]
default = ["const_default"]
[dependencies]
const-default = { version = "1.0", optional = true }

View File

@@ -2,11 +2,10 @@ use std::{borrow::Borrow, marker::PhantomData};
use crate::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;
impl<'n, T: Fn(&In) -> O, In, O: 'n> Node<'n, In> for FnNode<T, In, O> {
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())
}
}
@@ -23,11 +22,12 @@ pub struct FnNodeWithState<T: Fn(&In, &State) -> O, In, O, 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;
impl<'n, T: Fn(&In, &State) -> O, In, O: 'n, State> Node<'n, In>
for FnNodeWithState<T, In, O, State>
{
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)
}
}

View File

@@ -1,90 +1,57 @@
#![feature(generic_associated_types)]
pub mod generic;
pub mod ops;
pub mod structural;
pub mod value;
use std::{any::Any, borrow::Borrow, ops::Deref};
use std::any::Any;
#[rustfmt::skip]
pub trait Node {
// Self: 'a means that Self has to live at least as long as 'a (the input and output)
// this ensures that the node does not spontaneously disappear during evaluation
type Input<'i> where Self: 'i;
type Output<'o> where Self: 'o;
pub trait Node< 'n, Input> {
type Output : 'n;
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> {
fn eval_simple(&self, input: &I) -> &O;
pub trait Exec<'n> {
type Output: 'n;
fn exec(&'n self) -> Self::Output;
}
impl<T: for<'n> SimpleNode<'n, I, O>, I, O> Node for T {
type Input<'i> = &'i I where Self: 'i;
type Output<'o> = &'o O where Self: 'o;
fn eval<'a, In: Borrow<Self::Input<'a>>>(&'a self, input: In) -> Self::Output<'a> {
self.eval_simple(input.borrow())
impl<'n, T: Exec<'n>> Node<'n, ()> for T {
type Output = <Self as Exec<'n>>::Output;
fn eval(&'n self, _input: &()) -> Self::Output {
self.exec()
}
}
#[rustfmt::skip]
pub trait OutputNode<'a, T>: Node<Output<'a> = T> where Self: 'a {}
#[rustfmt::skip]
pub trait ArgNode<'a, T>: OutputNode<'a, T> + Node<Input<'a> = ()> where Self: 'a {}
pub trait AnyRef: Node {
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
where
Self::Input<'a>: 'static + Copy;
pub trait DynamicInput<'n> {
fn set_kwarg_by_name(
&mut self,
name: &str,
value: &'n dyn Node<'n, (), Output = &'n (dyn Any + 'static)>,
);
fn set_arg_by_index(
&mut self,
index: usize,
value: &'n dyn Node<'n, (), Output = &'n (dyn Any + 'static)>,
);
}
impl<T: Node> AnyRef for T {
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
pub trait AnyRef<'n, I>: Node<'n, I> {
fn any(&'n self, input: &'n dyn Any) -> Self::Output
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(
|| {
panic!(
"Node was evaluated with wrong input. The input has to be of type: {}",
std::any::type_name::<Self::Input<'a>>(),
)
},
))
self.eval(input.downcast_ref::<I>().unwrap_or_else(|| {
panic!(
"Node was evaluated with wrong input. The input has to be of type: {}",
std::any::type_name::<I>(),
)
}))
}
}
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);
}

View File

@@ -4,21 +4,20 @@ use crate::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
impl<'n, T: std::ops::Add + Copy + 'n> Node<'n, (T, T)> for AddNode<T> {
type Output = <T as std::ops::Add>::Output;
fn eval(&'n self, input: &'n (T, T)) -> T::Output {
let (ref a, ref b) = input.borrow();
*a + *b
}
}
#[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> {
impl<'n, T: Copy + 'n, U> Node<'n, (T, U)> for FstNode<T, U> {
type Output = &'n T;
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
let &(ref a, _) = input.borrow();
a
}
@@ -27,10 +26,9 @@ impl<T: Copy, U> Node for FstNode<T, U> {
#[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> {
impl<'n, T, U: Copy + 'n> Node<'n, (T, U)> for SndNode<T, U> {
type Output = &'n U;
fn eval(&'n self, input: &'n (T, U)) -> Self::Output {
let &(_, ref b) = input.borrow();
b
}

View File

@@ -1,60 +1,51 @@
use std::{any::Any, borrow::Borrow};
use std::marker::PhantomData;
use crate::{DynamicInput, Node};
pub struct ComposeNode<'n, FIRST, SECOND> {
use crate::Node;
pub struct ComposeNode<'n, Input, Inter, FIRST, SECOND> {
first: &'n FIRST,
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
FIRST: Node,
SECOND: Node,
for<'a> FIRST::Output<'a>: Borrow<SECOND::Input<'a>>,
First: Node<'n, Input, Output = &'n Inter>,
Second: Node<'n, Inter>, /*+ Node<<First as Node<Input>>::Output<'n>>*/
{
type Input<'a> = FIRST::Input<'a> where Self: 'a;
type Output<'a> = SECOND::Output<'a> where Self: 'a;
type Output = <Second as Node<'n, Inter>>::Output;
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
// and then pipe the result from the first computation
// into the second node
let arg = self.first.eval(input);
let arg: &Inter = self.first.eval(input);
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
FIRST: Node,
FIRST: Node<'n, Input>,
{
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 {
fn after<'a, First: Node>(&'a self, first: &'a First) -> ComposeNode<'a, First, Self> {
pub trait After<I>: Sized {
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)
}
}
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)
}
}
impl<Second: for<'n> Node<'n, I>, I> After<I> for Second {}

View File

@@ -1,39 +1,34 @@
use std::{borrow::Borrow, marker::PhantomData};
use const_default::ConstDefault;
use std::{any::Any, marker::PhantomData};
use crate::{Exec, Node};
pub struct IntNode<const N: u32>;
impl<const N: u32> Node for IntNode<N> {
type Input<'o> = ();
type Output<'i> = u32;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&self, _input: I) -> u32 {
impl<'n, const N: u32> Exec<'n> for IntNode<N> {
type Output = u32;
fn exec(&self) -> u32 {
N
}
}
#[derive(Default)]
pub struct ValueNode<T>(T);
impl<T> Node for ValueNode<T> {
type Input<'i> = () where T: 'i;
type Output<'o> = &'o T where T: 'o;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> &T {
pub struct ValueNode<'n, T>(T, PhantomData<&'n ()>);
impl<'n, T: 'n> Exec<'n> for ValueNode<'n, T> {
type Output = &'n T;
fn exec(&'n self) -> &'n T {
&self.0
}
}
impl<T> ValueNode<T> {
pub const fn new(value: T) -> ValueNode<T> {
ValueNode(value)
impl<'n, T> ValueNode<'n, T> {
pub const fn new(value: T) -> ValueNode<'n, T> {
ValueNode(value, PhantomData)
}
}
#[derive(Default)]
pub struct DefaultNode<T>(PhantomData<T>);
impl<T: Default> Node for DefaultNode<T> {
type Input<'i> = () where T: 'i;
type Output<'o> = T where T: 'o;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> T {
impl<'n, T: Default + 'n> Exec<'n> for DefaultNode<T> {
type Output = T;
fn exec(&self) -> T {
T::default()
}
}
@@ -43,23 +38,33 @@ impl<T> DefaultNode<T> {
}
}
pub struct DefaultRefNode<T>(ValueNode<T>);
impl<T: 'static> Node for DefaultRefNode<T> {
type Input<'i> = () where T: 'i;
type Output<'o> = &'o T where T: 'o;
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, _input: I) -> &'a T {
pub struct AnyRefNode<'n, N: Node<'n, I, Output = &'n O>, I, O>(
&'n N,
PhantomData<&'n I>,
PhantomData<&'n O>,
);
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()
}
}
#[cfg(feature = "const_default")]
impl<T: ConstDefault> DefaultRefNode<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> {
impl<'n, T: Default> Default for DefaultRefNode<'n, T> {
fn default() -> DefaultRefNode<'n, T> {
DefaultRefNode(ValueNode::new(T::default()))
}
}