nested state

This commit is contained in:
Evan Almloff committed 2022-04-19 20:12:57 -05:00
1 parent f4689a4e27
commit 7c30d93a3d
5 files changed
+270 -30

No files matched your search

+137 -15
View File
@@ -4,6 +4,7 @@ mod sorted_slice;
use dioxus_native_core::state::MemberId;
use proc_macro::TokenStream;
use quote::format_ident;
use quote::{quote, ToTokens, __private::Span};
use sorted_slice::StrSlice;
use syn::{
@@ -26,7 +27,10 @@ enum DepKind {
Parent,
}
#[proc_macro_derive(State, attributes(node_dep_state, child_dep_state, parent_dep_state))]
#[proc_macro_derive(
State,
attributes(node_dep_state, child_dep_state, parent_dep_state, state)
)]
pub fn state_macro_derive(input: TokenStream) -> TokenStream {
let ast = syn::parse(input).unwrap();
impl_derive_macro(&ast)
@@ -89,8 +93,51 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
let type_name_str = type_name.to_string();
let child_states = &state_strct.child_states;
let member_size = state_strct.state_members.len();
let child_state_ty = child_states.iter().map(|m| &m.ty);
let child_state_idents: Vec<_> = child_states.iter().map(|m| &m.ident).collect();
let sum_const_declarations = child_state_ty.clone().enumerate().map(|(i, ty)| {
let ident = format_ident!("__{}_SUM_{}", i, type_name.to_string());
let ident_minus = format_ident!("__{}_SUM_{}_minus", i, type_name.to_string());
if i == 0 {
quote!(const #ident_minus: usize = #member_size + #ty::SIZE - 1;
const #ident: usize = #member_size + #ty::SIZE;)
} else {
let prev_ident = format_ident!("__{}_SUM_{}", i - 1, type_name.to_string());
quote!(const #ident_minus: usize = #prev_ident + #ty::SIZE - 1;
const #ident: usize = #prev_ident + #ty::SIZE;)
}
});
let sum_idents: Vec<_> = std::iter::once(quote!(#member_size))
.chain((0..child_states.len()).map(|i| {
let ident = format_ident!("__{}_SUM_{}", i, type_name.to_string());
quote!(#ident)
}))
.collect();
let child_state_ranges: Vec<_> = (0..child_state_ty.len())
.map(|i| {
let current = format_ident!("__{}_SUM_{}_minus", i, type_name.to_string());
let previous = if i == 0 {
quote!(#member_size)
} else {
let ident = format_ident!("__{}_SUM_{}", i - 1, type_name.to_string());
quote!(#ident)
};
quote!(#previous..=#current)
})
.collect();
let gen = quote! {
#(
#sum_const_declarations
)*
impl State for #type_name{
const SIZE: usize = #member_size #( + #child_state_ty::SIZE)*;
fn update_node_dep_state<'a>(
&'a mut self,
ty: dioxus_native_core::state::MemberId,
@@ -99,10 +146,26 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
ctx: &anymap::AnyMap,
) -> Option<dioxus_native_core::state::NodeStatesChanged>{
use dioxus_native_core::state::NodeDepState as _;
use dioxus_native_core::state::State as _;
match ty.0{
#(
#node_ids => #node_dep_state_fields,
)*
#(
#child_state_ranges => {
self.#child_state_idents.update_node_dep_state(
ty - #sum_idents,
node,
vdom,
ctx,
).map(|mut changed|{
for id in &mut changed.node_dep{
*id += #sum_idents;
}
changed
})
}
)*
_ => panic!("{:?} not in {}", ty, #type_name_str),
}
}
@@ -120,6 +183,25 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
#(
#parent_ids => #parent_dep_state_fields,
)*
#(
#child_state_ranges => {
self.#child_state_idents.update_parent_dep_state(
ty - #sum_idents,
node,
vdom,
parent.map(|p| &p.#child_state_idents),
ctx,
).map(|mut changed|{
for id in &mut changed.node_dep{
*id += #sum_idents;
}
for id in &mut changed.parent_dep{
*id += #sum_idents;
}
changed
})
}
)*
_ => panic!("{:?} not in {}", ty, #type_name_str),
}
}
@@ -129,13 +211,32 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
ty: dioxus_native_core::state::MemberId,
node: &'a dioxus_core::VNode<'a>,
vdom: &'a dioxus_core::VirtualDom,
children: &[&Self],
children: &Vec<&Self>,
ctx: &anymap::AnyMap,
) -> Option<dioxus_native_core::state::ChildStatesChanged>{
use dioxus_native_core::state::ChildDepState as _;
match ty.0{
#(
#child_ids => {#child_dep_state_fields},
#child_ids => #child_dep_state_fields,
)*
#(
#child_state_ranges => {
self.#child_state_idents.update_child_dep_state(
ty - #sum_idents,
node,
vdom,
&children.iter().map(|p| &p.#child_state_idents).collect(),
ctx,
).map(|mut changed|{
for id in &mut changed.node_dep{
*id += #sum_idents;
}
for id in &mut changed.child_dep{
*id += #sum_idents;
}
changed
})
}
)*
_ => panic!("{:?} not in {}", ty, #type_name_str),
}
@@ -146,6 +247,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
#(if #child_types::NODE_MASK.overlaps(mask) {
dep_types.push(dioxus_native_core::state::MemberId(#child_ids_clone));
})*
#(
dep_types.extend(self.#child_state_idents.child_dep_types(mask).into_iter().map(|id| id + #sum_idents));
)*
dep_types
}
@@ -154,6 +258,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
#(if #parent_types::NODE_MASK.overlaps(mask) {
dep_types.push(dioxus_native_core::state::MemberId(#parent_ids_clone));
})*
#(
dep_types.extend(self.#child_state_idents.parent_dep_types(mask).into_iter().map(|id| id + #sum_idents));
)*
dep_types
}
@@ -162,6 +269,9 @@ fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream {
#(if #node_types::NODE_MASK.overlaps(mask) {
dep_types.push(dioxus_native_core::state::MemberId(#node_ids_clone));
})*
#(
dep_types.extend(self.#child_state_idents.node_dep_types(mask).into_iter().map(|id| id + #sum_idents));
)*
dep_types
}
}
@@ -186,6 +296,7 @@ impl Struct {
struct StateStruct<'a> {
state_members: Vec<StateMember<'a>>,
child_states: Vec<&'a Member>,
}
impl<'a> StateStruct<'a> {
@@ -203,6 +314,20 @@ impl<'a> StateStruct<'a> {
}
});
let child_states = strct
.members
.iter()
.zip(fields.iter())
.filter(|(_, f)| {
f.attrs.iter().any(|a| {
a.path
.get_ident()
.filter(|i| i.to_string().as_str() == "state")
.is_some()
})
})
.map(|(m, _)| m);
#[derive(Debug, Clone)]
struct DepNode<'a> {
state_mem: StateMember<'a>,
@@ -350,7 +475,10 @@ impl<'a> StateStruct<'a> {
.flat_map(|r| r.flatten().into_iter())
.collect();
Ok(Self { state_members })
Ok(Self {
state_members,
child_states: child_states.collect(),
})
}
}
}
@@ -484,23 +612,23 @@ impl<'a> StateMember<'a> {
DepKind::Node => {
quote! {
dioxus_native_core::state::NodeStatesChanged{
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
}
}
}
DepKind::Child => {
quote! {
dioxus_native_core::state::ChildStatesChanged{
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
child_dep: &[#(dioxus_native_core::state::MemberId(#child_dep), )*],
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
child_dep: vec![#(dioxus_native_core::state::MemberId(#child_dep), )*],
}
}
}
DepKind::Parent => {
quote! {
dioxus_native_core::state::ParentStatesChanged{
node_dep: &[#(dioxus_native_core::state::MemberId(#node_dep), )*],
parent_dep: &[#(dioxus_native_core::state::MemberId(#parent_dep), )*],
node_dep: vec![#(dioxus_native_core::state::MemberId(#node_dep), )*],
parent_dep: vec![#(dioxus_native_core::state::MemberId(#parent_dep), )*],
}
}
}
@@ -515,7 +643,6 @@ impl<'a> StateMember<'a> {
match self.dep_kind {
DepKind::Node => {
quote!({
// println!("node: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, &self.#dep_ident, #get_ctx){
Some(#states_changed)
} else{
@@ -525,7 +652,6 @@ impl<'a> StateMember<'a> {
}
DepKind::Child => {
quote!({
// println!("child: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, children.iter().map(|s| &s.#dep_ident), #get_ctx){
Some(#states_changed)
} else{
@@ -535,7 +661,6 @@ impl<'a> StateMember<'a> {
}
DepKind::Parent => {
quote!({
// println!("parent: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, parent.as_ref().map(|p| &p.#dep_ident), #get_ctx){
Some(#states_changed)
} else{
@@ -548,7 +673,6 @@ impl<'a> StateMember<'a> {
match self.dep_kind {
DepKind::Node => {
quote!({
// println!("node: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, &(), #get_ctx){
Some(#states_changed)
} else{
@@ -558,7 +682,6 @@ impl<'a> StateMember<'a> {
}
DepKind::Child => {
quote!({
// println!("child: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, std::iter::empty(), #get_ctx){
Some(#states_changed)
} else{
@@ -568,7 +691,6 @@ impl<'a> StateMember<'a> {
}
DepKind::Parent => {
quote!({
println!("parent: {:?} {:?} {:?}", self.#ident, #id, #node_view.id());
if self.#ident.reduce(#node_view, Some(&()), #get_ctx){
Some(#states_changed)
} else{