#![deny(missing_docs)]
#![deny(rust_2021_compatibility)]
#![deny(rust_2018_compatibility)]
#![deny(rust_2018_idioms)]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg",
html_favicon_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg"
)]
#[allow(unused_extern_crates)]
extern crate proc_macro;
use core::ops;
use proc_macro::TokenStream;
use indexmap::{IndexMap, IndexSet};
use proc_macro2::TokenStream as TokenStream2;
use syn::Ident;
use crate::ast::App;
mod accessors;
pub mod analyze;
pub mod ast;
mod check;
mod optimize;
mod parse;
#[cfg(test)]
mod tests;
pub type Map<T> = IndexMap<Ident, T>;
pub type Set<T> = IndexSet<T>;
pub struct P<T> {
ptr: Box<T>,
}
impl<T> P<T> {
pub fn new(x: T) -> P<T> {
P { ptr: Box::new(x) }
}
}
impl<T> ops::Deref for P<T> {
type Target = T;
fn deref(&self) -> &T {
&self.ptr
}
}
#[derive(Clone, Copy)]
pub enum Context<'a> {
Idle,
Init,
SoftwareTask(&'a Ident),
HardwareTask(&'a Ident),
}
impl<'a> Context<'a> {
pub fn ident(&self, app: &'a App) -> &'a Ident {
match self {
Context::HardwareTask(ident) => ident,
Context::Idle => &app.idle.as_ref().unwrap().name,
Context::Init => &app.init.name,
Context::SoftwareTask(ident) => ident,
}
}
pub fn is_idle(&self) -> bool {
matches!(self, Context::Idle)
}
pub fn is_init(&self) -> bool {
matches!(self, Context::Init)
}
pub fn runs_once(&self) -> bool {
self.is_init() || self.is_idle()
}
pub fn has_shared_resources(&self, app: &App) -> bool {
match *self {
Context::HardwareTask(name) => {
!app.hardware_tasks[name].args.shared_resources.is_empty()
}
Context::Idle => !app.idle.as_ref().unwrap().args.shared_resources.is_empty(),
Context::Init => false,
Context::SoftwareTask(name) => {
!app.software_tasks[name].args.shared_resources.is_empty()
}
}
}
pub fn has_local_resources(&self, app: &App) -> bool {
match *self {
Context::HardwareTask(name) => {
!app.hardware_tasks[name].args.local_resources.is_empty()
}
Context::Idle => !app.idle.as_ref().unwrap().args.local_resources.is_empty(),
Context::Init => !app.init.args.local_resources.is_empty(),
Context::SoftwareTask(name) => {
!app.software_tasks[name].args.local_resources.is_empty()
}
}
}
}
#[derive(Default)]
#[non_exhaustive]
pub struct Settings {
pub parse_binds: bool,
pub parse_extern_interrupt: bool,
pub optimize_priorities: bool,
}
pub fn parse(
args: TokenStream,
input: TokenStream,
settings: Settings,
) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
parse2(args.into(), input.into(), settings)
}
pub fn parse2(
args: TokenStream2,
input: TokenStream2,
settings: Settings,
) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
let mut app = parse::app(args, input, &settings)?;
check::app(&app)?;
optimize::app(&mut app, &settings);
match analyze::app(&app) {
Err(e) => Err(e),
Ok(analysis) => Ok((P::new(app), P::new(analysis))),
}
}
enum Either<A, B> {
Left(A),
Right(B),
}