Device macro to generate stateful and publish variants of device specific poll inputs.

This commit is contained in:
Zachary Sunforge
2023-06-20 16:59:28 -07:00
parent ec37a343f6
commit 8557ed19fd
3 changed files with 29 additions and 47 deletions

View File

@ -92,7 +92,7 @@ features = ["defmt", "unstable-traits", "nightly"]
# Macros # Macros
[workspace.dependencies.syn] [workspace.dependencies.syn]
version = "2.0.*" version = "2.0.*"
features = ["extra-traits"] features = ["extra-traits", "parsing"]
[workspace.dependencies.quote] [workspace.dependencies.quote]
version = "1.0.*" version = "1.0.*"
[workspace.dependencies.trybuild] [workspace.dependencies.trybuild]

View File

@ -22,4 +22,7 @@ workspace = true
[dev-dependencies.trybuild] [dev-dependencies.trybuild]
workspace = true workspace = true
[dev-dependencies.physical-node] [dev-dependencies.physical-node]
path = "../../node" path = "../../node"
features = ["embassy-sync"]
[dev-dependencies.embassy-sync]
workspace = true

View File

@ -5,8 +5,8 @@ use syn::__private::Span;
use syn::punctuated::Punctuated; use syn::punctuated::Punctuated;
use syn::token::{Colon, PathSep, Plus}; use syn::token::{Colon, PathSep, Plus};
use syn::{ use syn::{
parse_macro_input, Data, DeriveInput, Expr, GenericParam, Ident, Lit, Meta, Path, PathSegment, parse_macro_input, parse_quote, Data, DeriveInput, Expr, GenericParam, Ident, Lit, Meta, Path,
Token, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, PathSegment, Token, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
}; };
// Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub // Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub
@ -60,9 +60,14 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
panic!("Need attribute {VALUE_T_NAME}: #[{VALUE_T_NAME} = \"type\"]") panic!("Need attribute {VALUE_T_NAME}: #[{VALUE_T_NAME} = \"type\"]")
}; };
// ----- Build publisher generics ---------------------------------- // ----- Add publisher generics ----------------------------------
// Check if generics contains T // MutexT
const MUTEX_T_IDENT_STR: &str = "MutexT"; const MUTEX_T_NAME: &str = "MutexT";
let mutex_t_ident = Ident::new(MUTEX_T_NAME, Span::call_site());
const CAPACITY_NAME: &str = "CAPACITY";
let capacity_ident = Ident::new(CAPACITY_NAME, Span::call_site());
const NUM_SUBS_NAME: &str = "NUM_SUBS";
let num_subs_ident = Ident::new(NUM_SUBS_NAME, Span::call_site());
let mut num_lifetimes: usize = 0; let mut num_lifetimes: usize = 0;
let mut num_types: usize = 0; let mut num_types: usize = 0;
let mut num_const: usize = 0; let mut num_const: usize = 0;
@ -73,8 +78,8 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
GenericParam::Type(param) => { GenericParam::Type(param) => {
num_types += 1; num_types += 1;
// If the generic parameter is T // If the generic parameter is MutexT
if param.ident == MUTEX_T_IDENT_STR { if param.ident == MUTEX_T_NAME {
has_mutex_t = true; has_mutex_t = true;
} }
}, },
@ -85,35 +90,8 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
let mut publish_generics = og_generics.clone(); let mut publish_generics = og_generics.clone();
// If MutexT is not a generic parameter, add it // If MutexT is not a generic parameter, add it
if !has_mutex_t { if !has_mutex_t {
let mutex_t_ident = Ident::new(MUTEX_T_IDENT_STR, Span::call_site()); let mutex_t_param: GenericParam =
let mut mutex_t_bounds: Punctuated<TypeParamBound, Plus> = Punctuated::new(); parse_quote!(#mutex_t_ident: embassy_sync::blocking_mutex::raw::RawMutex);
let mut path: Punctuated<PathSegment, PathSep> = Punctuated::new();
path.push(Ident::new("embassy_sync", Span::call_site()).into());
path.push(Ident::new("blocking_mutex", Span::call_site()).into());
path.push(Ident::new("raw", Span::call_site()).into());
path.push(Ident::new("RawMutex", Span::call_site()).into());
let raw_mutex_path = Path {
leading_colon: None,
segments: path,
};
let mutex_t_bound = TraitBound {
paren_token: None,
modifier: TraitBoundModifier::None,
lifetimes: None,
path: raw_mutex_path,
};
mutex_t_bounds.push(mutex_t_bound.into());
let mutex_t_param: TypeParam = TypeParam {
attrs: Vec::new(),
ident: mutex_t_ident,
colon_token: Some(Colon::default()),
bounds: mutex_t_bounds,
eq_token: None,
default: None,
};
let num_generics = num_lifetimes + num_types + num_const; let num_generics = num_lifetimes + num_types + num_const;
// If there are generics // If there are generics
@ -121,28 +99,29 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
// If all generics are lifetimes // If all generics are lifetimes
if num_lifetimes == num_generics { if num_lifetimes == num_generics {
// Add MutexT after the lifetimes // Add MutexT after the lifetimes
publish_generics.params.push(mutex_t_param.into()); publish_generics.params.push(mutex_t_param);
// If no generics are lifetimes // If no generics are lifetimes
} else if num_lifetimes == 0 { } else if num_lifetimes == 0 {
// Insert MutexT at the front // Insert MutexT at the front
publish_generics publish_generics.params.insert(0, mutex_t_param);
.params
.insert(0, mutex_t_param.into());
// If there are lifetimes and other generics // If there are lifetimes and other generics
} else { } else {
// Insert MutexT after the lifetimes // Insert MutexT after the lifetimes
publish_generics publish_generics
.params .params
.insert(num_lifetimes, mutex_t_param.into()); .insert(num_lifetimes, mutex_t_param);
} }
// If there are no generics // If there are no generics
} else { } else {
// Add MutexT // Add MutexT
publish_generics.params.push(mutex_t_param.into()); publish_generics.params.push(mutex_t_param);
} }
} }
// const generics // const generics
let capacity_param: GenericParam = parse_quote!(const #capacity_ident: usize);
let num_subs_param: GenericParam = parse_quote!(const #num_subs_ident: usize);
publish_generics.params.push(capacity_param);
publish_generics.params.push(num_subs_param);
let (publ_impl_generics, publ_type_generics, publ_where_clause) = let (publ_impl_generics, publ_type_generics, publ_where_clause) =
&publish_generics.split_for_impl(); &publish_generics.split_for_impl();
@ -185,10 +164,10 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
} }
// ----- Publish struct ---------------------------------- // ----- Publish struct ----------------------------------
#[cfg(feature = "embassy-sync")] //#[cfg(feature = "embassy-sync")]
#vis struct #publish_ident #publish_generics #publ_where_clause { #vis struct #publish_ident #publish_generics #publ_where_clause {
pub poll: #ident #og_type_generics, pub poll: #ident #og_type_generics,
pub publisher: physical_node::transducer::Publisher<#value_type_ident, MutexT, CAPACITY, NUM_SUBS>, pub publisher: physical_node::transducer::Publisher<#value_type_ident, #mutex_t_ident, #capacity_ident, #num_subs_ident>,
} }
// ----- Publish impl ---------------------------------- // ----- Publish impl ----------------------------------