rtic_macros/syntax/
ast.rs

1//! Abstract Syntax Tree
2
3use syn::{Attribute, Expr, Ident, Item, ItemUse, Pat, PatType, Path, Stmt, Type};
4
5use crate::syntax::{backend::BackendArgs, Map};
6
7/// The `#[app]` attribute
8#[derive(Debug)]
9#[non_exhaustive]
10pub struct App {
11    /// The arguments to the `#[app]` attribute
12    pub args: AppArgs,
13
14    /// The name of the `const` item on which the `#[app]` attribute has been placed
15    pub name: Ident,
16
17    /// The `#[init]` function
18    pub init: Init,
19
20    /// The `#[idle]` function
21    pub idle: Option<Idle>,
22
23    /// Resources shared between tasks defined in `#[shared]`
24    pub shared_resources: Map<SharedResource>,
25
26    pub shared_resources_vis: syn::Visibility,
27
28    /// Task local resources defined in `#[local]`
29    pub local_resources: Map<LocalResource>,
30
31    pub local_resources_vis: syn::Visibility,
32
33    /// User imports
34    pub user_imports: Vec<ItemUse>,
35
36    /// User code
37    pub user_code: Vec<Item>,
38
39    /// Hardware tasks: `#[task(binds = ..)]`s
40    pub hardware_tasks: Map<HardwareTask>,
41
42    /// Async software tasks: `#[task]`
43    pub software_tasks: Map<SoftwareTask>,
44}
45
46/// Interrupts used to dispatch software tasks
47pub type Dispatchers = Map<Dispatcher>;
48
49/// Interrupt that could be used to dispatch software tasks
50#[derive(Debug, Clone)]
51#[non_exhaustive]
52pub struct Dispatcher {
53    /// Attributes that will apply to this interrupt handler
54    pub attrs: Vec<Attribute>,
55}
56
57/// The arguments of the `#[app]` attribute
58#[derive(Debug)]
59pub struct AppArgs {
60    /// Device
61    pub device: Path,
62
63    /// Core peripherals
64    pub core: bool,
65
66    /// Device peripherals
67    pub peripherals: bool,
68
69    /// Interrupts used to dispatch software tasks
70    pub dispatchers: Dispatchers,
71
72    /// Backend-specific arguments
73    #[allow(dead_code)]
74    pub backend: Option<BackendArgs>,
75}
76
77/// The `init`-ialization function
78#[derive(Debug)]
79#[non_exhaustive]
80pub struct Init {
81    /// `init` context metadata
82    pub args: InitArgs,
83
84    /// Attributes that will apply to this `init` function
85    pub attrs: Vec<Attribute>,
86
87    /// The name of the `#[init]` function
88    pub name: Ident,
89
90    /// The context argument
91    pub context: Box<Pat>,
92
93    /// The statements that make up this `init` function
94    pub stmts: Vec<Stmt>,
95
96    /// The name of the user provided shared resources struct
97    pub user_shared_struct: Ident,
98
99    /// The name of the user provided local resources struct
100    pub user_local_struct: Ident,
101
102    /// The init function is declared externally
103    pub is_extern: bool,
104}
105
106/// `init` context metadata
107#[derive(Debug)]
108#[non_exhaustive]
109pub struct InitArgs {
110    /// Local resources that can be accessed from this context
111    pub local_resources: LocalResources,
112}
113
114impl Default for InitArgs {
115    fn default() -> Self {
116        Self {
117            local_resources: LocalResources::new(),
118        }
119    }
120}
121
122/// The `idle` context
123#[derive(Debug)]
124#[non_exhaustive]
125pub struct Idle {
126    /// `idle` context metadata
127    pub args: IdleArgs,
128
129    /// Attributes that will apply to this `idle` function
130    pub attrs: Vec<Attribute>,
131
132    /// The name of the `#[idle]` function
133    pub name: Ident,
134
135    /// The context argument
136    pub context: Box<Pat>,
137
138    /// The statements that make up this `idle` function
139    pub stmts: Vec<Stmt>,
140
141    /// The idle function is declared externally
142    pub is_extern: bool,
143}
144
145/// `idle` context metadata
146#[derive(Debug)]
147#[non_exhaustive]
148pub struct IdleArgs {
149    /// Local resources that can be accessed from this context
150    pub local_resources: LocalResources,
151
152    /// Shared resources that can be accessed from this context
153    pub shared_resources: SharedResources,
154}
155
156impl Default for IdleArgs {
157    fn default() -> Self {
158        Self {
159            local_resources: LocalResources::new(),
160            shared_resources: SharedResources::new(),
161        }
162    }
163}
164
165/// Shared resource properties
166#[derive(Debug)]
167pub struct SharedResourceProperties {
168    /// A lock free (exclusive resource)
169    pub lock_free: bool,
170}
171
172/// A shared resource, defined in `#[shared]`
173#[derive(Debug)]
174#[non_exhaustive]
175pub struct SharedResource {
176    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
177    pub cfgs: Vec<Attribute>,
178
179    /// `#[doc]` attributes like `/// this is a docstring`
180    pub docs: Vec<Attribute>,
181
182    /// Attributes that will apply to this resource
183    pub attrs: Vec<Attribute>,
184
185    /// The type of this resource
186    pub ty: Box<Type>,
187
188    /// Shared resource properties
189    pub properties: SharedResourceProperties,
190
191    /// The visibility of this resource
192    pub vis: syn::Visibility,
193}
194
195/// A local resource, defined in `#[local]`
196#[derive(Debug)]
197#[non_exhaustive]
198pub struct LocalResource {
199    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
200    pub cfgs: Vec<Attribute>,
201
202    /// `#[doc]` attributes like `/// this is a docstring`
203    pub docs: Vec<Attribute>,
204
205    /// Attributes that will apply to this resource
206    pub attrs: Vec<Attribute>,
207
208    /// The type of this resource
209    pub ty: Box<Type>,
210
211    /// The visibility of this resource
212    pub vis: syn::Visibility,
213}
214
215/// An async software task
216#[derive(Debug)]
217#[non_exhaustive]
218pub struct SoftwareTask {
219    /// Software task metadata
220    pub args: SoftwareTaskArgs,
221
222    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
223    pub cfgs: Vec<Attribute>,
224
225    /// Attributes that will apply to this interrupt handler
226    pub attrs: Vec<Attribute>,
227
228    /// The context argument
229    pub context: Box<Pat>,
230
231    /// The inputs of this software task
232    pub inputs: Vec<PatType>,
233
234    /// The statements that make up the task handler
235    pub stmts: Vec<Stmt>,
236
237    /// The task is declared externally
238    pub is_extern: bool,
239
240    /// The task will never return `Poll::Ready`
241    pub is_bottom: bool,
242}
243
244/// Software task metadata
245#[derive(Debug)]
246#[non_exhaustive]
247pub struct SoftwareTaskArgs {
248    /// The priority of this task
249    pub priority: u8,
250
251    /// Local resources that can be accessed from this context
252    pub local_resources: LocalResources,
253
254    /// Shared resources that can be accessed from this context
255    pub shared_resources: SharedResources,
256}
257
258impl Default for SoftwareTaskArgs {
259    fn default() -> Self {
260        Self {
261            priority: 0,
262            local_resources: LocalResources::new(),
263            shared_resources: SharedResources::new(),
264        }
265    }
266}
267
268/// A hardware task
269#[derive(Debug)]
270#[non_exhaustive]
271pub struct HardwareTask {
272    /// Hardware task metadata
273    pub args: HardwareTaskArgs,
274
275    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
276    pub cfgs: Vec<Attribute>,
277
278    /// Attributes that will apply to this interrupt handler
279    pub attrs: Vec<Attribute>,
280
281    /// The context argument
282    pub context: Box<Pat>,
283
284    /// The statements that make up the task handler
285    pub stmts: Vec<Stmt>,
286
287    /// The task is declared externally
288    pub is_extern: bool,
289}
290
291/// Hardware task metadata
292#[derive(Debug)]
293#[non_exhaustive]
294pub struct HardwareTaskArgs {
295    /// The interrupt or exception that this task is bound to
296    pub binds: Ident,
297
298    /// The priority of this task
299    pub priority: u8,
300
301    /// Local resources that can be accessed from this context
302    pub local_resources: LocalResources,
303
304    /// Shared resources that can be accessed from this context
305    pub shared_resources: SharedResources,
306}
307
308/// A `static mut` variable local to and owned by a context
309#[derive(Debug)]
310#[non_exhaustive]
311pub struct Local {
312    /// Attributes like `#[link_section]`
313    pub attrs: Vec<Attribute>,
314
315    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
316    pub cfgs: Vec<Attribute>,
317
318    /// Type
319    pub ty: Box<Type>,
320
321    /// Initial value
322    pub expr: Box<Expr>,
323}
324
325/// A wrapper of the 2 kinds of locals that tasks can have
326#[derive(Debug)]
327#[non_exhaustive]
328pub enum TaskLocal {
329    /// The local is declared externally (i.e. `#[local]` struct)
330    External,
331    /// The local is declared in the task
332    Declared(Local),
333}
334
335/// Resource access
336#[derive(Clone, Copy, Debug, Eq, PartialEq)]
337pub enum Access {
338    /// `[x]`, a mutable resource
339    Exclusive,
340
341    /// `[&x]`, a static non-mutable resource
342    Shared,
343}
344
345impl Access {
346    /// Is this enum in the `Exclusive` variant?
347    pub fn is_exclusive(&self) -> bool {
348        *self == Access::Exclusive
349    }
350
351    /// Is this enum in the `Shared` variant?
352    pub fn is_shared(&self) -> bool {
353        *self == Access::Shared
354    }
355}
356
357/// Shared resource access list in task attribute
358pub type SharedResources = Map<Access>;
359
360/// Local resource access/declaration list in task attribute
361pub type LocalResources = Map<TaskLocal>;