Device macro to generate stateful and publish variants of device specific poll inputs.
This commit is contained in:
@ -1,11 +1,13 @@
|
|||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use std::path::Path;
|
|
||||||
use syn::__private::Span;
|
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::{parse_macro_input, Data, DeriveInput, GenericParam, Ident, PathSegment, Token, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, Meta, Expr, Lit};
|
use syn::{
|
||||||
|
parse_macro_input, Data, DeriveInput, Expr, GenericParam, Ident, Lit, Meta, Path, PathSegment,
|
||||||
|
Token, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound,
|
||||||
|
};
|
||||||
|
|
||||||
// Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub
|
// Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub
|
||||||
#[proc_macro_derive(PollVariants, attributes(value_type))]
|
#[proc_macro_derive(PollVariants, attributes(value_type))]
|
||||||
@ -31,10 +33,10 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
|
|||||||
let mut value_type_ident: Option<Ident> = None;
|
let mut value_type_ident: Option<Ident> = None;
|
||||||
for attribute in attrs.iter() {
|
for attribute in attrs.iter() {
|
||||||
// if the attribute is a named value
|
// if the attribute is a named value
|
||||||
if let Meta::NameValue(meta) = &attribute.meta {
|
if let Meta::NameValue(meta) = &attribute.meta {
|
||||||
// if the name of the attribute is value_t
|
// if the name of the attribute is value_t
|
||||||
if meta.path.segments[0].ident == VALUE_T_NAME {
|
if meta.path.segments[0].ident == VALUE_T_NAME {
|
||||||
// if the value of the attribute is a literal
|
// if the value of the attribute is a literal
|
||||||
if let Expr::Lit(lit) = &meta.value {
|
if let Expr::Lit(lit) = &meta.value {
|
||||||
// if the literal is a string
|
// if the literal is a string
|
||||||
if let Lit::Str(lit) = &lit.lit {
|
if let Lit::Str(lit) = &lit.lit {
|
||||||
@ -45,13 +47,13 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
|
|||||||
} else {
|
} else {
|
||||||
panic!("{VALUE_T_NAME} must be set with a literal.")
|
panic!("{VALUE_T_NAME} must be set with a literal.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
let value_type_ident = if let Some(val) = value_type_ident {
|
let value_type_ident = if let Some(val) = value_type_ident {
|
||||||
val
|
val
|
||||||
} else {
|
} else {
|
||||||
@ -59,56 +61,95 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// ----- Build publisher generics ----------------------------------
|
// ----- Build publisher generics ----------------------------------
|
||||||
//TODO: Get rid of all this adding T stuff
|
// Check if generics contains T
|
||||||
|
const MUTEX_T_IDENT_STR: &str = "MutexT";
|
||||||
|
let mut num_lifetimes: usize = 0;
|
||||||
|
let mut num_types: usize = 0;
|
||||||
|
let mut num_const: usize = 0;
|
||||||
|
let mut has_mutex_t = false;
|
||||||
|
for param in og_generics.params.iter() {
|
||||||
|
match param {
|
||||||
|
GenericParam::Lifetime(_) => num_lifetimes += 1,
|
||||||
|
GenericParam::Type(param) => {
|
||||||
|
num_types += 1;
|
||||||
|
|
||||||
// // Check if generics contains T
|
// If the generic parameter is T
|
||||||
// const T_IDENT_STR: &str = "T";
|
if param.ident == MUTEX_T_IDENT_STR {
|
||||||
// const COPY_IDENT_STR: &str = "Copy";
|
has_mutex_t = true;
|
||||||
// let mut first_type_index: Option<usize> = None;
|
}
|
||||||
// let mut has_t = false;
|
},
|
||||||
// for (index, param) in og_generics.params.iter().enumerate() {
|
GenericParam::Const(_) => num_const += 1,
|
||||||
// // If the generic parameter is a type
|
}
|
||||||
// if let GenericParam::Type(param) = param {
|
}
|
||||||
// if first_type_index.is_none() {
|
|
||||||
// first_type_index = Some(index);
|
|
||||||
// }
|
|
||||||
// // If the generic parameter is T
|
|
||||||
// if param.ident == T_IDENT_STR {
|
|
||||||
// has_t = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let mut generics_with_t = og_generics.clone();
|
let mut publish_generics = og_generics.clone();
|
||||||
// // If T is not a generic parameter, add it
|
// If MutexT is not a generic parameter, add it
|
||||||
// if !has_t {
|
if !has_mutex_t {
|
||||||
// let first_type_index = first_type_index.unwrap_or(0);
|
let mutex_t_ident = Ident::new(MUTEX_T_IDENT_STR, Span::call_site());
|
||||||
// let t_ident = Ident::new(T_IDENT_STR, Span::call_site());
|
let mut mutex_t_bounds: Punctuated<TypeParamBound, Plus> = Punctuated::new();
|
||||||
// let copy_ident = Ident::new(COPY_IDENT_STR, Span::call_site());
|
|
||||||
// let mut t_bounds: Punctuated<TypeParamBound, Plus> = Punctuated::new();
|
let mut path: Punctuated<PathSegment, PathSep> = Punctuated::new();
|
||||||
//
|
path.push(Ident::new("embassy_sync", Span::call_site()).into());
|
||||||
// let t_bound = TraitBound {
|
path.push(Ident::new("blocking_mutex", Span::call_site()).into());
|
||||||
// paren_token: None,
|
path.push(Ident::new("raw", Span::call_site()).into());
|
||||||
// modifier: TraitBoundModifier::None,
|
path.push(Ident::new("RawMutex", Span::call_site()).into());
|
||||||
// lifetimes: None,
|
let raw_mutex_path = Path {
|
||||||
// path: copy_ident.into(),
|
leading_colon: None,
|
||||||
// };
|
segments: path,
|
||||||
// t_bounds.push(t_bound.into());
|
};
|
||||||
//
|
|
||||||
// let t_param: TypeParam = TypeParam {
|
let mutex_t_bound = TraitBound {
|
||||||
// attrs: Vec::new(),
|
paren_token: None,
|
||||||
// ident: t_ident,
|
modifier: TraitBoundModifier::None,
|
||||||
// colon_token: Some(Colon::default()),
|
lifetimes: None,
|
||||||
// bounds: t_bounds,
|
path: raw_mutex_path,
|
||||||
// eq_token: None,
|
};
|
||||||
// default: None,
|
mutex_t_bounds.push(mutex_t_bound.into());
|
||||||
// };
|
|
||||||
// generics_with_t
|
let mutex_t_param: TypeParam = TypeParam {
|
||||||
// .params
|
attrs: Vec::new(),
|
||||||
// .insert(first_type_index, t_param.into());
|
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;
|
||||||
|
// If there are generics
|
||||||
|
if num_generics > 0 {
|
||||||
|
// If all generics are lifetimes
|
||||||
|
if num_lifetimes == num_generics {
|
||||||
|
// Add MutexT after the lifetimes
|
||||||
|
publish_generics.params.push(mutex_t_param.into());
|
||||||
|
// If no generics are lifetimes
|
||||||
|
} else if num_lifetimes == 0 {
|
||||||
|
// Insert MutexT at the front
|
||||||
|
publish_generics
|
||||||
|
.params
|
||||||
|
.insert(0, mutex_t_param.into());
|
||||||
|
// If there are lifetimes and other generics
|
||||||
|
} else {
|
||||||
|
// Insert MutexT after the lifetimes
|
||||||
|
publish_generics
|
||||||
|
.params
|
||||||
|
.insert(num_lifetimes, mutex_t_param.into());
|
||||||
|
}
|
||||||
|
// If there are no generics
|
||||||
|
} else {
|
||||||
|
// Add MutexT
|
||||||
|
publish_generics.params.push(mutex_t_param.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// const generics
|
||||||
|
|
||||||
|
|
||||||
|
let (publ_impl_generics, publ_type_generics, publ_where_clause) =
|
||||||
|
&publish_generics.split_for_impl();
|
||||||
|
|
||||||
let stateful_ident = Ident::new(format!("{ident}Stateful").deref(), ident.span());
|
let stateful_ident = Ident::new(format!("{ident}Stateful").deref(), ident.span());
|
||||||
|
let publish_ident = Ident::new(format!("{ident}Publish").deref(), ident.span());
|
||||||
|
let state_pub_ident = Ident::new(format!("{ident}StatePub").deref(), ident.span());
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
// ----- Stateful struct ----------------------------------
|
// ----- Stateful struct ----------------------------------
|
||||||
@ -144,6 +185,11 @@ pub fn poll_variant_macro(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ----- Publish struct ----------------------------------
|
// ----- Publish struct ----------------------------------
|
||||||
|
#[cfg(feature = "embassy-sync")]
|
||||||
|
#vis struct #publish_ident #publish_generics #publ_where_clause {
|
||||||
|
pub poll: #ident #og_type_generics,
|
||||||
|
pub publisher: physical_node::transducer::Publisher<#value_type_ident, MutexT, CAPACITY, NUM_SUBS>,
|
||||||
|
}
|
||||||
|
|
||||||
// ----- Publish impl ----------------------------------
|
// ----- Publish impl ----------------------------------
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user