mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 03:18:12 +08:00
Add FnNode and FnNodeWithState to node graph
This commit is contained in:
Generated
+12
@@ -367,9 +367,12 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"dashmap 5.2.0",
|
"dashmap 5.2.0",
|
||||||
"graph-proc-macros",
|
"graph-proc-macros",
|
||||||
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"parking_lot 0.11.1",
|
||||||
"ra_ap_ide",
|
"ra_ap_ide",
|
||||||
"ra_ap_ide_db",
|
"ra_ap_ide_db",
|
||||||
|
"storage-map",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1040,6 +1043,15 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "storage-map"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418bb14643aa55a7841d5303f72cf512cfb323b8cc221d51580500a1ca75206c"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.73"
|
version = "1.0.73"
|
||||||
|
|||||||
@@ -14,3 +14,6 @@ ide_db = { version = "*", package = "ra_ap_ide_db" , optional = true }
|
|||||||
graph-proc-macros = {path = "proc-macro"}
|
graph-proc-macros = {path = "proc-macro"}
|
||||||
once_cell = "1.10"
|
once_cell = "1.10"
|
||||||
dashmap = "5.2"
|
dashmap = "5.2"
|
||||||
|
storage-map = "*"
|
||||||
|
lock_api = "*"
|
||||||
|
parking_lot = "*"
|
||||||
|
|||||||
+25
-5
@@ -22,22 +22,42 @@ pub trait AnyRef: Node {
|
|||||||
where
|
where
|
||||||
Self::Input<'a>: 'static + Copy;
|
Self::Input<'a>: 'static + Copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Node> AnyRef for T {
|
impl<T: Node> AnyRef for T {
|
||||||
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
|
fn any<'a>(&'a self, input: &'a dyn Any) -> Self::Output<'a>
|
||||||
where
|
where
|
||||||
Self::Input<'a>: 'static + Copy,
|
Self::Input<'a>: 'static + Copy,
|
||||||
{
|
{
|
||||||
self.eval::<&Self::Input<'a>>(input.downcast_ref::<Self::Input<'a>>().unwrap())
|
self.eval::<&Self::Input<'a>>(input.downcast_ref::<Self::Input<'a>>().unwrap_or_else(
|
||||||
|
|| {
|
||||||
|
panic!(
|
||||||
|
"Node was evaluated with wrong input. The input has to be of type: {}",
|
||||||
|
std::any::type_name::<Self::Input<'a>>(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait After<SECOND: Node> {
|
trait DefaultNode: Default {
|
||||||
fn after<'a, FIRST: Node>(&'a self, first: &'a FIRST) -> ComposeNode<'a, FIRST, SECOND>;
|
fn default_node() -> ValueNode<Self> {
|
||||||
|
ValueNode::new(Self::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
impl<T: std::default::Default> DefaultNode for T {}
|
||||||
|
|
||||||
|
trait After: Sized {
|
||||||
|
fn after<'a, First: Node>(&'a self, first: &'a First) -> ComposeNode<'a, First, Self> {
|
||||||
|
ComposeNode::new(first, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<Second: Node> After for Second {}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let int = IntNode::<32>;
|
let int = IntNode::<32>;
|
||||||
let add: u32 = AddNode::<u32>::default().any(&(int.eval(&()), int.eval(&())) as &dyn Any);
|
let add: u32 = AddNode::<u32>::default().eval((int.eval(&()), int.eval(&())));
|
||||||
|
let fnode = FnNode::new(|(a, b): &(i32, i32)| a - b);
|
||||||
|
let sub = fnode.any(&("a", 2));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let curry: CurryNthArgNode<'_, _, _, u32, u32, 0> = CurryNthArgNode::new(&AddNode, &int);
|
let curry: CurryNthArgNode<'_, _, _, u32, u32, 0> = CurryNthArgNode::new(&AddNode, &int);
|
||||||
@@ -45,5 +65,5 @@ fn main() {
|
|||||||
let n = ValueNode::new(10_u32);
|
let n = ValueNode::new(10_u32);
|
||||||
let curry: CurryNthArgNode<'_, _, _, u32, _, 0> = CurryNthArgNode::new(&composition, &n);
|
let curry: CurryNthArgNode<'_, _, _, u32, _, 0> = CurryNthArgNode::new(&composition, &n);
|
||||||
*/
|
*/
|
||||||
println!("{}", add)
|
println!("{}", sub)
|
||||||
}
|
}
|
||||||
|
|||||||
+126
-65
@@ -1,10 +1,18 @@
|
|||||||
use std::{
|
use std::{
|
||||||
any::Any, borrow::Borrow, collections::hash_map::DefaultHasher, hash::Hasher, iter, iter::Sum,
|
any::Any,
|
||||||
|
borrow::Borrow,
|
||||||
|
cell::RefCell,
|
||||||
|
collections::{hash_map::DefaultHasher, HashMap},
|
||||||
|
hash::{Hash, Hasher},
|
||||||
|
iter,
|
||||||
|
iter::Sum,
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{insert_after_nth, After, Node};
|
use crate::{insert_after_nth, After, Node};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
use parking_lot::RawRwLock;
|
||||||
|
use storage_map::{StorageMap, StorageMapGuard};
|
||||||
|
|
||||||
pub struct IntNode<const N: u32>;
|
pub struct IntNode<const N: u32>;
|
||||||
impl<const N: u32> Node for IntNode<N> {
|
impl<const N: u32> Node for IntNode<N> {
|
||||||
@@ -41,31 +49,6 @@ impl<T: std::ops::Add + 'static + Copy> Node for AddNode<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Caches the output of a given Node and acts as a proxy
|
|
||||||
pub struct CachingNode<'n, 'c, CachedNode: Node + 'c> {
|
|
||||||
node: &'n CachedNode,
|
|
||||||
cache: OnceCell<CachedNode::Output<'c>>,
|
|
||||||
}
|
|
||||||
impl<'n: 'c, 'c, CashedNode: Node> Node for CachingNode<'n, 'c, CashedNode> {
|
|
||||||
type Output<'a> = &'a CashedNode::Output<'c> where 'c: 'a;
|
|
||||||
type Input<'a> = CashedNode::Input<'c> where 'c: 'a;
|
|
||||||
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
|
||||||
self.cache.get_or_init(|| self.node.eval(input))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'n, 'c, CachedNode: Node> CachingNode<'n, 'c, CachedNode> {
|
|
||||||
pub fn clear(&'n mut self) {
|
|
||||||
self.cache = OnceCell::new();
|
|
||||||
}
|
|
||||||
pub fn new(node: &'n CachedNode) -> CachingNode<'n, 'c, CachedNode> {
|
|
||||||
CachingNode {
|
|
||||||
node,
|
|
||||||
cache: OnceCell::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ComposeNode<'n, FIRST, SECOND> {
|
pub struct ComposeNode<'n, FIRST, SECOND> {
|
||||||
first: &'n FIRST,
|
first: &'n FIRST,
|
||||||
second: &'n SECOND,
|
second: &'n SECOND,
|
||||||
@@ -98,11 +81,64 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, SECOND: Node> After<SECOND> for SECOND {
|
pub struct FnNode<T: Fn(&In) -> O, In, O>(T, PhantomData<In>, PhantomData<O>);
|
||||||
fn after<'a, FIRST: Node>(&'a self, first: &'a FIRST) -> ComposeNode<'a, FIRST, SECOND> {
|
impl<T: Fn(&In) -> O, In, O> Node for FnNode<T, In, O> {
|
||||||
ComposeNode::<'a, FIRST, SECOND> {
|
type Output<'a> = O where Self: 'a;
|
||||||
first,
|
type Input<'a> = In where Self: 'a;
|
||||||
second: self,
|
|
||||||
|
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
||||||
|
self.0(input.borrow())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Fn(&In) -> O, In, O> FnNode<T, In, O> {
|
||||||
|
pub fn new(f: T) -> Self {
|
||||||
|
FnNode(f, PhantomData::default(), PhantomData::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FnNodeWithState<T: Fn(&In, &State) -> O, In, O, State>(
|
||||||
|
T,
|
||||||
|
State,
|
||||||
|
PhantomData<In>,
|
||||||
|
PhantomData<O>,
|
||||||
|
);
|
||||||
|
impl<T: Fn(&In, &State) -> O, In, O, State> Node for FnNodeWithState<T, In, O, State> {
|
||||||
|
type Output<'a> = O where Self: 'a;
|
||||||
|
type Input<'a> = In where Self: 'a;
|
||||||
|
|
||||||
|
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
||||||
|
self.0(input.borrow(), &self.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Fn(&In, &State) -> O, In, O, State> FnNodeWithState<T, In, O, State> {
|
||||||
|
pub fn new(f: T, state: State) -> Self {
|
||||||
|
FnNodeWithState(f, state, PhantomData::default(), PhantomData::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Caches the output of a given Node and acts as a proxy
|
||||||
|
pub struct CacheNode<'n, 'c, CachedNode: Node + 'c> {
|
||||||
|
node: &'n CachedNode,
|
||||||
|
cache: OnceCell<CachedNode::Output<'c>>,
|
||||||
|
}
|
||||||
|
impl<'n: 'c, 'c, CashedNode: Node> Node for CacheNode<'n, 'c, CashedNode> {
|
||||||
|
type Output<'a> = &'a CashedNode::Output<'c> where 'c: 'a;
|
||||||
|
type Input<'a> = CashedNode::Input<'c> where 'c: 'a;
|
||||||
|
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
||||||
|
self.cache.get_or_init(|| self.node.eval(input))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'n, 'c, CachedNode: Node> CacheNode<'n, 'c, CachedNode> {
|
||||||
|
pub fn clear(&'n mut self) {
|
||||||
|
self.cache = OnceCell::new();
|
||||||
|
}
|
||||||
|
pub fn new(node: &'n CachedNode) -> CacheNode<'n, 'c, CachedNode> {
|
||||||
|
CacheNode {
|
||||||
|
node,
|
||||||
|
cache: OnceCell::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,52 +146,77 @@ impl<'n, SECOND: Node> After<SECOND> for SECOND {
|
|||||||
/*
|
/*
|
||||||
/// Caches the output of a given Node and acts as a proxy
|
/// Caches the output of a given Node and acts as a proxy
|
||||||
/// Automatically resets if it receives different input
|
/// Automatically resets if it receives different input
|
||||||
pub struct SmartCacheNode<'n, NODE: Node<'n, OUT>, OUT: Clone> {
|
struct SmartCacheNode<'n, 'c, NODE: Node + 'c>
|
||||||
node: &'n NODE,
|
where
|
||||||
map: dashmap::DashMap<u64, CacheNode<'n, NODE, OUT>>,
|
for<'a> NODE::Input<'a>: Hash,
|
||||||
}
|
|
||||||
impl<'n, NODE: for<'a> Node<'a, OUT>, OUT: Clone> Node<'n, &'n CacheNode<'n, NODE, OUT>>
|
|
||||||
for SmartCacheNode<'n, NODE, OUT>
|
|
||||||
{
|
{
|
||||||
fn eval(
|
cache: InnerSmartCacheNode<'n, 'c, NODE>,
|
||||||
&'n self,
|
}
|
||||||
input: impl Iterator<Item = &'n dyn Any> + Clone,
|
impl<'n: 'c, 'c, NODE: Node> Node for SmartCacheNode<'n, 'c, NODE>
|
||||||
) -> &'n CacheNode<'n, NODE, OUT> {
|
where
|
||||||
|
for<'a> NODE::Input<'a>: Hash,
|
||||||
|
{
|
||||||
|
type Input<'a> = NODE::Input<'a> where Self: 'a, 'c : 'a;
|
||||||
|
type Output<'a> = &'a NODE::Output<'a> where Self: 'a, 'c: 'a;
|
||||||
|
fn eval<'a, I: Borrow<Self::Input<'a>>>(&'a self, input: I) -> Self::Output<'a> {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
input.clone().for_each(|value| unsafe {
|
input.borrow().hash(&mut hasher);
|
||||||
hasher.write(std::slice::from_raw_parts(
|
|
||||||
value as *const dyn Any as *const u8,
|
|
||||||
std::mem::size_of_val(value),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
let hash = hasher.finish();
|
let hash = hasher.finish();
|
||||||
self.map.entry(hash).or_insert(CacheNode::new(self.node));
|
|
||||||
fn map<'a, 'c, 'd, N, OUT: Clone>(
|
let node = self.cache.eval(input);
|
||||||
_key: &'a u64,
|
node.eval(input);
|
||||||
node: &'c CacheNode<'d, N, OUT>,
|
todo!()
|
||||||
) -> &'c CacheNode<'b, N, OUT>
|
|
||||||
where
|
|
||||||
N: for<'b> Node<'b, OUT>,
|
|
||||||
{
|
|
||||||
node
|
|
||||||
}
|
|
||||||
let foo: Option<&CacheNode<'n, NODE, OUT>> = self.map.view(&hash, map);
|
|
||||||
foo.unwrap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'n, NODE: Node<'n, OUT>, OUT: Clone> SmartCacheNode<'n, NODE, OUT> {
|
impl<'n, 'c, NODE: Node> SmartCacheNode<'n, 'c, NODE>
|
||||||
fn clear(&'n mut self) {
|
where
|
||||||
self.map.clear();
|
for<'a> NODE::Input<'a>: Hash,
|
||||||
|
{
|
||||||
|
pub fn clear(&'n mut self) {
|
||||||
|
self.cache.clear();
|
||||||
}
|
}
|
||||||
fn new(node: &'n NODE) -> SmartCacheNode<'n, NODE, OUT> {
|
pub fn new(node: &'n NODE) -> SmartCacheNode<'n, 'c, NODE> {
|
||||||
SmartCacheNode {
|
SmartCacheNode {
|
||||||
node,
|
cache: InnerSmartCacheNode::new(node),
|
||||||
map: dashmap::DashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/// 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<RawRwLock, HashMap<u64, CacheNode<'n, 'c, NODE>>>,
|
||||||
|
}
|
||||||
|
impl<'n: 'c, 'c, NODE: Node + 'c> Node for SmartCacheNode<'n, 'c, NODE>
|
||||||
|
where
|
||||||
|
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<Self::Input<'a>>>(&'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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 struct CurryNthArgNode<
|
pub struct CurryNthArgNode<
|
||||||
|
|||||||
Reference in New Issue
Block a user