bern_kernel_macros/
lib.rs

1//! Procedural macros for the `bern_kernel`.
2//!
3//! This crate provides macros that:
4//! - simplify the kernel usage
5//! - make kernel development less tedious (used internally)
6mod enum_map;
7mod process;
8
9use proc_macro::TokenStream;
10use quote::ToTokens;
11
12/// Generates an enum with values and a map to match the enum to another type.
13///
14/// e.g.
15/// ```ignore
16/// enum_map!{
17///     Size, u8;
18///     S128 = 5, 128;
19///     S256 = 6, 256;
20/// }
21/// ```
22/// expands to
23/// ```ignore
24/// #[derive(Copy, Clone, Debug, Eq, PartialEq)]
25/// #[repr(u8)]
26/// pub enum Size {
27///     S128 = 5,
28///     S256 = 6,
29/// }
30/// impl Size {
31///     pub const fn bits(self) -> u8 {
32///         self as u8
33///     }
34/// }
35///
36/// #[macro_export]
37/// macro_rules! size_from {
38///     (128) => { Size::S128 };
39///     (256) => { Size::S256 };
40///     ($x:expr) => {
41///         compile_error!("Invalid parameter - possible values are: 128, 256");
42///     }
43/// }
44/// ```
45/// ```
46#[doc(hidden)]
47#[proc_macro]
48pub fn enum_map(input: TokenStream) -> TokenStream {
49    let map = syn::parse_macro_input!(input as enum_map::EnumMap);
50    let mut output = proc_macro2::TokenStream::new();
51    map.to_tokens(&mut output);
52    TokenStream::from(output)
53}
54
55/// Creates a new process and the required linker sections.
56///
57/// # Example
58/// ```ignore
59/// // Create a process named `my_proc` with 32kB memory.
60/// static MY_PROC: &Process = bern_kernel::new_process!(my_proc, 32768);
61///
62/// // Place static variable in process memory.
63/// #[link_section = ".process.my_proc"]
64/// static DATA: u32 = 0xDEADBEEF;
65///
66/// #[entry]
67/// fn main() -> ! {
68///     let board = Board::new();
69///     bern_kernel::init();
70///     /*..*/
71///     MY_PROC.init(move |c| {
72///         // Spawn threads.
73///     }).unwrap();
74///     /*..*/
75///     bern_kernel::start();
76/// }
77/// ```
78#[proc_macro]
79pub fn new_process(input: TokenStream) -> TokenStream {
80    let map = syn::parse_macro_input!(input as process::ProcessInfo);
81    let mut output = proc_macro2::TokenStream::new();
82    map.to_tokens(&mut output);
83    TokenStream::from(output)
84}