Bump dyn-any version + format code

This commit is contained in:
Dennis
2022-08-04 09:08:48 +02:00
parent 30af1ba8db
commit 5e9545322e
12 changed files with 464 additions and 513 deletions
Generated
+2 -2
View File
@@ -283,14 +283,14 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
[[package]] [[package]]
name = "dyn-any" name = "dyn-any"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"dyn-any-derive", "dyn-any-derive",
] ]
[[package]] [[package]]
name = "dyn-any-derive" name = "dyn-any-derive"
version = "0.2.0" version = "0.2.1"
dependencies = [ dependencies = [
"dyn-any", "dyn-any",
"proc-macro2", "proc-macro2",
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "dyn-any" name = "dyn-any"
version = "0.2.0" version = "0.2.1"
edition = "2021" edition = "2021"
authors = ["Dennis Kobert <dennis@kobert.dev>"] authors = ["Dennis Kobert <dennis@kobert.dev>"]
+1 -1
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "dyn-any-derive" name = "dyn-any-derive"
version = "0.2.0" version = "0.2.1"
edition = "2021" edition = "2021"
authors = ["Dennis Kobert"] authors = ["Dennis Kobert"]
+50 -52
View File
@@ -8,48 +8,48 @@ pub use dyn_any_derive::DynAny;
use std::any::TypeId; use std::any::TypeId;
pub trait DynAny<'a> { pub trait DynAny<'a> {
fn type_id(&self) -> TypeId; fn type_id(&self) -> TypeId;
} }
impl<'a, T: StaticType> DynAny<'a> for T { impl<'a, T: StaticType> DynAny<'a> for T {
fn type_id(&self) -> std::any::TypeId { fn type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<T::Static>() std::any::TypeId::of::<T::Static>()
} }
} }
pub fn downcast_ref<'a, V: StaticType>(i: &'a dyn DynAny<'a>) -> Option<&'a V> { pub fn downcast_ref<'a, V: StaticType>(i: &'a dyn DynAny<'a>) -> Option<&'a V> {
if i.type_id() == std::any::TypeId::of::<<V as StaticType>::Static>() { if i.type_id() == std::any::TypeId::of::<<V as StaticType>::Static>() {
// SAFETY: caller guarantees that T is the correct type // SAFETY: caller guarantees that T is the correct type
let ptr = i as *const dyn DynAny<'a> as *const V; let ptr = i as *const dyn DynAny<'a> as *const V;
Some(unsafe { &*ptr }) Some(unsafe { &*ptr })
} else { } else {
None None
} }
} }
pub trait StaticType { pub trait StaticType {
type Static: 'static + ?Sized; type Static: 'static + ?Sized;
fn type_id(&self) -> std::any::TypeId { fn type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<Self::Static>() std::any::TypeId::of::<Self::Static>()
} }
} }
pub trait StaticTypeSized { pub trait StaticTypeSized {
type Static: 'static; type Static: 'static;
fn type_id(&self) -> std::any::TypeId { fn type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<Self::Static>() std::any::TypeId::of::<Self::Static>()
} }
} }
impl<'a, T: StaticTypeSized> StaticType for T { impl<'a, T: StaticTypeSized> StaticType for T {
type Static = <T as StaticTypeSized>::Static; type Static = <T as StaticTypeSized>::Static;
} }
pub trait StaticTypeClone { pub trait StaticTypeClone {
type Static: 'static + Clone; type Static: 'static + Clone;
fn type_id(&self) -> std::any::TypeId { fn type_id(&self) -> std::any::TypeId {
std::any::TypeId::of::<Self::Static>() std::any::TypeId::of::<Self::Static>()
} }
} }
impl<'a, T: StaticTypeClone> StaticTypeSized for T { impl<'a, T: StaticTypeClone> StaticTypeSized for T {
type Static = <T as StaticTypeClone>::Static; type Static = <T as StaticTypeClone>::Static;
} }
macro_rules! impl_type { macro_rules! impl_type {
@@ -61,54 +61,52 @@ macro_rules! impl_type {
)* )*
}; };
} }
impl<'a, T: Clone + StaticTypeClone> StaticTypeClone impl<'a, T: Clone + StaticTypeClone> StaticTypeClone for std::borrow::Cow<'a, T> {
for std::borrow::Cow<'a, T> type Static = std::borrow::Cow<'static, <T as StaticTypeSized>::Static>;
{
type Static = std::borrow::Cow<'static, <T as StaticTypeSized>::Static>;
} }
impl<'a, T: StaticTypeSized> StaticTypeSized for *const [T] { impl<'a, T: StaticTypeSized> StaticTypeSized for *const [T] {
type Static = *const [<T as StaticTypeSized>::Static]; type Static = *const [<T as StaticTypeSized>::Static];
} }
impl<'a, T: StaticTypeSized> StaticTypeSized for *mut [T] { impl<'a, T: StaticTypeSized> StaticTypeSized for *mut [T] {
type Static = *mut [<T as StaticTypeSized>::Static]; type Static = *mut [<T as StaticTypeSized>::Static];
} }
impl<'a, T: StaticTypeSized> StaticTypeSized for &'a [T] { impl<'a, T: StaticTypeSized> StaticTypeSized for &'a [T] {
type Static = &'static [<T as StaticTypeSized>::Static]; type Static = &'static [<T as StaticTypeSized>::Static];
} }
impl<'a> StaticTypeSized for &'a str { impl<'a> StaticTypeSized for &'a str {
type Static = &'static str; type Static = &'static str;
} }
impl<'a> StaticTypeSized for () { impl<'a> StaticTypeSized for () {
type Static = (); type Static = ();
} }
impl<'a, T: 'a + StaticTypeClone> StaticTypeClone for &'a T { impl<'a, T: 'a + StaticTypeClone> StaticTypeClone for &'a T {
type Static = &'static <T as StaticTypeClone>::Static; type Static = &'static <T as StaticTypeClone>::Static;
} }
impl<'a, T: StaticTypeSized, const N: usize> StaticTypeSized for [T; N] { impl<'a, T: StaticTypeSized, const N: usize> StaticTypeSized for [T; N] {
type Static = [<T as StaticTypeSized>::Static; N]; type Static = [<T as StaticTypeSized>::Static; N];
} }
use core::{ use core::{
cell::{Cell, RefCell, UnsafeCell}, cell::{Cell, RefCell, UnsafeCell},
iter::Empty, iter::Empty,
marker::{PhantomData, PhantomPinned}, marker::{PhantomData, PhantomPinned},
mem::{ManuallyDrop, MaybeUninit}, mem::{ManuallyDrop, MaybeUninit},
num::Wrapping, num::Wrapping,
time::Duration, time::Duration,
}; };
use std::{ use std::{
collections::*, collections::*,
sync::{atomic::*, *}, sync::{atomic::*, *},
vec::Vec, vec::Vec,
}; };
impl_type!(Option<T>,Result<T, E>,Cell<T>,UnsafeCell<T>,RefCell<T>,MaybeUninit<T>, impl_type!(Option<T>,Result<T, E>,Cell<T>,UnsafeCell<T>,RefCell<T>,MaybeUninit<T>,
Vec<T>, String, BTreeMap<K,V>,BTreeSet<V>, LinkedList<T>, VecDeque<T>, Vec<T>, String, BTreeMap<K,V>,BTreeSet<V>, LinkedList<T>, VecDeque<T>,
BinaryHeap<T>, ManuallyDrop<T>, PhantomData<T>, PhantomPinned,Empty<T>, BinaryHeap<T>, ManuallyDrop<T>, PhantomData<T>, PhantomPinned,Empty<T>,
Wrapping<T>, Duration, Once, Mutex<T>, RwLock<T>, bool, f32, f64, char, Wrapping<T>, Duration, Once, Mutex<T>, RwLock<T>, bool, f32, f64, char,
u8, AtomicU8, u16,AtomicU16, u32,AtomicU32, u64,AtomicU64, usize,AtomicUsize, u8, AtomicU8, u16,AtomicU16, u32,AtomicU32, u64,AtomicU64, usize,AtomicUsize,
i8,AtomicI8, i16,AtomicI16, i32,AtomicI32, i64,AtomicI64, isize,AtomicIsize, i8,AtomicI8, i16,AtomicI16, i32,AtomicI32, i64,AtomicI64, isize,AtomicIsize,
i128, u128, AtomicBool, AtomicPtr<T> i128, u128, AtomicBool, AtomicPtr<T>
); );
macro_rules! impl_tuple { macro_rules! impl_tuple {
(@rec $t:ident) => { }; (@rec $t:ident) => { };
@@ -127,5 +125,5 @@ macro_rules! impl_tuple {
} }
impl_tuple! { impl_tuple! {
A B C D E F G H I J K L A B C D E F G H I J K L
} }
+47 -55
View File
@@ -1,79 +1,71 @@
use std::{ use std::{
marker::PhantomData, marker::PhantomData,
mem::MaybeUninit, mem::MaybeUninit,
pin::Pin, pin::Pin,
sync::atomic::{AtomicUsize, Ordering}, sync::atomic::{AtomicUsize, Ordering},
}; };
pub trait BorrowStack<'n> { pub trait BorrowStack<'n> {
type Item; type Item;
unsafe fn push(&'n self, value: Self::Item); unsafe fn push(&'n self, value: Self::Item);
unsafe fn pop(&'n self); unsafe fn pop(&'n self);
unsafe fn get(&'n self) -> &'n [Self::Item]; unsafe fn get(&'n self) -> &'n [Self::Item];
} }
#[derive(Debug)] #[derive(Debug)]
pub struct FixedSizeStack<'n, T> { pub struct FixedSizeStack<'n, T> {
data: Pin<Box<[MaybeUninit<T>]>>, data: Pin<Box<[MaybeUninit<T>]>>,
capacity: usize, capacity: usize,
len: AtomicUsize, len: AtomicUsize,
_phantom: PhantomData<&'n ()>, _phantom: PhantomData<&'n ()>,
} }
impl<'n, T: Unpin> FixedSizeStack<'n, T> { impl<'n, T: Unpin> FixedSizeStack<'n, T> {
pub fn new(capacity: usize) -> Self { pub fn new(capacity: usize) -> Self {
let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap(); let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap();
let array = unsafe { std::alloc::alloc(layout) }; let array = unsafe { std::alloc::alloc(layout) };
let array = Pin::new(unsafe { let array = Pin::new(unsafe { Box::from_raw(std::slice::from_raw_parts_mut(array as *mut MaybeUninit<T>, capacity) as *mut [MaybeUninit<T>]) });
Box::from_raw(
std::slice::from_raw_parts_mut(array as *mut MaybeUninit<T>, capacity)
as *mut [MaybeUninit<T>],
)
});
Self { Self {
data: array, data: array,
capacity, capacity,
len: AtomicUsize::new(0), len: AtomicUsize::new(0),
_phantom: PhantomData, _phantom: PhantomData,
} }
} }
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.len.load(Ordering::SeqCst) self.len.load(Ordering::SeqCst)
} }
} }
impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> { impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> {
type Item = T; type Item = T;
unsafe fn push(&'n self, value: Self::Item) { unsafe fn push(&'n self, value: Self::Item) {
let len = self.len.load(Ordering::SeqCst); let len = self.len.load(Ordering::SeqCst);
assert!(len < self.capacity); assert!(len < self.capacity);
let ptr = self.data[len].as_ptr(); let ptr = self.data[len].as_ptr();
(ptr as *mut T).write(value); (ptr as *mut T).write(value);
self.len.fetch_add(1, Ordering::SeqCst); self.len.fetch_add(1, Ordering::SeqCst);
} }
unsafe fn pop(&'n self) { unsafe fn pop(&'n self) {
let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr(); let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr();
Box::from_raw(ptr as *mut T); Box::from_raw(ptr as *mut T);
self.len.fetch_sub(1, Ordering::SeqCst); self.len.fetch_sub(1, Ordering::SeqCst);
} }
unsafe fn get(&'n self) -> &'n [Self::Item] { unsafe fn get(&'n self) -> &'n [Self::Item] {
std::slice::from_raw_parts( std::slice::from_raw_parts(self.data.as_ptr() as *const T, self.len.load(Ordering::SeqCst))
self.data.as_ptr() as *const T, }
self.len.load(Ordering::SeqCst),
)
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
#[test] #[test]
fn it_works() { fn it_works() {
let result = 2 + 2; let result = 2 + 2;
assert_eq!(result, 4); assert_eq!(result, 4);
} }
} }
+18 -32
View File
@@ -1,46 +1,32 @@
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::Node; use crate::Node;
pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O>( pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O>(T, N, PhantomData<&'n O>);
T,
N,
PhantomData<&'n O>,
);
impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> Node<'n> for FnNode<'n, T, N, O> { impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> Node<'n> for FnNode<'n, T, N, O> {
type Output = O; type Output = O;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
self.0(self.1.eval()) self.0(self.1.eval())
} }
} }
impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> FnNode<'n, T, N, O> { impl<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O> FnNode<'n, T, N, O> {
pub fn new(f: T, input: N) -> Self { pub fn new(f: T, input: N) -> Self {
FnNode(f, input, PhantomData) FnNode(f, input, PhantomData)
} }
} }
pub struct FnNodeWithState< pub struct FnNodeWithState<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O, State: 'n>(T, N, State, PhantomData<&'n O>);
'n, impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> Node<'n> for FnNodeWithState<'n, T, N, O, State> {
T: Fn(<N as Node<'n>>::Output, &'n State) -> O, type Output = O;
N: Node<'n>,
O,
State: 'n,
>(T, N, State, PhantomData<&'n O>);
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> Node<'n>
for FnNodeWithState<'n, T, N, O, State>
{
type Output = O;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
self.0(self.1.eval(), &self.2) self.0(self.1.eval(), &self.2)
} }
} }
impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> impl<'n, T: Fn(<N as Node<'n>>::Output, &'n State) -> O, N: Node<'n>, O: 'n, State: 'n> FnNodeWithState<'n, T, N, O, State> {
FnNodeWithState<'n, T, N, O, State> pub fn new(f: T, input: N, state: State) -> Self {
{ FnNodeWithState(f, input, state, PhantomData)
pub fn new(f: T, input: N, state: State) -> Self { }
FnNodeWithState(f, input, state, PhantomData)
}
} }
+21 -21
View File
@@ -14,62 +14,62 @@ pub mod ops;
pub mod value; pub mod value;
pub trait Node<'n> { pub trait Node<'n> {
type Output; // TODO: replace with generic associated type type Output; // TODO: replace with generic associated type
fn eval(&'n self) -> Self::Output; fn eval(&'n self) -> Self::Output;
} }
impl<'n, N: Node<'n>> Node<'n> for &'n N { impl<'n, N: Node<'n>> Node<'n> for &'n N {
type Output = N::Output; type Output = N::Output;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
Node::eval(*self) Node::eval(*self)
} }
} }
pub trait NodeInput { pub trait NodeInput {
type Nodes; type Nodes;
fn new(input: Self::Nodes) -> Self; fn new(input: Self::Nodes) -> Self;
} }
trait FQN { trait FQN {
fn fqn(&self) -> &'static str; fn fqn(&self) -> &'static str;
} }
trait Input<I> { trait Input<I> {
unsafe fn input(&self, input: I); unsafe fn input(&self, input: I);
} }
#[cfg(feature = "async")] #[cfg(feature = "async")]
#[async_trait] #[async_trait]
pub trait AsyncNode<'n> { pub trait AsyncNode<'n> {
type Output; // TODO: replace with generic associated type type Output; // TODO: replace with generic associated type
async fn eval_async(&'n self) -> Self::Output; async fn eval_async(&'n self) -> Self::Output;
} }
#[cfg(feature = "async")] #[cfg(feature = "async")]
#[async_trait] #[async_trait]
impl<'n, N: Node<'n> + Sync> AsyncNode<'n> for N { impl<'n, N: Node<'n> + Sync> AsyncNode<'n> for N {
type Output = N::Output; type Output = N::Output;
async fn eval_async(&'n self) -> Self::Output { async fn eval_async(&'n self) -> Self::Output {
Node::eval(self) Node::eval(self)
} }
} }
pub trait Cache { pub trait Cache {
fn clear(&mut self); fn clear(&mut self);
} }
#[cfg(not(feature = "gpu"))] #[cfg(not(feature = "gpu"))]
extern crate alloc; extern crate alloc;
#[cfg(not(feature = "gpu"))] #[cfg(not(feature = "gpu"))]
impl<'n, I, O: 'n> Node<'n, I> for alloc::boxed::Box<dyn Node<'n, I, Output = O>> { impl<'n, I, O: 'n> Node<'n, I> for alloc::boxed::Box<dyn Node<'n, I, Output = O>> {
type Output = O; type Output = O;
fn eval(&'n self, input: &'n I) -> Self::Output { fn eval(&'n self, input: &'n I) -> Self::Output {
self.as_ref().eval(input) self.as_ref().eval(input)
} }
} }
+107 -116
View File
@@ -3,165 +3,156 @@ use core::{marker::PhantomData, ops::Add};
use crate::{Node, NodeInput}; use crate::{Node, NodeInput};
#[repr(C)] #[repr(C)]
pub struct AddNode<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>>( pub struct AddNode<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>>(pub I1, pub I2, PhantomData<&'n (L, R)>);
pub I1, impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> Node<'n> for AddNode<'n, L, R, I1, I2> {
pub I2, type Output = <L as Add<R>>::Output;
PhantomData<&'n (L, R)>, fn eval(&'n self) -> Self::Output {
); self.0.eval() + self.1.eval()
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> Node<'n> }
for AddNode<'n, L, R, I1, I2>
{
type Output = <L as Add<R>>::Output;
fn eval(&'n self) -> Self::Output {
self.0.eval() + self.1.eval()
}
} }
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> AddNode<'n, L, R, I1, I2> {
AddNode<'n, L, R, I1, I2> pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> {
{ AddNode(input.0, input.1, PhantomData)
pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> { }
AddNode(input.0, input.1, PhantomData)
}
} }
#[repr(C)] #[repr(C)]
pub struct CloneNode<'n, N: Node<'n, Output = &'n O>, O: Clone + 'n>(pub N, PhantomData<&'n ()>); pub struct CloneNode<'n, N: Node<'n, Output = &'n O>, O: Clone + 'n>(pub N, PhantomData<&'n ()>);
impl<'n, N: Node<'n, Output = &'n O>, O: Clone> Node<'n> for CloneNode<'n, N, O> { impl<'n, N: Node<'n, Output = &'n O>, O: Clone> Node<'n> for CloneNode<'n, N, O> {
type Output = O; type Output = O;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
self.0.eval().clone() self.0.eval().clone()
} }
} }
impl<'n, N: Node<'n, Output = &'n O>, O: Clone> CloneNode<'n, N, O> { impl<'n, N: Node<'n, Output = &'n O>, O: Clone> CloneNode<'n, N, O> {
pub const fn new(node: N) -> CloneNode<'n, N, O> { pub const fn new(node: N) -> CloneNode<'n, N, O> {
CloneNode(node, PhantomData) CloneNode(node, PhantomData)
} }
} }
#[repr(C)] #[repr(C)]
pub struct FstNode<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>); pub struct FstNode<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>);
impl<'n, T: 'n, U, N: Node<'n, Output = (T, U)>> Node<'n> for FstNode<'n, N> { impl<'n, T: 'n, U, N: Node<'n, Output = (T, U)>> Node<'n> for FstNode<'n, N> {
type Output = T; type Output = T;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
let (a, _) = self.0.eval(); let (a, _) = self.0.eval();
a a
} }
} }
#[repr(C)] #[repr(C)]
/// 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<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>); pub struct SndNode<'n, N: Node<'n>>(pub N, PhantomData<&'n ()>);
impl<'n, T, U: 'n, N: Node<'n, Output = (T, U)>> Node<'n> for SndNode<'n, N> { impl<'n, T, U: 'n, N: Node<'n, Output = (T, U)>> Node<'n> for SndNode<'n, N> {
type Output = U; type Output = U;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
let (_, b) = self.0.eval(); let (_, b) = self.0.eval();
b b
} }
} }
#[repr(C)] #[repr(C)]
/// Return a tuple with two instances of the input argument /// Return a tuple with two instances of the input argument
pub struct DupNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>); pub struct DupNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
impl<'n, N: Node<'n>> Node<'n> for DupNode<'n, N> { impl<'n, N: Node<'n>> Node<'n> for DupNode<'n, N> {
type Output = (N::Output, N::Output); type Output = (N::Output, N::Output);
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
(self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation (self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation
} }
} }
impl<'n, N: Node<'n>> NodeInput for DupNode<'n, N> { impl<'n, N: Node<'n>> NodeInput for DupNode<'n, N> {
type Nodes = N; type Nodes = N;
fn new(input: Self::Nodes) -> Self { fn new(input: Self::Nodes) -> Self {
Self(input, PhantomData) Self(input, PhantomData)
} }
} }
#[repr(C)] #[repr(C)]
/// Return the Input Argument /// Return the Input Argument
pub struct IdNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>); pub struct IdNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
impl<'n, N: Node<'n>> Node<'n> for IdNode<'n, N> { impl<'n, N: Node<'n>> Node<'n> for IdNode<'n, N> {
type Output = N::Output; type Output = N::Output;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
self.0.eval() self.0.eval()
} }
} }
impl<'n, N: Node<'n>> NodeInput for IdNode<'n, N> { impl<'n, N: Node<'n>> NodeInput for IdNode<'n, N> {
type Nodes = N; type Nodes = N;
fn new(input: Self::Nodes) -> Self { fn new(input: Self::Nodes) -> Self {
Self(input, PhantomData) Self(input, PhantomData)
} }
} }
pub fn foo() { pub fn foo() {
let unit = crate::value::UnitNode; let unit = crate::value::UnitNode;
let value = IdNode(crate::value::ValueNode(2u32), PhantomData); let value = IdNode(crate::value::ValueNode(2u32), PhantomData);
let value2 = crate::value::ValueNode(4u32); let value2 = crate::value::ValueNode(4u32);
let dup = DupNode(&value, PhantomData); let dup = DupNode(&value, PhantomData);
fn int(_: (), state: &u32) -> &u32 { fn int(_: (), state: &u32) -> &u32 {
state state
} }
fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) { fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) {
(input.1, input.0) (input.1, input.0)
} }
let fnn = crate::generic::FnNode::new(swap, &dup); let fnn = crate::generic::FnNode::new(swap, &dup);
let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32); let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32);
let _ = fnn.eval(); let _ = fnn.eval();
let _ = fns.eval(); let _ = fns.eval();
let snd = SndNode(&fnn, PhantomData); let snd = SndNode(&fnn, PhantomData);
let _ = snd.eval(); let _ = snd.eval();
let add = AddNode(&snd, value2, PhantomData); let add = AddNode(&snd, value2, PhantomData);
let _ = add.eval(); let _ = add.eval();
} }
#[cfg(target_arch = "spirv")] #[cfg(target_arch = "spirv")]
pub mod gpu { pub mod gpu {
//#![deny(warnings)] //#![deny(warnings)]
#[repr(C)] #[repr(C)]
pub struct PushConsts { pub struct PushConsts {
n: u32, n: u32,
node: u32, node: u32,
} }
use super::*; use super::*;
use crate::{structural::ComposeNodeOwned, Node}; use crate::{structural::ComposeNodeOwned, Node};
//use crate::Node; //use crate::Node;
use spirv_std::glam::UVec3; use spirv_std::glam::UVec3;
const ADD: AddNode<u32> = AddNode(PhantomData); const ADD: AddNode<u32> = AddNode(PhantomData);
const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> = const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> = ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
#[allow(unused)] #[allow(unused)]
#[spirv(compute(threads(64)))] #[spirv(compute(threads(64)))]
pub fn spread( pub fn spread(
#[spirv(global_invocation_id)] global_id: UVec3, #[spirv(global_invocation_id)] global_id: UVec3,
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)], #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [(u32, u32)], #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [(u32, u32)],
#[spirv(push_constant)] push_consts: &PushConsts, #[spirv(push_constant)] push_consts: &PushConsts,
) { ) {
fn node_graph(input: Input) -> Output { fn node_graph(input: Input) -> Output {
let n0 = ValueNode::new(input); let n0 = ValueNode::new(input);
let n1 = IdNode::new(n0); let n1 = IdNode::new(n0);
let n2 = IdNode::new(n1); let n2 = IdNode::new(n1);
return n2.eval(); return n2.eval();
} }
let gid = global_id.x as usize; let gid = global_id.x as usize;
// Only process up to n, which is the length of the buffers. // Only process up to n, which is the length of the buffers.
if global_id.x < push_consts.n { if global_id.x < push_consts.n {
y[gid] = node_graph(a[gid]); y[gid] = node_graph(a[gid]);
} }
} }
#[allow(unused)] #[allow(unused)]
#[spirv(compute(threads(64)))] #[spirv(compute(threads(64)))]
pub fn add( pub fn add(
#[spirv(global_invocation_id)] global_id: UVec3, #[spirv(global_invocation_id)] global_id: UVec3,
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)], #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[(u32, u32)],
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [u32], #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [u32],
#[spirv(push_constant)] push_consts: &PushConsts, #[spirv(push_constant)] push_consts: &PushConsts,
) { ) {
let gid = global_id.x as usize; let gid = global_id.x as usize;
// Only process up to n, which is the length of the buffers. // Only process up to n, which is the length of the buffers.
if global_id.x < push_consts.n { if global_id.x < push_consts.n {
y[gid] = ADD.eval(a[gid]); y[gid] = ADD.eval(a[gid]);
} }
} }
} }
+28 -28
View File
@@ -6,57 +6,57 @@ use crate::Node;
pub struct IntNode<const N: u32>; pub struct IntNode<const N: u32>;
impl<'n, const N: u32> Node<'n> for IntNode<N> { impl<'n, const N: u32> Node<'n> for IntNode<N> {
type Output = u32; type Output = u32;
fn eval(&self) -> u32 { fn eval(&self) -> u32 {
N N
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct ValueNode<T>(pub T); pub struct ValueNode<T>(pub T);
impl<'n, T: 'n> Node<'n> for ValueNode<T> { impl<'n, T: 'n> Node<'n> for ValueNode<T> {
type Output = &'n T; type Output = &'n T;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
&self.0 &self.0
} }
} }
impl<T> ValueNode<T> { impl<T> ValueNode<T> {
pub const fn new(value: T) -> ValueNode<T> { pub const fn new(value: T) -> ValueNode<T> {
ValueNode(value) ValueNode(value)
} }
} }
#[derive(Default)] #[derive(Default)]
pub struct DefaultNode<T>(PhantomData<T>); pub struct DefaultNode<T>(PhantomData<T>);
impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> { impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
type Output = T; type Output = T;
fn eval(&self) -> T { fn eval(&self) -> T {
T::default() T::default()
} }
} }
#[repr(C)] #[repr(C)]
/// Return the unit value /// Return the unit value
pub struct UnitNode; pub struct UnitNode;
impl<'n> Node<'n> for UnitNode { impl<'n> Node<'n> for UnitNode {
type Output = (); type Output = ();
fn eval(&'n self) -> Self::Output {} fn eval(&'n self) -> Self::Output {}
} }
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool); pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
impl<'n, T: 'n> Node<'n> for InputNode<T> { impl<'n, T: 'n> Node<'n> for InputNode<T> {
type Output = &'n T; type Output = &'n T;
fn eval(&'n self) -> Self::Output { fn eval(&'n self) -> Self::Output {
if self.1.load(core::sync::atomic::Ordering::SeqCst) { if self.1.load(core::sync::atomic::Ordering::SeqCst) {
unsafe { self.0.assume_init_ref() } unsafe { self.0.assume_init_ref() }
} else { } else {
panic!("tried to access an input before setting it") panic!("tried to access an input before setting it")
} }
} }
} }
impl<T> InputNode<T> { impl<T> InputNode<T> {
pub const fn new() -> InputNode<T> { pub const fn new() -> InputNode<T> {
InputNode(MaybeUninit::uninit(), AtomicBool::new(false)) InputNode(MaybeUninit::uninit(), AtomicBool::new(false))
} }
} }
+1 -1
View File
@@ -2,7 +2,7 @@ pub mod value;
pub use graphene_core::{generic, ops /*, structural*/}; pub use graphene_core::{generic, ops /*, structural*/};
#[cfg(feature = "caching")] #[cfg(feature = "caching")]
pub mod caching; pub mod cache;
#[cfg(feature = "memoization")] #[cfg(feature = "memoization")]
pub mod memo; pub mod memo;
+121 -124
View File
@@ -5,147 +5,144 @@ use graphene_std::value::{AnyRefNode, AnyValueNode, StorageNode, ValueNode};
use graphene_std::*; use graphene_std::*;
/*fn mul(#[dyn_any(default)] a: f32, b: f32) -> f32 { /*fn mul(#[dyn_any(default)] a: f32, b: f32) -> f32 {
a * b a * b
}*/ }*/
mod mul { mod mul {
use dyn_any::{downcast_ref, DynAny, StaticType}; use dyn_any::{downcast_ref, DynAny, StaticType};
use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node}; use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node};
pub struct MulNodeInput<'n> { pub struct MulNodeInput<'n> {
pub a: &'n f32, pub a: &'n f32,
pub b: &'n f32, pub b: &'n f32,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct MulNodeAnyProxy<'n> { pub struct MulNodeAnyProxy<'n> {
pub a: Option<DynAnyNode<'n>>, pub a: Option<DynAnyNode<'n>>,
pub b: Option<DynAnyNode<'n>>, pub b: Option<DynAnyNode<'n>>,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct MulNodeTypedProxy<'n> { pub struct MulNodeTypedProxy<'n> {
pub a: Option<DynNode<'n, &'n f32>>, pub a: Option<DynNode<'n, &'n f32>>,
pub b: Option<DynNode<'n, &'n f32>>, pub b: Option<DynNode<'n, &'n f32>>,
} }
impl<'n> Node<'n> for MulNodeAnyProxy<'n> { impl<'n> Node<'n> for MulNodeAnyProxy<'n> {
type Output = MulNodeInput<'n>; type Output = MulNodeInput<'n>;
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output { fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
let a = self.a.unwrap().eval(); let a = self.a.unwrap().eval();
let a: &f32 = self let a: &f32 = self.a.map(|v| downcast_ref(v.eval()).unwrap()).unwrap_or(&1.);
.a /*let b: &f32 = self
.map(|v| downcast_ref(v.eval()).unwrap()) .b
.unwrap_or(&1.); .map(|v| v.eval(&()).downcast_ref::<&'n f32, &'n f32>().unwrap())
/*let b: &f32 = self .unwrap_or(&&2.);
.b a * b*/
.map(|v| v.eval(&()).downcast_ref::<&'n f32, &'n f32>().unwrap()) MulNodeInput { a, b: a }
.unwrap_or(&&2.); }
a * b*/ }
MulNodeInput { a, b: a } impl<'n> Node<'n> for MulNodeTypedProxy<'n> {
} type Output = MulNodeInput<'n>;
} fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
impl<'n> Node<'n> for MulNodeTypedProxy<'n> { let a = self.a.unwrap().eval();
type Output = MulNodeInput<'n>; let b = self.b.unwrap().eval();
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output { MulNodeInput { a, b }
let a = self.a.unwrap().eval(); }
let b = self.b.unwrap().eval(); }
MulNodeInput { a, b }
}
}
/*macro_rules! new { /*macro_rules! new {
() => { () => {
mul::MulNode { a: None, b: None } mul::MulNode { a: None, b: None }
}; };
}*/ }*/
//pub(crate) use new; //pub(crate) use new;
impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> { impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> {
fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>) { fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>) {
todo!() todo!()
} }
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) { fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) {
match index { match index {
0 => { 0 => {
self.a = Some(value); self.a = Some(value);
} }
_ => todo!(), _ => todo!(),
} }
} }
} }
} }
type SNode<'n> = dyn Node<'n, Output = &'n dyn DynAny<'n>>; type SNode<'n> = dyn Node<'n, Output = &'n dyn DynAny<'n>>;
struct NodeStore<'n>(borrow_stack::FixedSizeStack<'n, Box<SNode<'n>>>); struct NodeStore<'n>(borrow_stack::FixedSizeStack<'n, Box<SNode<'n>>>);
impl<'n> NodeStore<'n> { impl<'n> NodeStore<'n> {
fn len(&self) -> usize { fn len(&self) -> usize {
self.0.len() self.0.len()
} }
fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) { fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) {
unsafe { self.0.push(f(self.0.get())) }; unsafe { self.0.push(f(self.0.get())) };
} }
/*fn get_index(&'n self, index: usize) -> &'n SNode<'n> { /*fn get_index(&'n self, index: usize) -> &'n SNode<'n> {
assert!(index < self.0.len()); assert!(index < self.0.len());
&unsafe { self.0.get()[index] } &unsafe { self.0.get()[index] }
}*/ }*/
} }
fn main() { fn main() {
use graphene_std::*; use graphene_std::*;
use quote::quote; use quote::quote;
use syn::parse::Parse; use syn::parse::Parse;
let nodes = vec![ let nodes = vec![
NodeKind::Input, NodeKind::Input,
NodeKind::Value(syn::parse_quote!(1u32)), NodeKind::Value(syn::parse_quote!(1u32)),
NodeKind::Node(syn::parse_quote!(graphene_core::ops::AddNode), vec![0, 0]), NodeKind::Node(syn::parse_quote!(graphene_core::ops::AddNode), vec![0, 0]),
]; ];
//println!("{}", node_graph(1)); //println!("{}", node_graph(1));
let nodegraph = NodeGraph { let nodegraph = NodeGraph {
nodes, nodes,
input: syn::Type::Verbatim(quote! {u32}), input: syn::Type::Verbatim(quote! {u32}),
output: syn::Type::Verbatim(quote! {u32}), output: syn::Type::Verbatim(quote! {u32}),
}; };
//let pretty = pretty_token_stream::Pretty::new(nodegraph.serialize_gpu("add")); //let pretty = pretty_token_stream::Pretty::new(nodegraph.serialize_gpu("add"));
//pretty.print(); //pretty.print();
/* /*
use dyn_any::{downcast_ref, DynAny, StaticType}; use dyn_any::{downcast_ref, DynAny, StaticType};
//let mut mul = mul::MulNode::new(); //let mut mul = mul::MulNode::new();
let mut stack: borrow_stack::FixedSizeStack<Box<dyn Node<'_, Output = &dyn DynAny>>> = let mut stack: borrow_stack::FixedSizeStack<Box<dyn Node<'_, Output = &dyn DynAny>>> =
borrow_stack::FixedSizeStack::new(42); borrow_stack::FixedSizeStack::new(42);
unsafe { stack.push(Box::new(AnyValueNode::new(1f32))) }; unsafe { stack.push(Box::new(AnyValueNode::new(1f32))) };
//let node = unsafe { stack.get(0) }; //let node = unsafe { stack.get(0) };
//let boxed = Box::new(StorageNode::new(node)); //let boxed = Box::new(StorageNode::new(node));
//unsafe { stack.push(boxed) }; //unsafe { stack.push(boxed) };
let result = unsafe { &stack.get()[0] }.eval(); let result = unsafe { &stack.get()[0] }.eval();
dbg!(downcast_ref::<f32>(result)); dbg!(downcast_ref::<f32>(result));
/*unsafe { /*unsafe {
stack stack
.push(Box::new(AnyRefNode::new(stack.get(0).as_ref())) .push(Box::new(AnyRefNode::new(stack.get(0).as_ref()))
as Box<dyn Node<(), Output = &dyn DynAny>>) as Box<dyn Node<(), Output = &dyn DynAny>>)
};*/ };*/
let f = (3.2f32, 3.1f32); let f = (3.2f32, 3.1f32);
let a = ValueNode::new(1.); let a = ValueNode::new(1.);
let id = std::any::TypeId::of::<&f32>(); let id = std::any::TypeId::of::<&f32>();
let any_a = AnyRefNode::new(&a); let any_a = AnyRefNode::new(&a);
/*let _mul2 = mul::MulNodeInput { /*let _mul2 = mul::MulNodeInput {
a: None, a: None,
b: Some(&any_a), b: Some(&any_a),
}; };
let mut mul2 = mul::new!(); let mut mul2 = mul::new!();
//let cached = memo::CacheNode::new(&mul1); //let cached = memo::CacheNode::new(&mul1);
//let foo = value::AnyRefNode::new(&cached); //let foo = value::AnyRefNode::new(&cached);
mul2.set_arg_by_index(0, &any_a);*/ mul2.set_arg_by_index(0, &any_a);*/
let int = value::IntNode::<32>; let int = value::IntNode::<32>;
Node::eval(&int); Node::eval(&int);
println!("{}", Node::eval(&int)); println!("{}", Node::eval(&int));
//let _add: u32 = ops::AddNode::<u32>::default().eval((int.exec(), int.exec())); //let _add: u32 = ops::AddNode::<u32>::default().eval((int.exec(), int.exec()));
//let fnode = generic::FnNode::new(|(a, b): &(i32, i32)| a - b); //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)
} }
+67 -80
View File
@@ -5,106 +5,93 @@ use syn::punctuated::Punctuated;
use syn::{parse_macro_input, FnArg, ItemFn, Pat, Type}; use syn::{parse_macro_input, FnArg, ItemFn, Pat, Type};
fn extract_type(a: FnArg) -> Type { fn extract_type(a: FnArg) -> Type {
match a { match a {
FnArg::Typed(p) => *p.ty, // notice `ty` instead of `pat` FnArg::Typed(p) => *p.ty, // notice `ty` instead of `pat`
_ => panic!("Not supported on types with `self`!"), _ => panic!("Not supported on types with `self`!"),
} }
} }
fn extract_arg_types(fn_args: Punctuated<FnArg, syn::token::Comma>) -> Vec<Type> { fn extract_arg_types(fn_args: Punctuated<FnArg, syn::token::Comma>) -> Vec<Type> {
fn_args.into_iter().map(extract_type).collect::<Vec<_>>() fn_args.into_iter().map(extract_type).collect::<Vec<_>>()
} }
fn extract_arg_idents(fn_args: Punctuated<FnArg, syn::token::Comma>) -> Vec<Pat> { fn extract_arg_idents(fn_args: Punctuated<FnArg, syn::token::Comma>) -> Vec<Pat> {
fn_args.into_iter().map(extract_arg_pat).collect::<Vec<_>>() fn_args.into_iter().map(extract_arg_pat).collect::<Vec<_>>()
} }
fn extract_arg_pat(a: FnArg) -> Pat { fn extract_arg_pat(a: FnArg) -> Pat {
match a { match a {
FnArg::Typed(p) => *p.pat, FnArg::Typed(p) => *p.pat,
_ => panic!("Not supported on types with `self`!"), _ => panic!("Not supported on types with `self`!"),
} }
} }
#[proc_macro_attribute] // 2 #[proc_macro_attribute] // 2
pub fn to_node(_attr: TokenStream, item: TokenStream) -> TokenStream { pub fn to_node(_attr: TokenStream, item: TokenStream) -> TokenStream {
let string = item.to_string(); let string = item.to_string();
let item2 = item; let item2 = item;
let parsed = parse_macro_input!(item2 as ItemFn); // 3 let parsed = parse_macro_input!(item2 as ItemFn); // 3
//item.extend(generate_to_string(parsed, string)); // 4 //item.extend(generate_to_string(parsed, string)); // 4
//item //item
generate_to_string(parsed, string) generate_to_string(parsed, string)
} }
fn generate_to_string(parsed: ItemFn, string: String) -> TokenStream { fn generate_to_string(parsed: ItemFn, string: String) -> TokenStream {
let whole_function = parsed.clone(); let whole_function = parsed.clone();
//let fn_body = parsed.block; // function body //let fn_body = parsed.block; // function body
let sig = parsed.sig; // function signature let sig = parsed.sig; // function signature
//let vis = parsed.vis; // visibility, pub or not //let vis = parsed.vis; // visibility, pub or not
let generics = sig.generics; let generics = sig.generics;
let fn_args = sig.inputs; // comma separated args let fn_args = sig.inputs; // comma separated args
let fn_return_type = sig.output; // return type let fn_return_type = sig.output; // return type
let fn_name = sig.ident; // function name/identifier let fn_name = sig.ident; // function name/identifier
let idents = extract_arg_idents(fn_args.clone()); let idents = extract_arg_idents(fn_args.clone());
let types = extract_arg_types(fn_args); let types = extract_arg_types(fn_args);
let types = types let types = types.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
.iter() let idents = idents.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
.map(|t| t.to_token_stream()) let const_idents = idents
.collect::<Vec<_>>(); .iter()
let idents = idents .map(|t| {
.iter() let name = t.to_string().to_uppercase();
.map(|t| t.to_token_stream()) quote! {#name}
.collect::<Vec<_>>(); })
let const_idents = idents .collect::<Vec<_>>();
.iter()
.map(|t| {
let name = t.to_string().to_uppercase();
quote! {#name}
})
.collect::<Vec<_>>();
let node_fn_name = fn_name.append("_node"); let node_fn_name = fn_name.append("_node");
let struct_name = fn_name.append("_input"); let struct_name = fn_name.append("_input");
let return_type_string = fn_return_type let return_type_string = fn_return_type.to_token_stream().to_string().replace("->", "");
.to_token_stream() let arg_type_string = types.iter().map(|t| t.to_string()).collect::<Vec<_>>().join(", ");
.to_string() let error = format!("called {} with the wrong type", fn_name);
.replace("->", "");
let arg_type_string = types
.iter()
.map(|t| t.to_string())
.collect::<Vec<_>>()
.join(", ");
let error = format!("called {} with the wrong type", fn_name);
let x = quote! { let x = quote! {
//#whole_function //#whole_function
mod #fn_name { mod #fn_name {
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
type F32Node<'n> = &'n (dyn Node<'n, (), Output = &'n (dyn Any + 'static)> + 'n); type F32Node<'n> = &'n (dyn Node<'n, (), Output = &'n (dyn Any + 'static)> + 'n);
struct #struct_name { struct #struct_name {
#(#idents: #types,)* #(#idents: #types,)*
} }
impl Node for #struct_name { impl Node for #struct_name {
} }
} }
fn #node_fn_name #generics() -> Node<'static> { fn #node_fn_name #generics() -> Node<'static> {
Node { func: Box::new(move |x| { Node { func: Box::new(move |x| {
let args = x.downcast::<(#(#types,)*)>().expect(#error); let args = x.downcast::<(#(#types,)*)>().expect(#error);
let (#(#idents,)*) = *args; let (#(#idents,)*) = *args;
#whole_function #whole_function
Box::new(#fn_name(#(#idents,)*)) Box::new(#fn_name(#(#idents,)*))
}), }),
code: #string.to_string(), code: #string.to_string(),
return_type: #return_type_string.trim().to_string(), return_type: #return_type_string.trim().to_string(),
args: format!("({})",#arg_type_string.trim()), args: format!("({})",#arg_type_string.trim()),
position: (0., 0.), position: (0., 0.),
} }
} }
}; };
//panic!("{}\n{:?}", x.to_string(), x); //panic!("{}\n{:?}", x.to_string(), x);
x.into() x.into()
} }