rtic_macros/codegen/
init.rs

1use proc_macro2::TokenStream as TokenStream2;
2use quote::quote;
3
4use crate::{
5    analyze::Analysis,
6    codegen::{local_resources_struct, module},
7    syntax::{ast::App, Context},
8};
9
10/// Generates support code for `#[init]` functions
11pub fn codegen(app: &App, analysis: &Analysis) -> TokenStream2 {
12    let init = &app.init;
13    let name = &init.name;
14
15    let mut root_init = vec![];
16
17    let context = &init.context;
18    let attrs = &init.attrs;
19    let stmts = &init.stmts;
20    let shared = &init.user_shared_struct;
21    let shared_vis = &app.shared_resources_vis;
22    let local = &init.user_local_struct;
23    let local_vis = &app.local_resources_vis;
24
25    let shared_resources: Vec<_> = app
26        .shared_resources
27        .iter()
28        .map(|(k, v)| {
29            let ty = &v.ty;
30            let cfgs = &v.cfgs;
31            let docs = &v.docs;
32            let vis = &v.vis;
33            quote!(
34                #(#cfgs)*
35                #(#docs)*
36                #vis #k: #ty,
37            )
38        })
39        .collect();
40    let local_resources: Vec<_> = app
41        .local_resources
42        .iter()
43        .map(|(k, v)| {
44            let ty = &v.ty;
45            let cfgs = &v.cfgs;
46            let docs = &v.docs;
47            let vis = &v.vis;
48            quote!(
49                #(#cfgs)*
50                #(#docs)*
51                #vis #k: #ty,
52            )
53        })
54        .collect();
55
56    root_init.push(quote! {
57        #[doc = r"Shared resources"]
58        #shared_vis struct #shared {
59            #(#shared_resources)*
60        }
61
62        #[doc = r"Local resources"]
63        #local_vis struct #local {
64            #(#local_resources)*
65        }
66    });
67
68    // let locals_pat = locals_pat.iter();
69
70    let user_init_return = quote! {#shared, #local};
71
72    let user_init = if !init.is_extern {
73        Some(quote!(
74            #(#attrs)*
75            #[inline(always)]
76            #[allow(non_snake_case)]
77            fn #name(#context: #name::Context) -> (#user_init_return) {
78                #(#stmts)*
79            }
80        ))
81    } else {
82        None
83    };
84
85    let mut mod_app = None;
86
87    // `${task}Locals`
88    if !init.args.local_resources.is_empty() {
89        let (item, constructor) = local_resources_struct::codegen(Context::Init, app);
90
91        root_init.push(item);
92
93        mod_app = Some(constructor);
94    }
95
96    root_init.push(module::codegen(Context::Init, app, analysis));
97
98    quote!(
99        #mod_app
100
101        #(#root_init)*
102
103        #user_init
104    )
105}