WIP: derive macro
This commit is contained in:
1 parent
a8566b4e71
commit
bab3c8d584
3 files changed
+138
-42
No files matched your search
@@ -4,7 +4,7 @@ use std::collections::HashSet;
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::Type;
|
use syn::{ItemImpl, Type};
|
||||||
|
|
||||||
/// A helper attribute for deriving `State` for a struct.
|
/// A helper attribute for deriving `State` for a struct.
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
@@ -58,36 +58,125 @@ pub fn partial_derive_pass(_: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
let mut combined_dependencies = HashSet::new();
|
let mut combined_dependencies = HashSet::new();
|
||||||
|
|
||||||
match parent_dependencies {
|
let parent_dependencies = match parent_dependencies {
|
||||||
Type::Tuple(tuple) => {
|
Type::Tuple(tuple) => {
|
||||||
|
let mut parent_dependencies = Vec::new();
|
||||||
for type_ in &tuple.elems {
|
for type_ in &tuple.elems {
|
||||||
combined_dependencies.insert(type_.clone());
|
combined_dependencies.insert(type_.clone());
|
||||||
|
parent_dependencies.push(type_.clone());
|
||||||
}
|
}
|
||||||
|
parent_dependencies
|
||||||
}
|
}
|
||||||
_ => panic!("ParentDependencies must be a tuple"),
|
_ => panic!("ParentDependencies must be a tuple"),
|
||||||
}
|
};
|
||||||
match child_dependencies {
|
let child_dependencies = match child_dependencies {
|
||||||
Type::Tuple(tuple) => {
|
Type::Tuple(tuple) => {
|
||||||
|
let mut child_dependencies = Vec::new();
|
||||||
for type_ in &tuple.elems {
|
for type_ in &tuple.elems {
|
||||||
combined_dependencies.insert(type_.clone());
|
combined_dependencies.insert(type_.clone());
|
||||||
|
child_dependencies.push(type_.clone());
|
||||||
}
|
}
|
||||||
|
child_dependencies
|
||||||
}
|
}
|
||||||
_ => panic!("ChildDependencies must be a tuple"),
|
_ => panic!("ChildDependencies must be a tuple"),
|
||||||
}
|
};
|
||||||
match node_dependencies {
|
let node_dependencies = match node_dependencies {
|
||||||
Type::Tuple(tuple) => {
|
Type::Tuple(tuple) => {
|
||||||
|
let mut node_dependencies = Vec::new();
|
||||||
for type_ in &tuple.elems {
|
for type_ in &tuple.elems {
|
||||||
combined_dependencies.insert(type_.clone());
|
combined_dependencies.insert(type_.clone());
|
||||||
|
node_dependencies.push(type_.clone());
|
||||||
}
|
}
|
||||||
|
node_dependencies
|
||||||
}
|
}
|
||||||
_ => panic!("NodeDependencies must be a tuple"),
|
_ => panic!("NodeDependencies must be a tuple"),
|
||||||
}
|
};
|
||||||
combined_dependencies.insert(*this_type.clone());
|
combined_dependencies.insert(*this_type.clone());
|
||||||
|
|
||||||
let combined_dependencies = combined_dependencies.into_iter();
|
let combined_dependencies: Vec<_> = combined_dependencies.into_iter().collect();
|
||||||
|
let parent_dependancies_idxes: Vec<_> = combined_dependencies
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, ident)| parent_dependencies.contains(ident).then_some(i))
|
||||||
|
.collect();
|
||||||
|
let child_dependencies_idxes: Vec<_> = combined_dependencies
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, ident)| child_dependencies.contains(ident).then_some(i))
|
||||||
|
.collect();
|
||||||
|
let node_dependencies_idxes: Vec<_> = combined_dependencies
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(i, ident)| node_dependencies.contains(ident).then_some(i))
|
||||||
|
.collect();
|
||||||
|
let this_type_idx = node_dependencies
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find_map(|(i, ident)| (&**this_type == ident).then_some(i))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let combined_dependencies = combined_dependencies.iter().map(|ident| {
|
||||||
|
if ident == &**this_type {
|
||||||
|
quote! {shipyard::ViewMut<#ident>}
|
||||||
|
} else {
|
||||||
|
quote! {shipyard::View<#ident>}
|
||||||
|
}
|
||||||
|
});
|
||||||
let combined_dependencies = quote!((#(#combined_dependencies),*));
|
let combined_dependencies = quote!((#(#combined_dependencies),*));
|
||||||
|
|
||||||
quote!(#impl_block).into()
|
let ItemImpl {
|
||||||
|
attrs,
|
||||||
|
defaultness,
|
||||||
|
unsafety,
|
||||||
|
impl_token,
|
||||||
|
generics,
|
||||||
|
trait_,
|
||||||
|
self_ty,
|
||||||
|
items,
|
||||||
|
..
|
||||||
|
} = impl_block;
|
||||||
|
let for_ = trait_.as_ref().map(|t| t.2);
|
||||||
|
let trait_ = trait_.map(|t| t.1);
|
||||||
|
|
||||||
|
// if the mutable borrow on the current type overlaps with the child or parent dependancies we need to use apply
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
#(#attrs)*
|
||||||
|
#defaultness #unsafety #impl_token #impl_token #generics #trait_ #for_ #self_ty {
|
||||||
|
#(#items)*
|
||||||
|
|
||||||
|
fn workload_system(type_id: TypeId, dependants: FxHashSet<TypeId>, pass_direction: PassDirection) -> WorkloadSystem {
|
||||||
|
use shipyard::IntoWorkloadSystem;
|
||||||
|
|
||||||
|
move |data: #combined_dependencies, run_view: RunPassView| {
|
||||||
|
shipyard::run(type_id, dependants, pass_direction, run_view, |id: NodeId, ctx: &SendAnyMap| {
|
||||||
|
// get all of the states from the tree view
|
||||||
|
// Safety: No node has itself as a parent or child.
|
||||||
|
let myself: SlabEntry<'static, Self> = unsafe {
|
||||||
|
std::mem::transmute(tree.get_slab_mut::<Self>().unwrap().entry(node_id))
|
||||||
|
};
|
||||||
|
let node_data = tree.get_single::<NodeType<V>>(node_id).unwrap();
|
||||||
|
let node = tree.get::<Self::NodeDependencies>(node_id).unwrap();
|
||||||
|
let children = tree.children::<Self::ChildDependencies>(node_id);
|
||||||
|
let parent = tree.parent::<Self::ParentDependencies>(node_id);
|
||||||
|
|
||||||
|
let view = NodeView::new(node_id, node_data, &node_mask);
|
||||||
|
if myself.value.is_none() {
|
||||||
|
*myself.value = Some(Self::create(view, node, parent, children, context));
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
myself
|
||||||
|
.value
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.update(view, node, parent, children, context)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}.into_workload_system()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
// pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ mod passes;
|
|||||||
pub mod real_dom;
|
pub mod real_dom;
|
||||||
pub mod tree;
|
pub mod tree;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
pub use passes::run_pass;
|
||||||
pub use shipyard::EntityId as NodeId;
|
pub use shipyard::EntityId as NodeId;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
use anymap::AnyMap;
|
use anymap::AnyMap;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use shipyard::{
|
use shipyard::{BorrowInfo, Component, IntoBorrow, Unique, UniqueView, View, WorkloadSystem};
|
||||||
BorrowInfo, Component, IntoBorrow, IntoWorkloadSystem, Unique, UniqueView, View,
|
|
||||||
WorkloadSystem, World,
|
|
||||||
};
|
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@@ -13,8 +10,8 @@ use std::sync::Arc;
|
|||||||
use crate::node::FromAnyValue;
|
use crate::node::FromAnyValue;
|
||||||
use crate::node_ref::{NodeMaskBuilder, NodeView};
|
use crate::node_ref::{NodeMaskBuilder, NodeView};
|
||||||
use crate::real_dom::{DirtyNodesResult, SendAnyMapWrapper};
|
use crate::real_dom::{DirtyNodesResult, SendAnyMapWrapper};
|
||||||
use crate::tree::{TreeMut, TreeRef, TreeRefView};
|
use crate::tree::{TreeRef, TreeRefView};
|
||||||
use crate::{FxDashSet, SendAnyMap};
|
use crate::SendAnyMap;
|
||||||
use crate::{NodeId, NodeMask};
|
use crate::{NodeId, NodeMask};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
@@ -113,8 +110,6 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
|||||||
type ChildDependencies: Dependancy;
|
type ChildDependencies: Dependancy;
|
||||||
/// This is a tuple of (T: Pass, ..) of states read from the node required to run this pass
|
/// This is a tuple of (T: Pass, ..) of states read from the node required to run this pass
|
||||||
type NodeDependencies: Dependancy;
|
type NodeDependencies: Dependancy;
|
||||||
/// A tuple of all the dependencies combined
|
|
||||||
type CombinedDependencies: Dependancy;
|
|
||||||
/// This is a mask of what aspects of the node are required to run this pass
|
/// This is a mask of what aspects of the node are required to run this pass
|
||||||
const NODE_MASK: NodeMaskBuilder<'static>;
|
const NODE_MASK: NodeMaskBuilder<'static>;
|
||||||
|
|
||||||
@@ -138,43 +133,54 @@ pub trait State<V: FromAnyValue + Send + Sync = ()>: Any + Send + Sync {
|
|||||||
) -> Self;
|
) -> Self;
|
||||||
|
|
||||||
/// Create a workload system for this state
|
/// Create a workload system for this state
|
||||||
fn workload_system(dependants: FxHashSet<TypeId>) -> WorkloadSystem;
|
fn workload_system(
|
||||||
|
type_id: TypeId,
|
||||||
|
dependants: FxHashSet<TypeId>,
|
||||||
|
pass_direction: PassDirection,
|
||||||
|
) -> WorkloadSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RunPassView<'a> {
|
pub struct RunPassView<'a> {
|
||||||
type_id: TypeId,
|
|
||||||
dependants: FxHashSet<TypeId>,
|
|
||||||
pass_direction: PassDirection,
|
|
||||||
tree: TreeRefView<'a>,
|
tree: TreeRefView<'a>,
|
||||||
nodes_updated: UniqueView<'a, DirtyNodesResult>,
|
nodes_updated: UniqueView<'a, DirtyNodesResult>,
|
||||||
dirty: UniqueView<'a, DirtyNodeStates>,
|
dirty: UniqueView<'a, DirtyNodeStates>,
|
||||||
ctx: UniqueView<'a, SendAnyMapWrapper>,
|
ctx: UniqueView<'a, SendAnyMapWrapper>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> RunPassView<'a> {
|
impl<'v> shipyard::Borrow<'v> for RunPassView<'v> {
|
||||||
pub fn borrow(
|
type View = RunPassView<'v>;
|
||||||
type_id: TypeId,
|
|
||||||
dependants: FxHashSet<TypeId>,
|
fn borrow(
|
||||||
pass_direction: PassDirection,
|
world: &'v shipyard::World,
|
||||||
world: &'a World,
|
last_run: Option<u32>,
|
||||||
) -> Self {
|
current: u32,
|
||||||
Self {
|
) -> Result<Self::View, shipyard::error::GetStorage> {
|
||||||
type_id,
|
Ok(RunPassView {
|
||||||
dependants,
|
tree: <TreeRefView<'v> as shipyard::IntoBorrow>::Borrow::borrow(
|
||||||
pass_direction,
|
world, last_run, current,
|
||||||
tree: world.borrow().unwrap(),
|
)?,
|
||||||
nodes_updated: world.borrow().unwrap(),
|
nodes_updated:
|
||||||
dirty: world.borrow().unwrap(),
|
<UniqueView<'v, DirtyNodesResult> as shipyard::IntoBorrow>::Borrow::borrow(
|
||||||
ctx: world.borrow().unwrap(),
|
world, last_run, current,
|
||||||
}
|
)?,
|
||||||
|
dirty: <UniqueView<'v, DirtyNodeStates> as shipyard::IntoBorrow>::Borrow::borrow(
|
||||||
|
world, last_run, current,
|
||||||
|
)?,
|
||||||
|
ctx: <UniqueView<'v, SendAnyMapWrapper> as shipyard::IntoBorrow>::Borrow::borrow(
|
||||||
|
world, last_run, current,
|
||||||
|
)?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_pass(view: RunPassView, mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool) {
|
pub fn run_pass(
|
||||||
|
type_id: TypeId,
|
||||||
|
dependants: FxHashSet<TypeId>,
|
||||||
|
pass_direction: PassDirection,
|
||||||
|
view: RunPassView,
|
||||||
|
mut update_node: impl FnMut(NodeId, &SendAnyMap) -> bool,
|
||||||
|
) {
|
||||||
let RunPassView {
|
let RunPassView {
|
||||||
type_id,
|
|
||||||
dependants,
|
|
||||||
pass_direction,
|
|
||||||
tree,
|
tree,
|
||||||
nodes_updated,
|
nodes_updated,
|
||||||
dirty,
|
dirty,
|
||||||
@@ -284,7 +290,7 @@ pub struct TypeErasedPass<V: FromAnyValue + Send = ()> {
|
|||||||
pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
|
pub(crate) combined_dependancy_type_ids: FxHashSet<TypeId>,
|
||||||
pub(crate) dependants: FxHashSet<TypeId>,
|
pub(crate) dependants: FxHashSet<TypeId>,
|
||||||
pub(crate) mask: NodeMask,
|
pub(crate) mask: NodeMask,
|
||||||
pub(crate) workload: fn(FxHashSet<TypeId>) -> WorkloadSystem,
|
pub(crate) workload: fn(TypeId, FxHashSet<TypeId>, PassDirection) -> WorkloadSystem,
|
||||||
pub(crate) pass_direction: PassDirection,
|
pub(crate) pass_direction: PassDirection,
|
||||||
phantom: PhantomData<V>,
|
phantom: PhantomData<V>,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user