mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 15:28:04 +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,41 +1,36 @@
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Add;
|
||||
|
||||
use crate::{Node, RefNode};
|
||||
use crate::Node;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct AddNode;
|
||||
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<(L, R)> for AddNode {
|
||||
|
||||
impl<'i, L: Add<R, Output = O> + 'i, R: 'i, O: 'i> Node<'i, (L, R)> for AddNode {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(self, input: (L, R)) -> Self::Output {
|
||||
input.0 + input.1
|
||||
}
|
||||
}
|
||||
impl<'n, L: Add<R, Output = O> + 'n, R, O: 'n> Node<(L, R)> for &'n AddNode {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(self, input: (L, R)) -> Self::Output {
|
||||
input.0 + input.1
|
||||
}
|
||||
}
|
||||
impl<'n, L: Add<R, Output = O> + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for AddNode {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(self, input: &'n (L, R)) -> Self::Output {
|
||||
input.0 + input.1
|
||||
}
|
||||
}
|
||||
impl<'n, L: Add<R, Output = O> + 'n + Copy, R: Copy, O: 'n> Node<&'n (L, R)> for &'n AddNode {
|
||||
type Output = <L as Add<R>>::Output;
|
||||
fn eval(self, input: &'n (L, R)) -> Self::Output {
|
||||
fn eval<'s: 'i>(&'s self, input: (L, R)) -> Self::Output {
|
||||
input.0 + input.1
|
||||
}
|
||||
}
|
||||
|
||||
impl AddNode {
|
||||
pub fn new() -> Self {
|
||||
pub const fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
pub struct AddParameterNode<Second> {
|
||||
second: Second,
|
||||
}
|
||||
|
||||
#[node_macro::node_fn(AddParameterNode)]
|
||||
fn flat_map<U, T>(first: U, second: T) -> <U as Add<T>>::Output
|
||||
where
|
||||
U: Add<T>,
|
||||
{
|
||||
first + second
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(feature = "std")]
|
||||
pub mod dynamic {
|
||||
use super::*;
|
||||
@@ -65,9 +60,9 @@ pub mod dynamic {
|
||||
};
|
||||
}
|
||||
|
||||
impl<'n> Node<(Dynamic<'n>, Dynamic<'n>)> for DynamicAddNode {
|
||||
type Output = Dynamic<'n>;
|
||||
fn eval(self, (left, right): (Dynamic, Dynamic)) -> Self::Output {
|
||||
impl<'i> Node<(Dynamic<'i>, Dynamic<'i>)> for DynamicAddNode {
|
||||
type Output = Dynamic<'i>;
|
||||
fn eval<'s: 'i>(self, (left, right): (Dynamic, Dynamic)) -> Self::Output {
|
||||
resolve_dynamic_types! { AddNode =>
|
||||
(left: usize, right: usize)
|
||||
(left: u8, right: u8)
|
||||
@@ -85,106 +80,87 @@ pub mod dynamic {
|
||||
(left: f64, right: f64) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CloneNode;
|
||||
impl<'n, O: Clone> Node<&'n O> for CloneNode {
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct CloneNode<O>(PhantomData<O>);
|
||||
impl<'i, O: Clone + 'i> Node<'i, &'i O> for CloneNode<O> {
|
||||
type Output = O;
|
||||
fn eval(self, input: &'n O) -> Self::Output {
|
||||
fn eval<'s: 'i>(&'s self, input: &'i O) -> Self::Output {
|
||||
input.clone()
|
||||
}
|
||||
}
|
||||
impl<'n, O: Clone> Node<&'n O> for &CloneNode {
|
||||
type Output = O;
|
||||
fn eval(self, input: &'n O) -> Self::Output {
|
||||
input.clone()
|
||||
impl<O> CloneNode<O> {
|
||||
pub const fn new() -> Self {
|
||||
Self(PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct FstNode;
|
||||
impl<'n, T: 'n, U> Node<(T, U)> for FstNode {
|
||||
type Output = T;
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (a, _) = input;
|
||||
a
|
||||
impl<'i, L: 'i, R: 'i> Node<'i, (L, R)> for FstNode {
|
||||
type Output = L;
|
||||
fn eval<'s: 'i>(&'s self, input: (L, R)) -> Self::Output {
|
||||
input.0
|
||||
}
|
||||
}
|
||||
impl<'n, T: 'n, U> Node<&'n (T, U)> for FstNode {
|
||||
type Output = &'n T;
|
||||
fn eval(self, input: &'n (T, U)) -> Self::Output {
|
||||
let (a, _) = input;
|
||||
a
|
||||
impl FstNode {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructures a Tuple of two values and returns the first one
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct SndNode;
|
||||
impl<'n, T, U: 'n> Node<(T, U)> for SndNode {
|
||||
type Output = U;
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (_, b) = input;
|
||||
b
|
||||
impl<'i, L: 'i, R: 'i> Node<'i, (L, R)> for SndNode {
|
||||
type Output = R;
|
||||
fn eval<'s: 'i>(&'s self, input: (L, R)) -> Self::Output {
|
||||
input.1
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T, U: 'n> Node<&'n (T, U)> for SndNode {
|
||||
type Output = &'n U;
|
||||
fn eval(self, input: &'n (T, U)) -> Self::Output {
|
||||
let (_, b) = input;
|
||||
b
|
||||
impl SndNode {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// Destructures a Tuple of two values and returns them in reverse order
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct SwapNode;
|
||||
impl<'n, T: 'n, U: 'n> Node<(T, U)> for SwapNode {
|
||||
type Output = (U, T);
|
||||
fn eval(self, input: (T, U)) -> Self::Output {
|
||||
let (a, b) = input;
|
||||
(b, a)
|
||||
impl<'i, L: 'i, R: 'i> Node<'i, (L, R)> for SwapNode {
|
||||
type Output = (R, L);
|
||||
fn eval<'s: 'i>(&'s self, input: (L, R)) -> Self::Output {
|
||||
(input.1, input.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'n, T, U: 'n> Node<&'n (T, U)> for SwapNode {
|
||||
type Output = (&'n U, &'n T);
|
||||
fn eval(self, input: &'n (T, U)) -> Self::Output {
|
||||
let (a, b) = input;
|
||||
(b, a)
|
||||
impl SwapNode {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// Return a tuple with two instances of the input argument
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct DupNode;
|
||||
impl<'n, T: Clone + 'n> Node<T> for DupNode {
|
||||
type Output = (T, T);
|
||||
fn eval(self, input: T) -> Self::Output {
|
||||
impl<'i, O: Clone + 'i> Node<'i, O> for DupNode {
|
||||
type Output = (O, O);
|
||||
fn eval<'s: 'i>(&'s self, input: O) -> Self::Output {
|
||||
(input.clone(), input)
|
||||
}
|
||||
}
|
||||
impl DupNode {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the Input Argument
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct IdNode;
|
||||
impl<T> Node<T> for IdNode {
|
||||
type Output = T;
|
||||
fn eval(self, input: T) -> Self::Output {
|
||||
input
|
||||
}
|
||||
}
|
||||
impl<'n, T> Node<T> for &'n IdNode {
|
||||
type Output = T;
|
||||
fn eval(self, input: T) -> Self::Output {
|
||||
input
|
||||
}
|
||||
}
|
||||
impl<T> RefNode<T> for IdNode {
|
||||
type Output = T;
|
||||
fn eval_ref(&self, input: T) -> Self::Output {
|
||||
impl<'i, O: 'i> Node<'i, O> for IdNode {
|
||||
type Output = O;
|
||||
fn eval<'s: 'i>(&'s self, input: O) -> Self::Output {
|
||||
input
|
||||
}
|
||||
}
|
||||
@@ -197,75 +173,60 @@ impl IdNode {
|
||||
|
||||
/// Ascribe the node types
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||
pub struct TypeNode<N, I, O>(pub N, pub PhantomData<(I, O)>);
|
||||
impl<N: Node<I>, I> Node<I> for TypeNode<N, I, N::Output> {
|
||||
type Output = N::Output;
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
pub struct TypeNode<N: for<'a> Node<'a, I>, I, O>(pub N, pub PhantomData<(I, O)>);
|
||||
impl<'i, N, I: 'i, O: 'i> Node<'i, I> for TypeNode<N, I, O>
|
||||
where
|
||||
N: for<'n> Node<'n, I, Output = O>,
|
||||
{
|
||||
type Output = O;
|
||||
fn eval<'s: 'i>(&'s self, input: I) -> Self::Output {
|
||||
self.0.eval(input)
|
||||
}
|
||||
}
|
||||
impl<N: Node<I> + Copy, I> Node<I> for &TypeNode<N, I, N::Output> {
|
||||
type Output = N::Output;
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0.eval(input)
|
||||
}
|
||||
} /*
|
||||
impl<N: RefNode<I>, I> Node<I> for &TypeNode<N, I, N::Output> {
|
||||
type Output = N::Output;
|
||||
fn eval(self, input: I) -> Self::Output {
|
||||
self.0.eval_ref(input)
|
||||
}
|
||||
}*/
|
||||
|
||||
impl<N: Node<I>, I> TypeNode<N, I, N::Output> {
|
||||
impl<'i, N: for<'a> Node<'a, I>, I: 'i> TypeNode<N, I, <N as Node<'i, I>>::Output> {
|
||||
pub fn new(node: N) -> Self {
|
||||
Self(node, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<N: Node<I> + Clone, I> Clone for TypeNode<N, I, N::Output> {
|
||||
impl<'i, N: for<'a> Node<'a, I> + Clone, I: 'i> Clone for TypeNode<N, I, <N as Node<'i, I>>::Output> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone(), self.1)
|
||||
}
|
||||
}
|
||||
impl<N: Node<I> + Copy, I> Copy for TypeNode<N, I, N::Output> {}
|
||||
impl<'i, N: for<'a> Node<'a, I> + Copy, I: 'i> Copy for TypeNode<N, I, <N as Node<'i, I>>::Output> {}
|
||||
|
||||
pub struct MapResultNode<MN, I, E>(pub MN, pub PhantomData<(I, E)>);
|
||||
|
||||
impl<MN: Node<I>, I, E> Node<Result<I, E>> for MapResultNode<MN, I, E> {
|
||||
type Output = Result<MN::Output, E>;
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
input.map(|x| self.0.eval(x))
|
||||
}
|
||||
}
|
||||
impl<'n, MN: Node<I> + Copy, I, E> Node<Result<I, E>> for &'n MapResultNode<MN, I, E> {
|
||||
type Output = Result<MN::Output, E>;
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
input.map(|x| self.0.eval(x))
|
||||
}
|
||||
/// input.map(|x| self.0.eval(x))
|
||||
pub struct MapResultNode<I, E, Mn> {
|
||||
node: Mn,
|
||||
_i: PhantomData<I>,
|
||||
_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<MN, I, E> MapResultNode<MN, I, E> {
|
||||
pub const fn new(mn: MN) -> Self {
|
||||
Self(mn, PhantomData)
|
||||
}
|
||||
#[node_macro::node_fn(MapResultNode<_I, _E>)]
|
||||
fn flat_map<_I, _E, N>(input: Result<_I, _E>, node: &'any_input N) -> Result<<N as Node<'input, _I>>::Output, _E>
|
||||
where
|
||||
N: for<'a> Node<'a, _I>,
|
||||
{
|
||||
input.map(|x| node.eval(x))
|
||||
}
|
||||
pub struct FlatMapResultNode<MN: Node<I>, I, E>(pub MN, pub PhantomData<(I, E)>);
|
||||
|
||||
impl<'n, MN: Node<I, Output = Result<O, E>>, I, O: 'n, E: 'n> Node<Result<I, E>> for FlatMapResultNode<MN, I, E> {
|
||||
type Output = Result<O, E>;
|
||||
fn eval(self, input: Result<I, E>) -> Self::Output {
|
||||
match input.map(|x| self.0.eval(x)) {
|
||||
Ok(Ok(x)) => Ok(x),
|
||||
Ok(Err(e)) => Err(e),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
pub struct FlatMapResultNode<I, O, E, Mn> {
|
||||
node: Mn,
|
||||
_i: PhantomData<I>,
|
||||
_o: PhantomData<O>,
|
||||
_e: PhantomData<E>,
|
||||
}
|
||||
|
||||
impl<MN: Node<I>, I, E> FlatMapResultNode<MN, I, E> {
|
||||
pub const fn new(mn: MN) -> Self {
|
||||
Self(mn, PhantomData)
|
||||
#[node_macro::node_fn(FlatMapResultNode<_I, _O, _E>)]
|
||||
fn flat_map<_I, _O, _E, N>(input: Result<_I, _E>, node: &'any_input N) -> Result<_O, _E>
|
||||
where
|
||||
N: for<'a> Node<'a, _I, Output = Result<_O, _E>>,
|
||||
{
|
||||
match input.map(|x| node.eval(x)) {
|
||||
Ok(Ok(x)) => Ok(x),
|
||||
Ok(Err(e)) => Err(e),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,36 +238,69 @@ mod test {
|
||||
#[test]
|
||||
pub fn dup_node() {
|
||||
let value = ValueNode(4u32);
|
||||
let dup = value.then(DupNode);
|
||||
assert_eq!(dup.eval(()), (4, 4));
|
||||
let dup = ComposeNode::new(value, DupNode::new());
|
||||
assert_eq!(dup.eval(()), (&4, &4));
|
||||
}
|
||||
#[test]
|
||||
pub fn id_node() {
|
||||
let value = ValueNode(4u32).then(IdNode);
|
||||
assert_eq!(value.eval(()), 4);
|
||||
let value = ValueNode(4u32).then(IdNode::new());
|
||||
assert_eq!(value.eval(()), &4);
|
||||
}
|
||||
#[test]
|
||||
pub fn clone_node() {
|
||||
let cloned = (&ValueNode(4u32)).then(CloneNode);
|
||||
let cloned = ValueNode(4u32).then(CloneNode::new());
|
||||
assert_eq!(cloned.eval(()), 4);
|
||||
let type_erased = &CloneNode::new() as &dyn for<'a> Node<'a, &'a u32, Output = u32>;
|
||||
assert_eq!(type_erased.eval(&4), 4);
|
||||
let type_erased = &cloned as &dyn for<'a> Node<'a, (), Output = u32>;
|
||||
assert_eq!(type_erased.eval(()), 4);
|
||||
}
|
||||
#[test]
|
||||
pub fn fst_node() {
|
||||
let fst = ValueNode((4u32, "a")).then(FstNode);
|
||||
let fst = ValueNode((4u32, "a")).then(CloneNode::new()).then(FstNode::new());
|
||||
assert_eq!(fst.eval(()), 4);
|
||||
}
|
||||
#[test]
|
||||
pub fn snd_node() {
|
||||
let fst = ValueNode((4u32, "a")).then(SndNode);
|
||||
let fst = ValueNode((4u32, "a")).then(CloneNode::new()).then(SndNode::new());
|
||||
assert_eq!(fst.eval(()), "a");
|
||||
}
|
||||
#[test]
|
||||
pub fn object_safe() {
|
||||
let fst = ValueNode((4u32, "a")).then(CloneNode::new()).then(SndNode::new());
|
||||
let foo = &fst as &dyn Node<(), Output = &str>;
|
||||
assert_eq!(foo.eval(()), "a");
|
||||
}
|
||||
#[test]
|
||||
pub fn map_result() {
|
||||
let value: ClonedNode<Result<&u32, ()>> = ClonedNode(Ok(&4u32));
|
||||
assert_eq!(value.eval(()), Ok(&4u32));
|
||||
static clone: &CloneNode<u32> = &CloneNode::new();
|
||||
//let type_erased_clone = clone as &dyn for<'a> Node<'a, &'a u32, Output = u32>;
|
||||
let map_result = MapResultNode::new(ValueNode::new(FnNode::new(|x: &u32| x.clone())));
|
||||
//et type_erased = &map_result as &dyn for<'a> Node<'a, Result<&'a u32, ()>, Output = Result<u32, ()>>;
|
||||
assert_eq!(map_result.eval(Ok(&4u32)), Ok(4u32));
|
||||
let fst = value.then(map_result);
|
||||
//let type_erased = &fst as &dyn for<'a> Node<'a, (), Output = Result<u32, ()>>;
|
||||
assert_eq!(fst.eval(()), Ok(4u32));
|
||||
}
|
||||
#[test]
|
||||
pub fn flat_map_result() {
|
||||
let fst = ValueNode(Ok(&4u32)).then(CloneNode::new()); //.then(FlatMapResultNode::new(FnNode::new(|x| Ok(x))));
|
||||
let fn_node: FnNode<_, &u32, Result<&u32, _>> = FnNode::new(|_| Err(8u32));
|
||||
assert_eq!(fn_node.eval(&4u32), Err(8u32));
|
||||
let flat_map = FlatMapResultNode::new(ValueNode::new(fn_node));
|
||||
let fst = fst.then(flat_map);
|
||||
assert_eq!(fst.eval(()), Err(8u32));
|
||||
}
|
||||
#[test]
|
||||
pub fn add_node() {
|
||||
let a = ValueNode(42u32);
|
||||
let b = ValueNode(6u32);
|
||||
let cons_a = ConsNode(a, PhantomData);
|
||||
let cons_a = ConsNode::new(a);
|
||||
let tuple = b.then(cons_a);
|
||||
|
||||
let sum = b.then(cons_a).then(AddNode);
|
||||
let sum = tuple.then(AddNode::new());
|
||||
|
||||
assert_eq!(sum.eval(()), 48);
|
||||
}
|
||||
@@ -321,7 +315,7 @@ mod test {
|
||||
let fnn = FnNode::new(&swap);
|
||||
let fns = FnNodeWithState::new(int, 42u32);
|
||||
assert_eq!(fnn.eval((1u32, 2u32)), (2, 1));
|
||||
let result: u32 = (&fns).eval(());
|
||||
let result: u32 = fns.eval(());
|
||||
assert_eq!(result, 42);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user