use proc_macro2::TokenStream;
use quote::quote;
use rtic_syntax::{analyze::Analysis, ast::App};
use crate::codegen::util;
pub fn codegen(
app: &App,
_analysis: &Analysis,
) -> (
// mod_app -- the `static` variables behind the proxies
Vec<TokenStream>,
// mod_resources -- the `resources` module
TokenStream,
) {
let mut mod_app = vec![];
let mut mod_resources = vec![];
for (name, res) in &app.shared_resources {
let cfgs = &res.cfgs;
let ty = &res.ty;
let mangled_name = &util::static_shared_resource_ident(&name);
let attrs = &res.attrs;
mod_app.push(quote!(
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[doc(hidden)]
#(#attrs)*
#(#cfgs)*
static #mangled_name: rtic::RacyCell<core::mem::MaybeUninit<rtic::PcpMutex<#ty>>>
= rtic::RacyCell::new(core::mem::MaybeUninit::uninit());
));
if !res.properties.lock_free {
mod_resources.push(quote!(
#[doc(hidden)]
#[allow(non_camel_case_types)]
#(#cfgs)*
pub struct #name<'a> {
pub __marker__: &'a core::marker::PhantomData<()>
}
#(#cfgs)*
impl<'a> #name<'a> {
#[inline(always)]
pub unsafe fn new(__marker__: &'a core::marker::PhantomData<()>) -> Self {
#name { __marker__ }
}
}
));
let ptr = quote!(
#(#cfgs)*
#mangled_name.get_mut_unchecked().as_mut_ptr()
);
let tracing_name = format!("shared_{}", name);
let tracing_name_locked = format!("shared_{}_locked", name);
mod_app.push(quote!(
#(#cfgs)*
impl<'a> rtic::Mutex for shared_resources::#name<'a> {
type T = #ty;
#[inline(always)]
fn lock<RTIC_INTERNAL_R>(&mut self, f: impl FnOnce(&mut #ty) -> RTIC_INTERNAL_R) -> RTIC_INTERNAL_R {
let mutex = unsafe { & *#ptr };
#[cfg(feature = "profiling")]
let _span = rtic::tracing::span!(rtic::tracing::Level::TRACE, #tracing_name).entered();
#[cfg(feature = "profiling")]
rtic::tracing::trace!("locking");
let r = mutex.lock(|res| {
#[cfg(feature = "profiling")]
let _span = rtic::tracing::span!(rtic::tracing::Level::TRACE, #tracing_name_locked).entered();
#[cfg(feature = "profiling")]
rtic::tracing::trace!("locked");
let r = f(res);
#[cfg(feature = "profiling")]
rtic::tracing::trace!("unlocking");
r
});
#[cfg(feature = "profiling")]
rtic::tracing::trace!("unlocked");
r
}
}
));
}
}
let mod_resources = if mod_resources.is_empty() {
quote!()
} else {
quote!(mod shared_resources {
#(#mod_resources)*
})
};
(mod_app, mod_resources)
}