mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 07:48:02 +08:00
Incremental compilation and stable node IDs (#977)
* Generate stable node ids * checkpoint * Implement borrow tree * Add eval function on borrow tree * Refactor Node trait to fix lifetime issues * Compiler infinite loop * Impl compose pair * Transition to double lifetime on trait * Change node trait to use a generic arg for the input * Start adapting node_macro * Migrate more nodes to new macro * Fix raster tests * Port vector nodes * Make Node trait object safe * Fix FlatMapResultNode * Translate most of gstd * Fix DowncastBothNode * Refactor node trait once again to allow for HRTB for type erased nodes * Start working on type erased nodes * Try getting DowncastBothNode to work * Introduce Upcasting node + work on BorrowTree * Make enough 'static to get the code to compile * Transition DynamicExecutor to use borrow tree * Make Compose Node use HRTB's * Fix MapResultNode * Disable blur test * Add workaround for Composing type erased nodes * Convert more nodes in the node_registry * Convert more of the node_registry * Add update tree fn and hook up to frontend * Fix blur node * Implement CacheNode * Make frontend use graph compiler * Fix document_node_types type declaration for most nodes * Remove unused imports * Move comment down * Reuse nodes via borrow tree * Deprecate trait based value in favor of TaggedValue * Remove unsafe code in buffer creation * Fix blur node * Fix stable node id generation * Fix types for Image adjustment document nodes * Fix Imaginate Node * Remove unused imports * Remove log * Fix off by one error * Remove macro generated imaginate node entry * Create parameterized add node * Fix test case * Remove link from layer_panel.rs * Fix formatting
This commit is contained in:
committed by
Keavon Chambers
parent
12d6818d73
commit
004e87ca3e
@@ -1,144 +1,92 @@
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{AsRefNode, Node, RefNode};
|
||||
use crate::Node;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ComposeNode<First, Second, Input> {
|
||||
pub struct ComposeNode<First: for<'i> Node<'i, I>, Second: for<'i> Node<'i, <First as Node<'i, I>>::Output>, I> {
|
||||
first: First,
|
||||
second: Second,
|
||||
_phantom: PhantomData<Input>,
|
||||
phantom: PhantomData<I>,
|
||||
}
|
||||
|
||||
impl<Input, Inter, First, Second> Node<Input> for ComposeNode<First, Second, Input>
|
||||
impl<'i, Input: 'i, First, Second> Node<'i, Input> for ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: Node<Input, Output = Inter>,
|
||||
Second: Node<Inter>,
|
||||
First: for<'a> Node<'a, Input> + 'i,
|
||||
Second: for<'a> Node<'a, <First as Node<'a, Input>>::Output> + 'i,
|
||||
{
|
||||
type Output = <Second as Node<Inter>>::Output;
|
||||
|
||||
fn eval(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);
|
||||
type Output = <Second as Node<'i, <First as Node<'i, Input>>::Output>>::Output;
|
||||
fn eval<'s: 'i>(&'s self, input: Input) -> Self::Output {
|
||||
let arg = self.first.eval(input);
|
||||
self.second.eval(arg)
|
||||
}
|
||||
}
|
||||
impl<'n, Input, Inter, First, Second> Node<Input> for &'n ComposeNode<First, Second, Input>
|
||||
|
||||
impl<First, Second, Input> ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: AsRefNode<'n, Input, Output = Inter>,
|
||||
Second: AsRefNode<'n, Inter>,
|
||||
&'n First: Node<Input, Output = Inter>,
|
||||
&'n Second: Node<Inter>,
|
||||
First: for<'a> Node<'a, Input>,
|
||||
Second: for<'a> Node<'a, <First as Node<'a, Input>>::Output>,
|
||||
{
|
||||
type Output = <Second as AsRefNode<'n, Inter>>::Output;
|
||||
|
||||
fn eval(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_box(input);
|
||||
(self.second).eval_box(arg)
|
||||
}
|
||||
}
|
||||
impl<Input, Inter, First, Second> RefNode<Input> for ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: RefNode<Input, Output = Inter> + Copy,
|
||||
Second: RefNode<Inter> + Copy,
|
||||
{
|
||||
type Output = <Second as RefNode<Inter>>::Output;
|
||||
|
||||
fn eval_ref(&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_ref(input);
|
||||
(self.second).eval_ref(arg)
|
||||
}
|
||||
}
|
||||
impl<Input: 'static, First: 'static, Second: 'static> dyn_any::StaticType for ComposeNode<First, Second, Input> {
|
||||
type Static = ComposeNode<First, Second, Input>;
|
||||
}
|
||||
|
||||
impl<'n, Input, First: 'n, Second: 'n> ComposeNode<First, Second, Input> {
|
||||
pub const fn new(first: First, second: Second) -> Self {
|
||||
ComposeNode::<First, Second, Input> { first, second, _phantom: PhantomData }
|
||||
ComposeNode::<First, Second, Input> { first, second, phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Then<Inter, Input>: Sized {
|
||||
// impl Clone for ComposeNode<First, Second, Input>
|
||||
impl<First, Second, Input> Clone for ComposeNode<First, Second, Input>
|
||||
where
|
||||
First: for<'a> Node<'a, Input> + Clone,
|
||||
Second: for<'a> Node<'a, <First as Node<'a, Input>>::Output> + Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
ComposeNode::<First, Second, Input> {
|
||||
first: self.first.clone(),
|
||||
second: self.second.clone(),
|
||||
phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Then<'i, Input: 'i>: Sized {
|
||||
fn then<Second>(self, second: Second) -> ComposeNode<Self, Second, Input>
|
||||
where
|
||||
Self: Node<Input, Output = Inter>,
|
||||
Second: Node<Inter>,
|
||||
Self: for<'a> Node<'a, Input>,
|
||||
Second: for<'a> Node<'a, <Self as Node<'a, Input>>::Output>,
|
||||
{
|
||||
ComposeNode::<Self, Second, Input> {
|
||||
first: self,
|
||||
second,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
ComposeNode::new(self, second)
|
||||
}
|
||||
}
|
||||
|
||||
impl<First: Node<Input, Output = Inter>, Inter, Input> Then<Inter, Input> for First {}
|
||||
impl<'i, First: for<'a> Node<'a, Input>, Input: 'i> Then<'i, Input> for First {}
|
||||
|
||||
pub trait ThenRef<Inter, Input>: Sized {
|
||||
fn after<'n, Second: 'n>(&'n self, second: Second) -> ComposeNode<&'n Self, Second, Input>
|
||||
where
|
||||
&'n Self: Node<Input, Output = Inter> + Copy,
|
||||
Second: Node<Inter>,
|
||||
Self: 'n,
|
||||
{
|
||||
ComposeNode::<&'n Self, Second, Input> {
|
||||
first: self,
|
||||
second,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'n, First: 'n, Inter, Input> ThenRef<Inter, Input> for First where &'n First: Node<Input, Output = Inter> {}
|
||||
pub struct ConsNode<I: From<()>, Root>(pub Root, PhantomData<I>);
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
pub trait ThenBox<Inter, Input> {
|
||||
fn then<'n, Second: 'n>(self, second: Second) -> ComposeNode<Self, Second, Input>
|
||||
where
|
||||
alloc::boxed::Box<Self>: Node<Input, Output = Inter>,
|
||||
Second: Node<Inter> + Copy,
|
||||
Self: Sized,
|
||||
{
|
||||
ComposeNode::<Self, Second, Input> {
|
||||
first: self,
|
||||
second,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "async")]
|
||||
impl<'n, First: 'n, Inter, Input> ThenBox<Inter, Input> for alloc::boxed::Box<First> where &'n alloc::boxed::Box<First>: Node<Input, Output = Inter> {}
|
||||
|
||||
pub struct ConsNode<Root, T: From<()>>(pub Root, pub PhantomData<T>);
|
||||
|
||||
impl<Root, Input, T: From<()>> Node<Input> for ConsNode<Root, T>
|
||||
impl<'i, Root, Input: 'i, I: 'i + From<()>> Node<'i, Input> for ConsNode<I, Root>
|
||||
where
|
||||
Root: Node<T>,
|
||||
Root: Node<'i, I>,
|
||||
{
|
||||
type Output = (Input, <Root as Node<T>>::Output);
|
||||
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
let arg = self.0.eval(().into());
|
||||
(input, arg)
|
||||
}
|
||||
}
|
||||
impl<'n, Root: Node<T> + Copy, T: From<()>, Input> Node<Input> for &'n ConsNode<Root, T> {
|
||||
type Output = (Input, Root::Output);
|
||||
|
||||
fn eval(self, input: Input) -> Self::Output {
|
||||
let arg = self.0.eval(().into());
|
||||
fn eval<'s: 'i>(&'s self, input: Input) -> Self::Output {
|
||||
let arg = self.0.eval(I::from(()));
|
||||
(input, arg)
|
||||
}
|
||||
}
|
||||
impl<Root, T: From<()>> ConsNode<Root, T> {
|
||||
impl<'i, Root: Node<'i, I>, I: 'i + From<()>> ConsNode<I, Root> {
|
||||
pub fn new(root: Root) -> Self {
|
||||
ConsNode(root, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{ops::IdNode, value::ValueNode};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn compose() {
|
||||
let value = ValueNode::new(4u32);
|
||||
let compose = value.then(IdNode::new());
|
||||
assert_eq!(compose.eval(()), &4u32);
|
||||
let type_erased = &compose as &dyn for<'i> Node<'i, (), Output = &'i u32>;
|
||||
assert_eq!(type_erased.eval(()), &4u32);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user