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

This commit is contained in:
Zachary Sunforge
2023-06-18 20:49:30 -07:00
parent 07ae111e15
commit ce72a8a5be
6 changed files with 101 additions and 4 deletions

View File

@ -10,6 +10,8 @@ members = [
"peripherals/standalone-ads1256/*",
# Peripheral components
"peripheral-components/ads1256/*",
# Macros
"macros/node-poll-variants",
# Examples
"examples/ads1256"
]
@ -87,6 +89,14 @@ features = ["defmt", "unstable-traits", "unstable-pac", "nightly"]
[workspace.dependencies.embassy-nrf]
version = "0.1.*"
features = ["defmt", "unstable-traits", "nightly"]
# Macros
[workspace.dependencies.syn]
version = "2.0.*"
features = ["extra-traits"]
[workspace.dependencies.quote]
version = "1.0.*"
[workspace.dependencies.trybuild]
version = "1.0.*"
#---------------------------------------------------------------------------------------------------------------------
#----- Patch ------------------------

View File

@ -0,0 +1,23 @@
[package]
name = "node-poll-variants"
description = "Macros for physical nodes."
version.workspace = true
edition.workspace = true
repository.workspace = true
readme.workspace = true
license.workspace = true
[lib]
proc-macro = true
[[test]]
name = "tests"
path = "tests/test_build.rs"
[dependencies.syn]
workspace = true
[dependencies.quote]
workspace = true
[dev-dependencies.trybuild]
workspace = true

View File

@ -0,0 +1,46 @@
use proc_macro::TokenStream;
use std::ops::Deref;
use quote::quote;
use syn::{parse_macro_input, DeriveInput, Data, Ident};
// Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub
#[proc_macro_derive(PollVariants)]
pub fn transducer_macro(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let DeriveInput {
attrs,
vis,
ident,
generics,
data,
} = &input;
// Check that item the macro was used on is valid
match data {
Data::Struct(struct_data) => struct_data,
Data::Enum(_) => panic!("Stateful struct cannot be derived from an enum."),
Data::Union(_) => panic!("Stateful struct cannot be derived from a union.")
};
// Check if generics contains T
// If it does make sure it is T: Copy
// If it isn't Copy, panic
// If it doesn't contain T, add it for use in the type that will be generated
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let stateful_name = format!("{ident}Stateful");
let stateful_ident = Ident::new(stateful_name.deref(), ident.span());
eprintln!("input: {input:#?}");
eprintln!("impl_generics: {impl_generics:#?}");
let expanded = quote! {
#vis struct #stateful_ident #generics {
pub poll: #ident #ty_generics,
pub state: physical::transducer::State<T>,
}
};
TokenStream::from(expanded)
}

View File

@ -0,0 +1,11 @@
use node_poll_variants::{PollVariants};
#[derive(PollVariants)]
struct ExamplePoll<'a, FirstT: Copy, SecondT> {
a: &'a i32,
b: i32,
first: FirstT,
second: SecondT,
}
fn main() {}

View File

@ -0,0 +1,5 @@
#[test]
fn tests() {
let t = trybuild::TestCases::new();
t.pass("tests/generate.rs");
}

View File

@ -1,7 +1,9 @@
pub trait Output {
type Value: Copy;
//TODO: return result
//TODO: Make maybe async
fn output(&mut self, setting: Self::Value);
//TODO: Should this be maybe async?
fn output(&mut self, setting: Self::Value) -> Result<(), InvalidOutputSetting>;
}
/// Indicates the setting given for an [Output] is statically known to be an impossible setting to achieve.
pub struct InvalidOutputSetting;