1#![deny(missing_docs)]
4#![deny(rust_2018_compatibility)]
5#![deny(rust_2018_idioms)]
6#![deny(warnings)]
7
8#[allow(unused_extern_crates)]
9extern crate proc_macro;
10
11use core::ops;
12use proc_macro::TokenStream;
13
14use indexmap::{IndexMap, IndexSet};
15use proc_macro2::TokenStream as TokenStream2;
16use syn::Ident;
17
18use crate::ast::App;
19
20mod accessors;
21pub mod analyze;
22pub mod ast;
23mod check;
24mod optimize;
25mod parse;
26#[cfg(test)]
27mod tests;
28
29pub type Core = u8;
31
32pub type Map<T> = IndexMap<Ident, T>;
34
35pub type Set<T> = IndexSet<T>;
37
38pub struct P<T> {
40 ptr: Box<T>,
41}
42
43impl<T> P<T> {
44 pub fn new(x: T) -> P<T> {
46 P { ptr: Box::new(x) }
47 }
48}
49
50impl<T> ops::Deref for P<T> {
51 type Target = T;
52
53 fn deref(&self) -> &T {
54 &self.ptr
55 }
56}
57
58#[derive(Clone, Copy)]
60pub enum Context<'a> {
61 HardwareTask(&'a Ident),
63
64 Idle(Core),
66
67 Init(Core),
69
70 SoftwareTask(&'a Ident),
72}
73
74impl<'a> Context<'a> {
75 pub fn core(&self, app: &App) -> u8 {
77 match self {
78 Context::HardwareTask(name) => app.hardware_tasks[*name].args.core,
79 Context::Idle(core) => app.idles[core].args.core,
80 Context::Init(core) => app.inits[core].args.core,
81 Context::SoftwareTask(name) => app.software_tasks[*name].args.core,
82 }
83 }
84
85 pub fn ident(&self, app: &'a App) -> &'a Ident {
87 match self {
88 Context::HardwareTask(ident) => ident,
89 Context::Idle(core) => &app.idles[core].name,
90 Context::Init(core) => &app.inits[core].name,
91 Context::SoftwareTask(ident) => ident,
92 }
93 }
94
95 pub fn is_idle(&self) -> bool {
97 if let Context::Idle(_) = self {
98 true
99 } else {
100 false
101 }
102 }
103
104 pub fn is_init(&self) -> bool {
106 if let Context::Init(_) = self {
107 true
108 } else {
109 false
110 }
111 }
112
113 pub fn runs_once(&self) -> bool {
115 self.is_init() || self.is_idle()
116 }
117
118 pub fn has_locals(&self, app: &App) -> bool {
120 match *self {
121 Context::HardwareTask(name) => !app.hardware_tasks[name].locals.is_empty(),
122 Context::Idle(core) => !app.idles[&core].locals.is_empty(),
123 Context::Init(core) => !app.inits[&core].locals.is_empty(),
124 Context::SoftwareTask(name) => !app.software_tasks[name].locals.is_empty(),
125 }
126 }
127
128 pub fn has_resources(&self, app: &App) -> bool {
130 match *self {
131 Context::HardwareTask(name) => !app.hardware_tasks[name].args.resources.is_empty(),
132 Context::Idle(core) => !app.idles[&core].args.resources.is_empty(),
133 Context::Init(core) => !app.inits[&core].args.resources.is_empty(),
134 Context::SoftwareTask(name) => !app.software_tasks[name].args.resources.is_empty(),
135 }
136 }
137
138 pub fn uses_schedule(&self, app: &App) -> bool {
140 match *self {
141 Context::HardwareTask(name) => !app.hardware_tasks[name].args.schedule.is_empty(),
142 Context::Idle(core) => !app.idles[&core].args.schedule.is_empty(),
143 Context::Init(core) => !app.inits[&core].args.schedule.is_empty(),
144 Context::SoftwareTask(name) => !app.software_tasks[name].args.schedule.is_empty(),
145 }
146 }
147
148 pub fn uses_spawn(&self, app: &App) -> bool {
150 match *self {
151 Context::HardwareTask(name) => !app.hardware_tasks[name].args.spawn.is_empty(),
152 Context::Idle(core) => !app.idles[&core].args.spawn.is_empty(),
153 Context::Init(core) => !app.inits[&core].args.spawn.is_empty(),
154 Context::SoftwareTask(name) => !app.software_tasks[name].args.spawn.is_empty(),
155 }
156 }
157}
158
159#[derive(Default)]
161pub struct Settings {
162 pub parse_binds: bool,
164 pub parse_cores: bool,
166 pub parse_extern_interrupt: bool,
168 pub parse_schedule: bool,
170
171 pub optimize_priorities: bool,
173
174 _extensible: (),
175}
176
177pub fn parse(
179 args: TokenStream,
180 input: TokenStream,
181 settings: Settings,
182) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
183 parse2(args.into(), input.into(), settings)
184}
185
186pub fn parse2(
188 args: TokenStream2,
189 input: TokenStream2,
190 ref settings: Settings,
191) -> Result<(P<ast::App>, P<analyze::Analysis>), syn::parse::Error> {
192 let mut app = parse::app(args, input, settings)?;
193 check::app(&app)?;
194 optimize::app(&mut app, settings);
195 let analysis = analyze::app(&app);
196
197 Ok((P::new(app), P::new(analysis)))
198}
199
200enum Either<A, B> {
201 Left(A),
202 Right(B),
203}