From 0c2dbd411ba48481fe58e8a16b1445f118ca81dc Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Thu, 4 Aug 2022 00:18:42 -0700 Subject: [PATCH] Fix formatting of previous commit --- libraries/dyn-any/Cargo.toml | 2 +- libraries/dyn-any/derive/Cargo.toml | 2 +- node-graph/gcore/Cargo.toml | 4 +- node-graph/gcore/src/structural.rs | 127 +++++++++++----------- node-graph/gstd/Cargo.toml | 8 +- node-graph/gstd/src/cache.rs | 54 +++++----- node-graph/gstd/src/lib.rs | 156 ++++++++++++++-------------- node-graph/gstd/src/memo.rs | 42 ++++---- node-graph/gstd/src/value.rs | 44 ++++---- node-graph/proc-macro/Cargo.toml | 2 +- node-graph/proc-macro/src/lib.rs | 19 ++-- 11 files changed, 226 insertions(+), 234 deletions(-) diff --git a/libraries/dyn-any/Cargo.toml b/libraries/dyn-any/Cargo.toml index 3f52ecc7..6ca98dfa 100644 --- a/libraries/dyn-any/Cargo.toml +++ b/libraries/dyn-any/Cargo.toml @@ -2,7 +2,7 @@ name = "dyn-any" version = "0.2.1" edition = "2021" -authors = ["Dennis Kobert "] +authors = ["Graphite Authors "] description = "An Any trait that works for arbitrary lifetimes" diff --git a/libraries/dyn-any/derive/Cargo.toml b/libraries/dyn-any/derive/Cargo.toml index d498d27c..59104f4e 100644 --- a/libraries/dyn-any/derive/Cargo.toml +++ b/libraries/dyn-any/derive/Cargo.toml @@ -2,7 +2,7 @@ name = "dyn-any-derive" version = "0.2.1" edition = "2021" -authors = ["Dennis Kobert"] +authors = ["Graphite Authors "] description = "#[derive(DynAny<'a>)]" documentation = "https://docs.rs/dyn-any-derive" diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index 56a539db..7b173727 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -3,7 +3,7 @@ name = "graphene-core" version = "0.1.0" edition = "2021" description = "API definitions for Graphene" -authors = ["Dennis Kobert "] +authors = ["Graphite Authors "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,5 +17,5 @@ nightly = [] [dependencies] dyn-any = {path = "../../libraries/dyn-any", features = ["derive"], optional = true} -spirv-std = { git = "https://github.com/EmbarkStudios/rust-gpu", features = ["glam"] , optional = true} +spirv-std = { git = "https://github.com/EmbarkStudios/rust-gpu", features = ["glam"] , optional = true} async-trait = {version = "0.1", optional = true} diff --git a/node-graph/gcore/src/structural.rs b/node-graph/gcore/src/structural.rs index 67f74dae..7fe6fdfe 100644 --- a/node-graph/gcore/src/structural.rs +++ b/node-graph/gcore/src/structural.rs @@ -3,98 +3,93 @@ use core::marker::PhantomData; use crate::Node; pub struct ComposeNode<'n, Inter, First, Second> { - first: &'n First, - second: &'n Second, - _phantom: PhantomData<&'n Input>, - _phantom2: PhantomData, + first: &'n First, + second: &'n Second, + _phantom: PhantomData<&'n Input>, + _phantom2: PhantomData, } -impl<'n, Input: 'n, Inter: 'n, First, Second> Node<'n, Input> - for ComposeNode<'n, Input, Inter, First, Second> +impl<'n, Input: 'n, Inter: 'n, First, Second> Node<'n, Input> for ComposeNode<'n, Input, Inter, First, Second> where - First: Node<'n, Input, Output = Inter>, - Second: Node<'n, Inter>, /*+ Node<>::Output<'n>>*/ + First: Node<'n, Input, Output = Inter>, + Second: Node<'n, Inter>, /*+ Node<>::Output<'n>>*/ { - type Output = >::Output; + type Output = >::Output; - fn eval(&'n self, input: 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: Inter = self.first.eval(input); - self.second.eval(arg) - } + fn eval(&'n self, input: 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: Inter = self.first.eval(input); + self.second.eval(arg) + } } impl<'n, Input, Inter, FIRST, SECOND> ComposeNode<'n, Input, Inter, FIRST, SECOND> where - FIRST: Node<'n, Input>, + FIRST: Node<'n, Input>, { - pub const fn new(first: &'n FIRST, second: &'n SECOND) -> Self { - ComposeNode::<'n, Input, Inter, FIRST, SECOND> { - first, - second, - _phantom: PhantomData, - _phantom2: PhantomData, - } - } + pub const fn new(first: &'n FIRST, second: &'n SECOND) -> Self { + ComposeNode::<'n, Input, Inter, FIRST, SECOND> { + first, + second, + _phantom: PhantomData, + _phantom2: PhantomData, + } + } } #[repr(C)] pub struct ComposeNodeOwned<'n, Input, Inter, FIRST, SECOND> { - first: FIRST, - second: SECOND, - _phantom: PhantomData<&'n Input>, - _phantom2: PhantomData, + first: FIRST, + second: SECOND, + _phantom: PhantomData<&'n Input>, + _phantom2: PhantomData, } -impl<'n, Input: 'n, Inter: 'n, First, Second> Node<'n, Input> - for ComposeNodeOwned<'n, Input, Inter, First, Second> +impl<'n, Input: 'n, Inter: 'n, First, Second> Node<'n, Input> for ComposeNodeOwned<'n, Input, Inter, First, Second> where - First: Node<'n, Input, Output = Inter>, - Second: Node<'n, Inter>, + First: Node<'n, Input, Output = Inter>, + Second: Node<'n, Inter>, { - type Output = >::Output; + type Output = >::Output; - fn eval(&'n self, input: 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: Inter = self.first.eval(input); - self.second.eval(arg) - } + fn eval(&'n self, input: 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: Inter = self.first.eval(input); + self.second.eval(arg) + } } impl<'n, Input, Inter, First: 'n, Second> ComposeNodeOwned<'n, Input, Inter, First, Second> where - First: Node<'n, Input, Output = Inter>, + First: Node<'n, Input, Output = Inter>, { - #[cfg(feature = "nightly")] - pub const fn new(first: First, second: Second) -> Self { - ComposeNodeOwned::<'n, Input, Inter, First, Second> { - first, - second, - _phantom: PhantomData, - _phantom2: PhantomData, - } - } - #[cfg(not(feature = "nightly"))] - pub fn new(first: First, second: Second) -> Self { - ComposeNodeOwned::<'n, Input, Inter, First, Second> { - first, - second, - _phantom: PhantomData, - _phantom2: PhantomData, - } - } + #[cfg(feature = "nightly")] + pub const fn new(first: First, second: Second) -> Self { + ComposeNodeOwned::<'n, Input, Inter, First, Second> { + first, + second, + _phantom: PhantomData, + _phantom2: PhantomData, + } + } + #[cfg(not(feature = "nightly"))] + pub fn new(first: First, second: Second) -> Self { + ComposeNodeOwned::<'n, Input, Inter, First, Second> { + first, + second, + _phantom: PhantomData, + _phantom2: PhantomData, + } + } } pub trait After: Sized { - fn after<'n, First: Node<'n, I>>( - &'n self, - first: &'n First, - ) -> ComposeNode<'n, I, >::Output, First, Self> { - ComposeNode::new(first, self) - } + fn after<'n, First: Node<'n, I>>(&'n self, first: &'n First) -> ComposeNode<'n, I, >::Output, First, Self> { + ComposeNode::new(first, self) + } } impl Node<'n, I>, I> After for Second {} diff --git a/node-graph/gstd/Cargo.toml b/node-graph/gstd/Cargo.toml index f1d44008..340f4ba3 100644 --- a/node-graph/gstd/Cargo.toml +++ b/node-graph/gstd/Cargo.toml @@ -3,7 +3,7 @@ name = "graphene-std" version = "0.1.0" edition = "2021" description = "Graphene standard library" -authors = ["Dennis Kobert "] +authors = ["Graphite Authors "] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -22,11 +22,11 @@ dyn-any = {path = "../../libraries/dyn-any", features = ["derive"]} graph-proc-macros = {path = "../proc-macro", optional = true} once_cell = {version= "1.10", optional = true} ide = { version = "*", package = "ra_ap_ide", optional = true } -ide_db = { version = "*", package = "ra_ap_ide_db" , optional = true } +ide_db = { version = "*", package = "ra_ap_ide_db", optional = true } storage-map = { version = "*", optional = true } lock_api = { version= "*", optional = true } parking_lot = { version = "*", optional = true } #pretty-token-stream = {path = "../../pretty-token-stream"} -syn = {version = "1.0", default-features = false, features = ["parsing", "printing"]} -proc-macro2 = {version = "1.0", default-features = false, features = ["proc-macro"]} +syn = {version = "1.0", default-features = false, features = ["parsing", "printing"]} +proc-macro2 = {version = "1.0", default-features = false, features = ["proc-macro"]} quote = {version = "1.0", default-features = false } diff --git a/node-graph/gstd/src/cache.rs b/node-graph/gstd/src/cache.rs index 680b6573..ee917444 100644 --- a/node-graph/gstd/src/cache.rs +++ b/node-graph/gstd/src/cache.rs @@ -1,13 +1,13 @@ use parking_lot::RawRwLock; use std::{ - any::Any, - borrow::Borrow, - cell::RefCell, - collections::{hash_map::DefaultHasher, HashMap}, - hash::{Hash, Hasher}, - iter, - iter::Sum, - marker::PhantomData, + any::Any, + borrow::Borrow, + cell::RefCell, + collections::{hash_map::DefaultHasher, HashMap}, + hash::{Hash, Hasher}, + iter, + iter::Sum, + marker::PhantomData, }; use storage_map::{StorageMap, StorageMapGuard}; @@ -16,33 +16,29 @@ use graphene_api::{DynamicInput, Node}; /// Caches the output of a given Node and acts as a proxy /// Automatically resets if it receives different input pub struct SmartCacheNode<'n, 'c, NODE: Node + 'c> { - node: &'n NODE, - map: StorageMap>>, + node: &'n NODE, + map: StorageMap>>, } impl<'n: 'c, 'c, NODE: Node + 'c> Node for SmartCacheNode<'n, 'c, NODE> where - for<'a> NODE::Input<'a>: Hash, + for<'a> NODE::Input<'a>: Hash, { - type Input<'a> = NODE::Input<'a> where Self: 'a, 'c : 'a; - type Output<'a> = StorageMapGuard<'a, RawRwLock, CacheNode<'n, 'c, NODE>> where Self: 'a, 'c: 'a; - fn eval<'a, I: Borrow>>(&'a self, input: I) -> Self::Output<'a> { - let mut hasher = DefaultHasher::new(); - input.borrow().hash(&mut hasher); - let hash = hasher.finish(); + type Input<'a> = NODE::Input<'a> where Self: 'a, 'c : 'a; + type Output<'a> = StorageMapGuard<'a, RawRwLock, CacheNode<'n, 'c, NODE>> where Self: 'a, 'c: 'a; + fn eval<'a, I: Borrow>>(&'a self, input: I) -> Self::Output<'a> { + let mut hasher = DefaultHasher::new(); + input.borrow().hash(&mut hasher); + let hash = hasher.finish(); - self.map - .get_or_create_with(&hash, || CacheNode::new(self.node)) - } + self.map.get_or_create_with(&hash, || CacheNode::new(self.node)) + } } impl<'n, 'c, NODE: Node> SmartCacheNode<'n, 'c, NODE> { - pub fn clear(&'n mut self) { - self.map = StorageMap::default(); - } - pub fn new(node: &'n NODE) -> SmartCacheNode<'n, 'c, NODE> { - SmartCacheNode { - node, - map: StorageMap::default(), - } - } + pub fn clear(&'n mut self) { + self.map = StorageMap::default(); + } + pub fn new(node: &'n NODE) -> SmartCacheNode<'n, 'c, NODE> { + SmartCacheNode { node, map: StorageMap::default() } + } } diff --git a/node-graph/gstd/src/lib.rs b/node-graph/gstd/src/lib.rs index b909e18b..f06cba56 100644 --- a/node-graph/gstd/src/lib.rs +++ b/node-graph/gstd/src/lib.rs @@ -13,8 +13,8 @@ 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>); + 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; @@ -25,89 +25,89 @@ use syn::{Expr, ExprPath, Type}; /// on the gpu an fn node is constructed that takes a value /// node as input pub struct NodeGraph { - /// Collection of nodes with their corresponding inputs. - /// The first node always always has to be an Input Node. - pub nodes: Vec, - pub output: Type, - pub input: Type, + /// Collection of nodes with their corresponding inputs. + /// The first node always always has to be an Input Node. + pub nodes: Vec, + pub output: Type, + pub input: Type, } pub enum NodeKind { - Value(Expr), - Input, - Node(ExprPath, Vec), + Value(Expr), + Input, + Node(ExprPath, Vec), } impl NodeGraph { - pub fn serialize_function(&self) -> proc_macro2::TokenStream { - let output_type = &self.output; - let input_type = &self.input; + pub fn serialize_function(&self) -> proc_macro2::TokenStream { + let output_type = &self.output; + let input_type = &self.input; - fn nid(id: &usize) -> syn::Ident { - let str = format!("n{id}"); - syn::Ident::new(str.as_str(), proc_macro2::Span::call_site()) - } - let mut nodes = Vec::new(); - for (ref id, node) in self.nodes.iter().enumerate() { - let id = nid(id).clone(); - let line = match node { - NodeKind::Value(val) => { - quote! {let #id = graphene_core::value::ValueNode::new(#val);} - } - NodeKind::Node(node, ids) => { - let ids = ids.iter().map(nid).collect::>(); - quote! {let #id = #node::new((#(&#ids),*));} - } - NodeKind::Input => { - quote! { let n0 = graphene_core::value::ValueNode::new(input);} - } - }; - nodes.push(line) - } - let last_id = self.nodes.len() - 1; - let last_id = nid(&last_id); - let ret = quote! { #last_id.eval() }; - let function = quote! { - fn node_graph(input: #input_type) -> #output_type { - #(#nodes)* - #ret - } - }; - function - } - pub fn serialize_gpu(&self, name: &str) -> proc_macro2::TokenStream { - let function = self.serialize_function(); - let output_type = &self.output; - let input_type = &self.input; + fn nid(id: &usize) -> syn::Ident { + let str = format!("n{id}"); + syn::Ident::new(str.as_str(), proc_macro2::Span::call_site()) + } + let mut nodes = Vec::new(); + for (ref id, node) in self.nodes.iter().enumerate() { + let id = nid(id).clone(); + let line = match node { + NodeKind::Value(val) => { + quote! {let #id = graphene_core::value::ValueNode::new(#val);} + } + NodeKind::Node(node, ids) => { + let ids = ids.iter().map(nid).collect::>(); + quote! {let #id = #node::new((#(&#ids),*));} + } + NodeKind::Input => { + quote! { let n0 = graphene_core::value::ValueNode::new(input);} + } + }; + nodes.push(line) + } + let last_id = self.nodes.len() - 1; + let last_id = nid(&last_id); + let ret = quote! { #last_id.eval() }; + let function = quote! { + fn node_graph(input: #input_type) -> #output_type { + #(#nodes)* + #ret + } + }; + function + } + pub fn serialize_gpu(&self, name: &str) -> proc_macro2::TokenStream { + let function = self.serialize_function(); + let output_type = &self.output; + let input_type = &self.input; - quote! { - #[cfg(target_arch = "spirv")] - pub mod gpu { - //#![deny(warnings)] - #[repr(C)] - pub struct PushConsts { - n: u32, - node: u32, - } - use super::*; + quote! { + #[cfg(target_arch = "spirv")] + pub mod gpu { + //#![deny(warnings)] + #[repr(C)] + pub struct PushConsts { + n: u32, + node: u32, + } + use super::*; - use spirv_std::glam::UVec3; + use spirv_std::glam::UVec3; - #[allow(unused)] - #[spirv(compute(threads(64)))] - pub fn #name( - #[spirv(global_invocation_id)] global_id: UVec3, - #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[#input_type], - #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [#output_type], - #[spirv(push_constant)] push_consts: &PushConsts, - ) { - #function - let gid = global_id.x as usize; - // Only process up to n, which is the length of the buffers. - if global_id.x < push_consts.n { - y[gid] = node_graph(a[gid]); - } - } - } - } - } + #[allow(unused)] + #[spirv(compute(threads(64)))] + pub fn #name( + #[spirv(global_invocation_id)] global_id: UVec3, + #[spirv(storage_buffer, descriptor_set = 0, binding = 0)] a: &[#input_type], + #[spirv(storage_buffer, descriptor_set = 0, binding = 1)] y: &mut [#output_type], + #[spirv(push_constant)] push_consts: &PushConsts, + ) { + #function + let gid = global_id.x as usize; + // Only process up to n, which is the length of the buffers. + if global_id.x < push_consts.n { + y[gid] = node_graph(a[gid]); + } + } + } + } + } } diff --git a/node-graph/gstd/src/memo.rs b/node-graph/gstd/src/memo.rs index f97fd21b..443f8777 100644 --- a/node-graph/gstd/src/memo.rs +++ b/node-graph/gstd/src/memo.rs @@ -4,36 +4,36 @@ use std::marker::PhantomData; /// Caches the output of a given Node and acts as a proxy pub struct CacheNode<'n, CachedNode: Node<'n>> { - node: CachedNode, - cache: OnceCell, - _phantom: PhantomData<&'n ()>, + node: CachedNode, + cache: OnceCell, + _phantom: PhantomData<&'n ()>, } impl<'n, CashedNode: Node<'n>> Node<'n> for CacheNode<'n, CashedNode> where - CashedNode::Output: 'n, + CashedNode::Output: 'n, { - type Output = &'n CashedNode::Output; - fn eval(&'n self) -> Self::Output { - self.cache.get_or_init(|| self.node.eval()) - } + type Output = &'n CashedNode::Output; + fn eval(&'n self) -> Self::Output { + self.cache.get_or_init(|| self.node.eval()) + } } impl<'n, CachedNode: Node<'n>> CacheNode<'n, CachedNode> { - pub fn clear(&'n mut self) { - self.cache = OnceCell::new(); - } - pub fn new(node: CachedNode) -> CacheNode<'n, CachedNode> { - CacheNode { - node, - cache: OnceCell::new(), - _phantom: PhantomData, - } - } + pub fn clear(&'n mut self) { + self.cache = OnceCell::new(); + } + pub fn new(node: CachedNode) -> CacheNode<'n, CachedNode> { + CacheNode { + node, + cache: OnceCell::new(), + _phantom: PhantomData, + } + } } impl<'n, CachedNode: Node<'n>> Cache for CacheNode<'n, CachedNode> { - fn clear(&mut self) { - self.cache = OnceCell::new(); - } + fn clear(&mut self) { + self.cache = OnceCell::new(); + } } /*use dyn_any::{DynAny, StaticType}; diff --git a/node-graph/gstd/src/value.rs b/node-graph/gstd/src/value.rs index 46fc9299..9759075d 100644 --- a/node-graph/gstd/src/value.rs +++ b/node-graph/gstd/src/value.rs @@ -7,43 +7,43 @@ use dyn_any::{DynAny, StaticType, StaticTypeSized}; pub struct AnyRefNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>); impl<'n, N: Node<'n, Output = &'n O>, O: DynAny<'n> + 'n> Node<'n> for AnyRefNode<'n, N> { - type Output = &'n (dyn DynAny<'n>); - fn eval(&'n self) -> Self::Output { - let value: &O = self.0.eval(); - value - } + type Output = &'n (dyn DynAny<'n>); + fn eval(&'n self) -> Self::Output { + let value: &O = self.0.eval(); + value + } } impl<'n, N: Node<'n, Output = &'n O>, O: 'n + ?Sized> AnyRefNode<'n, N> { - pub fn new(n: N) -> AnyRefNode<'n, N> { - AnyRefNode(n, PhantomData) - } + pub fn new(n: N) -> AnyRefNode<'n, N> { + AnyRefNode(n, PhantomData) + } } pub struct StorageNode<'n>(&'n dyn Node<'n, Output = &'n dyn DynAny<'n>>); impl<'n> Node<'n> for StorageNode<'n> { - type Output = &'n (dyn DynAny<'n>); - fn eval(&'n self) -> Self::Output { - self.0.eval() - } + type Output = &'n (dyn DynAny<'n>); + fn eval(&'n self) -> Self::Output { + self.0.eval() + } } impl<'n> StorageNode<'n> { - pub fn new>>(n: &'n N) -> StorageNode<'n> { - StorageNode(n) - } + pub fn new>>(n: &'n N) -> StorageNode<'n> { + StorageNode(n) + } } #[derive(Default)] pub struct AnyValueNode<'n, T>(T, PhantomData<&'n ()>); impl<'n, T: 'n + DynAny<'n>> Node<'n> for AnyValueNode<'n, T> { - type Output = &'n dyn DynAny<'n>; - fn eval(&'n self) -> &'n dyn DynAny<'n> { - &self.0 - } + type Output = &'n dyn DynAny<'n>; + fn eval(&'n self) -> &'n dyn DynAny<'n> { + &self.0 + } } impl<'n, T> AnyValueNode<'n, T> { - pub const fn new(value: T) -> AnyValueNode<'n, T> { - AnyValueNode(value, PhantomData) - } + pub const fn new(value: T) -> AnyValueNode<'n, T> { + AnyValueNode(value, PhantomData) + } } diff --git a/node-graph/proc-macro/Cargo.toml b/node-graph/proc-macro/Cargo.toml index f9c6e682..81ba705d 100644 --- a/node-graph/proc-macro/Cargo.toml +++ b/node-graph/proc-macro/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "graph-proc-macros" version = "0.1.0" -authors = ["Dennis Kobert "] +authors = ["Graphite Authors "] edition = "2021" publish = false diff --git a/node-graph/proc-macro/src/lib.rs b/node-graph/proc-macro/src/lib.rs index c437ee79..a56629a5 100644 --- a/node-graph/proc-macro/src/lib.rs +++ b/node-graph/proc-macro/src/lib.rs @@ -31,8 +31,9 @@ pub fn to_node(_attr: TokenStream, item: TokenStream) -> TokenStream { let string = item.to_string(); let item2 = item; let parsed = parse_macro_input!(item2 as ItemFn); // 3 - //item.extend(generate_to_string(parsed, string)); // 4 - //item + + //item.extend(generate_to_string(parsed, string)); // 4 + //item generate_to_string(parsed, string) } @@ -40,7 +41,8 @@ fn generate_to_string(parsed: ItemFn, string: String) -> TokenStream { let whole_function = parsed.clone(); //let fn_body = parsed.block; // function body 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 fn_args = sig.inputs; // comma separated args let fn_return_type = sig.output; // return type @@ -78,19 +80,18 @@ fn generate_to_string(parsed: ItemFn, string: String) -> TokenStream { } fn #node_fn_name #generics() -> Node<'static> { Node { func: Box::new(move |x| { - let args = x.downcast::<(#(#types,)*)>().expect(#error); - let (#(#idents,)*) = *args; - #whole_function + let args = x.downcast::<(#(#types,)*)>().expect(#error); + let (#(#idents,)*) = *args; + #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(), args: format!("({})",#arg_type_string.trim()), position: (0., 0.), } } - }; //panic!("{}\n{:?}", x.to_string(), x); x.into()