mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-04 05:18:19 +00:00
Bump dyn-any version + format code
This commit is contained in:
parent
c44e9d22e3
commit
d09f023618
12 changed files with 464 additions and 513 deletions
|
@ -1,79 +1,71 @@
|
|||
use std::{
|
||||
marker::PhantomData,
|
||||
mem::MaybeUninit,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
marker::PhantomData,
|
||||
mem::MaybeUninit,
|
||||
pin::Pin,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
pub trait BorrowStack<'n> {
|
||||
type Item;
|
||||
unsafe fn push(&'n self, value: Self::Item);
|
||||
unsafe fn pop(&'n self);
|
||||
unsafe fn get(&'n self) -> &'n [Self::Item];
|
||||
type Item;
|
||||
unsafe fn push(&'n self, value: Self::Item);
|
||||
unsafe fn pop(&'n self);
|
||||
unsafe fn get(&'n self) -> &'n [Self::Item];
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FixedSizeStack<'n, T> {
|
||||
data: Pin<Box<[MaybeUninit<T>]>>,
|
||||
capacity: usize,
|
||||
len: AtomicUsize,
|
||||
_phantom: PhantomData<&'n ()>,
|
||||
data: Pin<Box<[MaybeUninit<T>]>>,
|
||||
capacity: usize,
|
||||
len: AtomicUsize,
|
||||
_phantom: PhantomData<&'n ()>,
|
||||
}
|
||||
|
||||
impl<'n, T: Unpin> FixedSizeStack<'n, T> {
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap();
|
||||
let array = unsafe { std::alloc::alloc(layout) };
|
||||
let array = Pin::new(unsafe {
|
||||
Box::from_raw(
|
||||
std::slice::from_raw_parts_mut(array as *mut MaybeUninit<T>, capacity)
|
||||
as *mut [MaybeUninit<T>],
|
||||
)
|
||||
});
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
let layout = std::alloc::Layout::array::<MaybeUninit<T>>(capacity).unwrap();
|
||||
let array = unsafe { std::alloc::alloc(layout) };
|
||||
let array = Pin::new(unsafe { Box::from_raw(std::slice::from_raw_parts_mut(array as *mut MaybeUninit<T>, capacity) as *mut [MaybeUninit<T>]) });
|
||||
|
||||
Self {
|
||||
data: array,
|
||||
capacity,
|
||||
len: AtomicUsize::new(0),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
Self {
|
||||
data: array,
|
||||
capacity,
|
||||
len: AtomicUsize::new(0),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.len.load(Ordering::SeqCst)
|
||||
}
|
||||
pub fn len(&self) -> usize {
|
||||
self.len.load(Ordering::SeqCst)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T> BorrowStack<'n> for FixedSizeStack<'n, T> {
|
||||
type Item = T;
|
||||
type Item = T;
|
||||
|
||||
unsafe fn push(&'n self, value: Self::Item) {
|
||||
let len = self.len.load(Ordering::SeqCst);
|
||||
assert!(len < self.capacity);
|
||||
let ptr = self.data[len].as_ptr();
|
||||
(ptr as *mut T).write(value);
|
||||
self.len.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
unsafe fn push(&'n self, value: Self::Item) {
|
||||
let len = self.len.load(Ordering::SeqCst);
|
||||
assert!(len < self.capacity);
|
||||
let ptr = self.data[len].as_ptr();
|
||||
(ptr as *mut T).write(value);
|
||||
self.len.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
unsafe fn pop(&'n self) {
|
||||
let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr();
|
||||
Box::from_raw(ptr as *mut T);
|
||||
self.len.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
unsafe fn pop(&'n self) {
|
||||
let ptr = self.data[self.len.load(Ordering::SeqCst)].as_ptr();
|
||||
Box::from_raw(ptr as *mut T);
|
||||
self.len.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
unsafe fn get(&'n self) -> &'n [Self::Item] {
|
||||
std::slice::from_raw_parts(
|
||||
self.data.as_ptr() as *const T,
|
||||
self.len.load(Ordering::SeqCst),
|
||||
)
|
||||
}
|
||||
unsafe fn get(&'n self) -> &'n [Self::Item] {
|
||||
std::slice::from_raw_parts(self.data.as_ptr() as *const T, self.len.load(Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = 2 + 2;
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = 2 + 2;
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,32 @@
|
|||
use core::marker::PhantomData;
|
||||
|
||||
use crate::Node;
|
||||
pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'n>, O>(
|
||||
T,
|
||||
N,
|
||||
PhantomData<&'n O>,
|
||||
);
|
||||
pub struct FnNode<'n, T: Fn(<N as Node<'n>>::Output) -> O, N: Node<'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> {
|
||||
type Output = O;
|
||||
type Output = O;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval())
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0(self.1.eval())
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
FnNode(f, input, PhantomData)
|
||||
}
|
||||
pub fn new(f: T, input: N) -> Self {
|
||||
FnNode(f, input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
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>);
|
||||
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;
|
||||
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>);
|
||||
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 {
|
||||
self.0(self.1.eval(), &self.2)
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
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>
|
||||
FnNodeWithState<'n, T, N, O, State>
|
||||
{
|
||||
pub fn new(f: T, input: N, state: State) -> Self {
|
||||
FnNodeWithState(f, input, state, PhantomData)
|
||||
}
|
||||
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> {
|
||||
pub fn new(f: T, input: N, state: State) -> Self {
|
||||
FnNodeWithState(f, input, state, PhantomData)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,62 +14,62 @@ pub mod ops;
|
|||
pub mod value;
|
||||
|
||||
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 {
|
||||
type Output = N::Output;
|
||||
type Output = N::Output;
|
||||
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
Node::eval(*self)
|
||||
}
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
Node::eval(*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NodeInput {
|
||||
type Nodes;
|
||||
type Nodes;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self;
|
||||
fn new(input: Self::Nodes) -> Self;
|
||||
}
|
||||
|
||||
trait FQN {
|
||||
fn fqn(&self) -> &'static str;
|
||||
fn fqn(&self) -> &'static str;
|
||||
}
|
||||
|
||||
trait Input<I> {
|
||||
unsafe fn input(&self, input: I);
|
||||
unsafe fn input(&self, input: I);
|
||||
}
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
#[async_trait]
|
||||
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")]
|
||||
#[async_trait]
|
||||
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 {
|
||||
Node::eval(self)
|
||||
}
|
||||
async fn eval_async(&'n self) -> Self::Output {
|
||||
Node::eval(self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Cache {
|
||||
fn clear(&mut self);
|
||||
fn clear(&mut self);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
extern crate alloc;
|
||||
#[cfg(not(feature = "gpu"))]
|
||||
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 {
|
||||
self.as_ref().eval(input)
|
||||
}
|
||||
fn eval(&'n self, input: &'n I) -> Self::Output {
|
||||
self.as_ref().eval(input)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,165 +3,156 @@ use core::{marker::PhantomData, ops::Add};
|
|||
use crate::{Node, NodeInput};
|
||||
|
||||
#[repr(C)]
|
||||
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)>,
|
||||
);
|
||||
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()
|
||||
}
|
||||
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)>);
|
||||
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>>
|
||||
AddNode<'n, L, R, I1, I2>
|
||||
{
|
||||
pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> {
|
||||
AddNode(input.0, input.1, PhantomData)
|
||||
}
|
||||
impl<'n, L: Add<R>, R, I1: Node<'n, Output = L>, I2: Node<'n, Output = R>> AddNode<'n, L, R, I1, I2> {
|
||||
pub fn new(input: (I1, I2)) -> AddNode<'n, L, R, I1, I2> {
|
||||
AddNode(input.0, input.1, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
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> {
|
||||
type Output = O;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval().clone()
|
||||
}
|
||||
type Output = O;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval().clone()
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n, Output = &'n O>, O: Clone> CloneNode<'n, N, O> {
|
||||
pub const fn new(node: N) -> CloneNode<'n, N, O> {
|
||||
CloneNode(node, PhantomData)
|
||||
}
|
||||
pub const fn new(node: N) -> CloneNode<'n, N, O> {
|
||||
CloneNode(node, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
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> {
|
||||
type Output = T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (a, _) = self.0.eval();
|
||||
a
|
||||
}
|
||||
type Output = T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (a, _) = self.0.eval();
|
||||
a
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Destructures a Tuple of two values and returns the first one
|
||||
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> {
|
||||
type Output = U;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (_, b) = self.0.eval();
|
||||
b
|
||||
}
|
||||
type Output = U;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
let (_, b) = self.0.eval();
|
||||
b
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return a tuple with two instances of the input argument
|
||||
pub struct DupNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
||||
impl<'n, N: Node<'n>> Node<'n> for DupNode<'n, N> {
|
||||
type Output = (N::Output, N::Output);
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
(self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation
|
||||
}
|
||||
type Output = (N::Output, N::Output);
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
(self.0.eval(), self.0.eval()) //TODO: use Copy/Clone implementation
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n>> NodeInput for DupNode<'n, N> {
|
||||
type Nodes = N;
|
||||
type Nodes = N;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return the Input Argument
|
||||
pub struct IdNode<'n, N: Node<'n>>(N, PhantomData<&'n ()>);
|
||||
impl<'n, N: Node<'n>> Node<'n> for IdNode<'n, N> {
|
||||
type Output = N::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval()
|
||||
}
|
||||
type Output = N::Output;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
self.0.eval()
|
||||
}
|
||||
}
|
||||
impl<'n, N: Node<'n>> NodeInput for IdNode<'n, N> {
|
||||
type Nodes = N;
|
||||
type Nodes = N;
|
||||
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
fn new(input: Self::Nodes) -> Self {
|
||||
Self(input, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn foo() {
|
||||
let unit = crate::value::UnitNode;
|
||||
let value = IdNode(crate::value::ValueNode(2u32), PhantomData);
|
||||
let value2 = crate::value::ValueNode(4u32);
|
||||
let dup = DupNode(&value, PhantomData);
|
||||
fn int(_: (), state: &u32) -> &u32 {
|
||||
state
|
||||
}
|
||||
fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) {
|
||||
(input.1, input.0)
|
||||
}
|
||||
let fnn = crate::generic::FnNode::new(swap, &dup);
|
||||
let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32);
|
||||
let _ = fnn.eval();
|
||||
let _ = fns.eval();
|
||||
let snd = SndNode(&fnn, PhantomData);
|
||||
let _ = snd.eval();
|
||||
let add = AddNode(&snd, value2, PhantomData);
|
||||
let _ = add.eval();
|
||||
let unit = crate::value::UnitNode;
|
||||
let value = IdNode(crate::value::ValueNode(2u32), PhantomData);
|
||||
let value2 = crate::value::ValueNode(4u32);
|
||||
let dup = DupNode(&value, PhantomData);
|
||||
fn int(_: (), state: &u32) -> &u32 {
|
||||
state
|
||||
}
|
||||
fn swap<'n>(input: (&'n u32, &'n u32)) -> (&'n u32, &'n u32) {
|
||||
(input.1, input.0)
|
||||
}
|
||||
let fnn = crate::generic::FnNode::new(swap, &dup);
|
||||
let fns = crate::generic::FnNodeWithState::new(int, &unit, 42u32);
|
||||
let _ = fnn.eval();
|
||||
let _ = fns.eval();
|
||||
let snd = SndNode(&fnn, PhantomData);
|
||||
let _ = snd.eval();
|
||||
let add = AddNode(&snd, value2, PhantomData);
|
||||
let _ = add.eval();
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "spirv")]
|
||||
pub mod gpu {
|
||||
//#![deny(warnings)]
|
||||
#[repr(C)]
|
||||
pub struct PushConsts {
|
||||
n: u32,
|
||||
node: u32,
|
||||
}
|
||||
use super::*;
|
||||
use crate::{structural::ComposeNodeOwned, Node};
|
||||
//use crate::Node;
|
||||
use spirv_std::glam::UVec3;
|
||||
const ADD: AddNode<u32> = AddNode(PhantomData);
|
||||
const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> =
|
||||
ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
|
||||
//#![deny(warnings)]
|
||||
#[repr(C)]
|
||||
pub struct PushConsts {
|
||||
n: u32,
|
||||
node: u32,
|
||||
}
|
||||
use super::*;
|
||||
use crate::{structural::ComposeNodeOwned, Node};
|
||||
//use crate::Node;
|
||||
use spirv_std::glam::UVec3;
|
||||
const ADD: AddNode<u32> = AddNode(PhantomData);
|
||||
const OPERATION: ComposeNodeOwned<'_, (u32, u32), u32, FstNode<u32, u32>, DupNode<u32>> = ComposeNodeOwned::new(FstNode(PhantomData, PhantomData), DupNode(PhantomData));
|
||||
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn spread(
|
||||
#[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 = 1)] y: &mut [(u32, u32)],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
fn node_graph(input: Input) -> Output {
|
||||
let n0 = ValueNode::new(input);
|
||||
let n1 = IdNode::new(n0);
|
||||
let n2 = IdNode::new(n1);
|
||||
return n2.eval();
|
||||
}
|
||||
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 add(
|
||||
#[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 = 1)] y: &mut [u32],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
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] = ADD.eval(a[gid]);
|
||||
}
|
||||
}
|
||||
#[allow(unused)]
|
||||
#[spirv(compute(threads(64)))]
|
||||
pub fn spread(
|
||||
#[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 = 1)] y: &mut [(u32, u32)],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
fn node_graph(input: Input) -> Output {
|
||||
let n0 = ValueNode::new(input);
|
||||
let n1 = IdNode::new(n0);
|
||||
let n2 = IdNode::new(n1);
|
||||
return n2.eval();
|
||||
}
|
||||
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 add(
|
||||
#[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 = 1)] y: &mut [u32],
|
||||
#[spirv(push_constant)] push_consts: &PushConsts,
|
||||
) {
|
||||
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] = ADD.eval(a[gid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,57 +6,57 @@ use crate::Node;
|
|||
|
||||
pub struct IntNode<const N: u32>;
|
||||
impl<'n, const N: u32> Node<'n> for IntNode<N> {
|
||||
type Output = u32;
|
||||
fn eval(&self) -> u32 {
|
||||
N
|
||||
}
|
||||
type Output = u32;
|
||||
fn eval(&self) -> u32 {
|
||||
N
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ValueNode<T>(pub T);
|
||||
impl<'n, T: 'n> Node<'n> for ValueNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
impl<T> ValueNode<T> {
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
pub const fn new(value: T) -> ValueNode<T> {
|
||||
ValueNode(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DefaultNode<T>(PhantomData<T>);
|
||||
impl<'n, T: Default + 'n> Node<'n> for DefaultNode<T> {
|
||||
type Output = T;
|
||||
fn eval(&self) -> T {
|
||||
T::default()
|
||||
}
|
||||
type Output = T;
|
||||
fn eval(&self) -> T {
|
||||
T::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
/// Return the unit value
|
||||
pub struct UnitNode;
|
||||
impl<'n> Node<'n> for UnitNode {
|
||||
type Output = ();
|
||||
fn eval(&'n self) -> Self::Output {}
|
||||
type Output = ();
|
||||
fn eval(&'n self) -> Self::Output {}
|
||||
}
|
||||
|
||||
pub struct InputNode<T>(MaybeUninit<T>, AtomicBool);
|
||||
impl<'n, T: 'n> Node<'n> for InputNode<T> {
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
panic!("tried to access an input before setting it")
|
||||
}
|
||||
}
|
||||
type Output = &'n T;
|
||||
fn eval(&'n self) -> Self::Output {
|
||||
if self.1.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
unsafe { self.0.assume_init_ref() }
|
||||
} else {
|
||||
panic!("tried to access an input before setting it")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> InputNode<T> {
|
||||
pub const fn new() -> InputNode<T> {
|
||||
InputNode(MaybeUninit::uninit(), AtomicBool::new(false))
|
||||
}
|
||||
pub const fn new() -> InputNode<T> {
|
||||
InputNode(MaybeUninit::uninit(), AtomicBool::new(false))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ pub mod value;
|
|||
pub use graphene_core::{generic, ops /*, structural*/};
|
||||
|
||||
#[cfg(feature = "caching")]
|
||||
pub mod caching;
|
||||
pub mod cache;
|
||||
#[cfg(feature = "memoization")]
|
||||
pub mod memo;
|
||||
|
||||
|
|
|
@ -5,147 +5,144 @@ use graphene_std::value::{AnyRefNode, AnyValueNode, StorageNode, ValueNode};
|
|||
use graphene_std::*;
|
||||
|
||||
/*fn mul(#[dyn_any(default)] a: f32, b: f32) -> f32 {
|
||||
a * b
|
||||
a * b
|
||||
}*/
|
||||
|
||||
mod mul {
|
||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
||||
use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node};
|
||||
pub struct MulNodeInput<'n> {
|
||||
pub a: &'n f32,
|
||||
pub b: &'n f32,
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MulNodeAnyProxy<'n> {
|
||||
pub a: Option<DynAnyNode<'n>>,
|
||||
pub b: Option<DynAnyNode<'n>>,
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MulNodeTypedProxy<'n> {
|
||||
pub a: Option<DynNode<'n, &'n f32>>,
|
||||
pub b: Option<DynNode<'n, &'n f32>>,
|
||||
}
|
||||
impl<'n> Node<'n> for MulNodeAnyProxy<'n> {
|
||||
type Output = MulNodeInput<'n>;
|
||||
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
|
||||
let a = self.a.unwrap().eval();
|
||||
let a: &f32 = self
|
||||
.a
|
||||
.map(|v| downcast_ref(v.eval()).unwrap())
|
||||
.unwrap_or(&1.);
|
||||
/*let b: &f32 = self
|
||||
.b
|
||||
.map(|v| v.eval(&()).downcast_ref::<&'n f32, &'n f32>().unwrap())
|
||||
.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 {
|
||||
let a = self.a.unwrap().eval();
|
||||
let b = self.b.unwrap().eval();
|
||||
MulNodeInput { a, b }
|
||||
}
|
||||
}
|
||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
||||
use graphene_std::{DynAnyNode, DynNode, DynamicInput, Node};
|
||||
pub struct MulNodeInput<'n> {
|
||||
pub a: &'n f32,
|
||||
pub b: &'n f32,
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MulNodeAnyProxy<'n> {
|
||||
pub a: Option<DynAnyNode<'n>>,
|
||||
pub b: Option<DynAnyNode<'n>>,
|
||||
}
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MulNodeTypedProxy<'n> {
|
||||
pub a: Option<DynNode<'n, &'n f32>>,
|
||||
pub b: Option<DynNode<'n, &'n f32>>,
|
||||
}
|
||||
impl<'n> Node<'n> for MulNodeAnyProxy<'n> {
|
||||
type Output = MulNodeInput<'n>;
|
||||
fn eval(&'n self) -> <Self as graphene_std::Node<'n>>::Output {
|
||||
let a = self.a.unwrap().eval();
|
||||
let a: &f32 = self.a.map(|v| downcast_ref(v.eval()).unwrap()).unwrap_or(&1.);
|
||||
/*let b: &f32 = self
|
||||
.b
|
||||
.map(|v| v.eval(&()).downcast_ref::<&'n f32, &'n f32>().unwrap())
|
||||
.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 {
|
||||
let a = self.a.unwrap().eval();
|
||||
let b = self.b.unwrap().eval();
|
||||
MulNodeInput { a, b }
|
||||
}
|
||||
}
|
||||
|
||||
/*macro_rules! new {
|
||||
() => {
|
||||
mul::MulNode { a: None, b: None }
|
||||
};
|
||||
}*/
|
||||
//pub(crate) use new;
|
||||
/*macro_rules! new {
|
||||
() => {
|
||||
mul::MulNode { a: None, b: None }
|
||||
};
|
||||
}*/
|
||||
//pub(crate) use new;
|
||||
|
||||
impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> {
|
||||
fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>) {
|
||||
todo!()
|
||||
}
|
||||
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) {
|
||||
match index {
|
||||
0 => {
|
||||
self.a = Some(value);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'n> DynamicInput<'n> for MulNodeAnyProxy<'n> {
|
||||
fn set_kwarg_by_name(&mut self, name: &str, value: DynAnyNode<'n>) {
|
||||
todo!()
|
||||
}
|
||||
fn set_arg_by_index(&mut self, index: usize, value: DynAnyNode<'n>) {
|
||||
match index {
|
||||
0 => {
|
||||
self.a = Some(value);
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
type SNode<'n> = dyn Node<'n, Output = &'n dyn DynAny<'n>>;
|
||||
|
||||
struct NodeStore<'n>(borrow_stack::FixedSizeStack<'n, Box<SNode<'n>>>);
|
||||
|
||||
impl<'n> NodeStore<'n> {
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) {
|
||||
unsafe { self.0.push(f(self.0.get())) };
|
||||
}
|
||||
fn push(&'n mut self, f: fn(&'n [Box<SNode>]) -> Box<SNode<'n>>) {
|
||||
unsafe { self.0.push(f(self.0.get())) };
|
||||
}
|
||||
|
||||
/*fn get_index(&'n self, index: usize) -> &'n SNode<'n> {
|
||||
assert!(index < self.0.len());
|
||||
&unsafe { self.0.get()[index] }
|
||||
}*/
|
||||
/*fn get_index(&'n self, index: usize) -> &'n SNode<'n> {
|
||||
assert!(index < self.0.len());
|
||||
&unsafe { self.0.get()[index] }
|
||||
}*/
|
||||
}
|
||||
|
||||
fn main() {
|
||||
use graphene_std::*;
|
||||
use quote::quote;
|
||||
use syn::parse::Parse;
|
||||
let nodes = vec![
|
||||
NodeKind::Input,
|
||||
NodeKind::Value(syn::parse_quote!(1u32)),
|
||||
NodeKind::Node(syn::parse_quote!(graphene_core::ops::AddNode), vec![0, 0]),
|
||||
];
|
||||
use graphene_std::*;
|
||||
use quote::quote;
|
||||
use syn::parse::Parse;
|
||||
let nodes = vec![
|
||||
NodeKind::Input,
|
||||
NodeKind::Value(syn::parse_quote!(1u32)),
|
||||
NodeKind::Node(syn::parse_quote!(graphene_core::ops::AddNode), vec![0, 0]),
|
||||
];
|
||||
|
||||
//println!("{}", node_graph(1));
|
||||
//println!("{}", node_graph(1));
|
||||
|
||||
let nodegraph = NodeGraph {
|
||||
nodes,
|
||||
input: syn::Type::Verbatim(quote! {u32}),
|
||||
output: syn::Type::Verbatim(quote! {u32}),
|
||||
};
|
||||
let nodegraph = NodeGraph {
|
||||
nodes,
|
||||
input: syn::Type::Verbatim(quote! {u32}),
|
||||
output: syn::Type::Verbatim(quote! {u32}),
|
||||
};
|
||||
|
||||
//let pretty = pretty_token_stream::Pretty::new(nodegraph.serialize_gpu("add"));
|
||||
//pretty.print();
|
||||
/*
|
||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
||||
//let mut mul = mul::MulNode::new();
|
||||
let mut stack: borrow_stack::FixedSizeStack<Box<dyn Node<'_, Output = &dyn DynAny>>> =
|
||||
borrow_stack::FixedSizeStack::new(42);
|
||||
unsafe { stack.push(Box::new(AnyValueNode::new(1f32))) };
|
||||
//let node = unsafe { stack.get(0) };
|
||||
//let boxed = Box::new(StorageNode::new(node));
|
||||
//unsafe { stack.push(boxed) };
|
||||
let result = unsafe { &stack.get()[0] }.eval();
|
||||
dbg!(downcast_ref::<f32>(result));
|
||||
/*unsafe {
|
||||
stack
|
||||
.push(Box::new(AnyRefNode::new(stack.get(0).as_ref()))
|
||||
as Box<dyn Node<(), Output = &dyn DynAny>>)
|
||||
};*/
|
||||
let f = (3.2f32, 3.1f32);
|
||||
let a = ValueNode::new(1.);
|
||||
let id = std::any::TypeId::of::<&f32>();
|
||||
let any_a = AnyRefNode::new(&a);
|
||||
/*let _mul2 = mul::MulNodeInput {
|
||||
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>;
|
||||
Node::eval(&int);
|
||||
println!("{}", Node::eval(&int));
|
||||
//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 cache = memo::CacheNode::new(&fnode);
|
||||
//let cached_result = cache.eval(&(2, 3));
|
||||
*/
|
||||
//println!("{}", cached_result)
|
||||
//let pretty = pretty_token_stream::Pretty::new(nodegraph.serialize_gpu("add"));
|
||||
//pretty.print();
|
||||
/*
|
||||
use dyn_any::{downcast_ref, DynAny, StaticType};
|
||||
//let mut mul = mul::MulNode::new();
|
||||
let mut stack: borrow_stack::FixedSizeStack<Box<dyn Node<'_, Output = &dyn DynAny>>> =
|
||||
borrow_stack::FixedSizeStack::new(42);
|
||||
unsafe { stack.push(Box::new(AnyValueNode::new(1f32))) };
|
||||
//let node = unsafe { stack.get(0) };
|
||||
//let boxed = Box::new(StorageNode::new(node));
|
||||
//unsafe { stack.push(boxed) };
|
||||
let result = unsafe { &stack.get()[0] }.eval();
|
||||
dbg!(downcast_ref::<f32>(result));
|
||||
/*unsafe {
|
||||
stack
|
||||
.push(Box::new(AnyRefNode::new(stack.get(0).as_ref()))
|
||||
as Box<dyn Node<(), Output = &dyn DynAny>>)
|
||||
};*/
|
||||
let f = (3.2f32, 3.1f32);
|
||||
let a = ValueNode::new(1.);
|
||||
let id = std::any::TypeId::of::<&f32>();
|
||||
let any_a = AnyRefNode::new(&a);
|
||||
/*let _mul2 = mul::MulNodeInput {
|
||||
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>;
|
||||
Node::eval(&int);
|
||||
println!("{}", Node::eval(&int));
|
||||
//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 cache = memo::CacheNode::new(&fnode);
|
||||
//let cached_result = cache.eval(&(2, 3));
|
||||
*/
|
||||
//println!("{}", cached_result)
|
||||
}
|
||||
|
|
|
@ -5,106 +5,93 @@ use syn::punctuated::Punctuated;
|
|||
use syn::{parse_macro_input, FnArg, ItemFn, Pat, Type};
|
||||
|
||||
fn extract_type(a: FnArg) -> Type {
|
||||
match a {
|
||||
FnArg::Typed(p) => *p.ty, // notice `ty` instead of `pat`
|
||||
_ => panic!("Not supported on types with `self`!"),
|
||||
}
|
||||
match a {
|
||||
FnArg::Typed(p) => *p.ty, // notice `ty` instead of `pat`
|
||||
_ => panic!("Not supported on types with `self`!"),
|
||||
}
|
||||
}
|
||||
|
||||
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_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 {
|
||||
match a {
|
||||
FnArg::Typed(p) => *p.pat,
|
||||
_ => panic!("Not supported on types with `self`!"),
|
||||
}
|
||||
match a {
|
||||
FnArg::Typed(p) => *p.pat,
|
||||
_ => panic!("Not supported on types with `self`!"),
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro_attribute] // 2
|
||||
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
|
||||
generate_to_string(parsed, string)
|
||||
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
|
||||
generate_to_string(parsed, string)
|
||||
}
|
||||
|
||||
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 generics = sig.generics;
|
||||
let fn_args = sig.inputs; // comma separated args
|
||||
let fn_return_type = sig.output; // return type
|
||||
let fn_name = sig.ident; // function name/identifier
|
||||
let idents = extract_arg_idents(fn_args.clone());
|
||||
let types = extract_arg_types(fn_args);
|
||||
let types = types
|
||||
.iter()
|
||||
.map(|t| t.to_token_stream())
|
||||
.collect::<Vec<_>>();
|
||||
let idents = idents
|
||||
.iter()
|
||||
.map(|t| t.to_token_stream())
|
||||
.collect::<Vec<_>>();
|
||||
let const_idents = idents
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let name = t.to_string().to_uppercase();
|
||||
quote! {#name}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
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 generics = sig.generics;
|
||||
let fn_args = sig.inputs; // comma separated args
|
||||
let fn_return_type = sig.output; // return type
|
||||
let fn_name = sig.ident; // function name/identifier
|
||||
let idents = extract_arg_idents(fn_args.clone());
|
||||
let types = extract_arg_types(fn_args);
|
||||
let types = types.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
||||
let idents = idents.iter().map(|t| t.to_token_stream()).collect::<Vec<_>>();
|
||||
let const_idents = idents
|
||||
.iter()
|
||||
.map(|t| {
|
||||
let name = t.to_string().to_uppercase();
|
||||
quote! {#name}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let node_fn_name = fn_name.append("_node");
|
||||
let struct_name = fn_name.append("_input");
|
||||
let return_type_string = fn_return_type
|
||||
.to_token_stream()
|
||||
.to_string()
|
||||
.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 node_fn_name = fn_name.append("_node");
|
||||
let struct_name = fn_name.append("_input");
|
||||
let return_type_string = fn_return_type.to_token_stream().to_string().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! {
|
||||
//#whole_function
|
||||
mod #fn_name {
|
||||
#[derive(Copy, Clone)]
|
||||
type F32Node<'n> = &'n (dyn Node<'n, (), Output = &'n (dyn Any + 'static)> + 'n);
|
||||
struct #struct_name {
|
||||
#(#idents: #types,)*
|
||||
}
|
||||
impl Node for #struct_name {
|
||||
let x = quote! {
|
||||
//#whole_function
|
||||
mod #fn_name {
|
||||
#[derive(Copy, Clone)]
|
||||
type F32Node<'n> = &'n (dyn Node<'n, (), Output = &'n (dyn Any + 'static)> + 'n);
|
||||
struct #struct_name {
|
||||
#(#idents: #types,)*
|
||||
}
|
||||
impl Node for #struct_name {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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
|
||||
}
|
||||
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
|
||||
|
||||
Box::new(#fn_name(#(#idents,)*))
|
||||
}),
|
||||
code: #string.to_string(),
|
||||
return_type: #return_type_string.trim().to_string(),
|
||||
args: format!("({})",#arg_type_string.trim()),
|
||||
position: (0., 0.),
|
||||
}
|
||||
}
|
||||
Box::new(#fn_name(#(#idents,)*))
|
||||
}),
|
||||
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()
|
||||
};
|
||||
//panic!("{}\n{:?}", x.to_string(), x);
|
||||
x.into()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue