rtic_syntax/
lib.rs
1#![deny(missing_docs)]
4#![deny(rust_2021_compatibility)]
5#![deny(rust_2018_compatibility)]
6#![deny(rust_2018_idioms)]
7#![doc(
8 html_logo_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg",
9 html_favicon_url = "https://raw.githubusercontent.com/rtic-rs/cortex-m-rtic/master/book/en/src/RTIC.svg"
10)]
11#[allow(unused_extern_crates)]
14extern crate proc_macro;
15
16use core::ops;
17use proc_macro::TokenStream;
18
19use indexmap::{IndexMap, IndexSet};
20use proc_macro2::TokenStream as TokenStream2;
21use syn::Ident;
22
23use crate::ast::App;
24
25mod accessors;
26pub mod analyze;
27pub mod ast;
28mod check;
29mod optimize;
30mod parse;
31#[cfg(test)]
32mod tests;
33
34pub type Map<T> = IndexMap<Ident, T>;
36
37pub type Set<T> = IndexSet<T>;
39
40pub struct P<T> {
42 ptr: Box<T>,
43}
44
45impl<T> P<T> {
46 pub fn new(x: T) -> P<T> {
48 P { ptr: Box::new(x) }
49 }
50}
51
52impl<T> ops::Deref for P<T> {
53 type Target = T;
54
55 fn deref(&self) -> &T {
56 &self.ptr
57 }
58}
59
60#[derive(Clone, Copy)]
62pub enum Context<'a> {
63 Idle,
65
66 Init,
68
69 SoftwareTask(&'a Ident),
71
72 HardwareTask(&'a Ident),
74}
75
76impl<'a> Context<'a> {
77 pub fn ident(&self, app: &'a App) -> &'a Ident {
79 match self {
80 Context::HardwareTask(ident) => ident,
81 Context::Idle => &app.idle.as_ref().unwrap().name,
82 Context::Init => &app.init.name,
83 Context::SoftwareTask(ident) => ident,
84 }
85 }
86
87 pub fn is_idle(&self) -> bool {
89 matches!(self, Context::Idle)
90 }
91
92 pub fn is_init(&self) -> bool {
94 matches!(self, Context::Init)
95 }
96
97 pub fn runs_once(&self) -> bool {
99 self.is_init() || self.is_idle()
100 }
101
102 pub fn has_shared_resources(&self, app: &App) -> bool {
104 match *self {
105 Context::HardwareTask(name) => {
106 !app.hardware_tasks[name].args.shared_resources.is_empty()
107 }
108 Context::Idle => !app.idle.as_ref().unwrap().args.shared_resources.is_empty(),
109 Context::Init => false,
110 Context::SoftwareTask(name) => {
111 !app.software_tasks[name].args.shared_resources.is_empty()
112 }
113 }
114 }
115
116 pub fn has_local_resources(&self, app: &App) -> bool {
118 match *self {
119 Context::HardwareTask(name) => {
120 !app.hardware_tasks[name].args.local_resources.is_empty()
121 }
122 Context::Idle => !app.idle.as_ref().unwrap().args.local_resources.is_empty(),
123 Context::Init => !app.init.args.local_resources.is_empty(),
124 Context::SoftwareTask(name) => {
125 !app.software_tasks[name].args.local_resources.is_empty()
126 }
127 }
128 }
129}
130
131#[derive(Default)]
133#[non_exhaustive]
134pub struct Settings {
135 pub parse_binds: bool,
137 pub parse_extern_interrupt: bool,
139 pub optimize_priorities: bool,
141}
142
143pub fn parse(
145 args: TokenStream,
146 input: TokenStream,
147 settings: Settings,
148) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
149 parse2(args.into(), input.into(), settings)
150}
151
152pub fn parse2(
154 args: TokenStream2,
155 input: TokenStream2,
156 settings: Settings,
157) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
158 let mut app = parse::app(args, input, &settings)?;
159 check::app(&app)?;
160 optimize::app(&mut app, &settings);
161
162 match analyze::app(&app) {
163 Err(e) => Err(e),
164 Ok(analysis) => Ok((P::new(app), P::new(analysis))),
166 }
167}
168
169enum Either<A, B> {
170 Left(A),
171 Right(B),
172}