rtfm_syntax/
ast.rs

1//! Abstract Syntax Tree
2
3use core::ops::Deref;
4use std::collections::BTreeMap;
5
6use syn::{Attribute, Expr, Ident, Pat, PatType, Path, Stmt, Type};
7
8use crate::{Core, Map, Set};
9
10/// The `#[app]` attribute
11#[derive(Debug)]
12pub struct App {
13    /// The arguments to the `#[app]` attribute
14    pub args: AppArgs,
15
16    /// The name of the `const` item on which the `#[app]` attribute has been placed
17    pub name: Ident,
18
19    // NOTE one per core
20    /// Per-core `#[init]` functions
21    pub inits: Inits,
22
23    /// Per-core `#[idle]` functions
24    pub idles: Idles,
25
26    /// Late (runtime initialized) resources
27    pub late_resources: Map<LateResource>,
28
29    /// Early (compile time initialized) resources
30    pub resources: Map<Resource>,
31
32    /// Hardware tasks: `#[task(binds = ..)]`s
33    pub hardware_tasks: Map<HardwareTask>,
34
35    /// Software tasks: `#[task]`
36    pub software_tasks: Map<SoftwareTask>,
37
38    /// Interrupts used to dispatch software tasks
39    pub extern_interrupts: ExternInterrupts,
40
41    pub(crate) _extensible: (),
42}
43
44/// Interrupts used to dispatch software tasks
45pub type ExternInterrupts = BTreeMap<Core, Map<ExternInterrupt>>;
46
47/// The arguments of the `#[app]` attribute
48#[derive(Debug)]
49pub struct AppArgs {
50    /// The number of cores the application will use
51    pub cores: u8,
52
53    /// Custom arguments
54    pub custom: Map<CustomArg>,
55}
56
57/// A custom argument
58#[derive(Debug)]
59pub enum CustomArg {
60    /// A boolean: `true` or `false`
61    Bool(bool),
62
63    /// An unsuffixed, unsigned integer
64    UInt(String),
65
66    /// An item path
67    Path(Path),
68}
69
70/// Per-core `init` functions
71pub type Inits = BTreeMap<u8, Init>;
72/// Per-core `idle` functions
73pub type Idles = BTreeMap<u8, Idle>;
74
75/// The `init`-ialization function
76#[derive(Debug)]
77pub struct Init {
78    /// `init` context metadata
79    pub args: InitArgs,
80
81    /// Attributes that will apply to this `init` function
82    pub attrs: Vec<Attribute>,
83
84    /// The name of the `#[init]` function
85    pub name: Ident,
86
87    /// The context argument
88    pub context: Box<Pat>,
89
90    /// Whether this `init` function returns `LateResources` or not
91    pub returns_late_resources: bool,
92
93    /// Static variables local to this context
94    pub locals: Map<Local>,
95    /// The statements that make up this `init` function
96    pub stmts: Vec<Stmt>,
97
98    pub(crate) _extensible: (),
99}
100
101/// `init` context metadata
102#[derive(Debug, Default)]
103pub struct InitArgs {
104    /// Which core this context belongs to?
105    pub core: u8,
106
107    /// Late resources that will be initialized by this core
108    ///
109    /// NOTE do not use this field for codegen; use `Analysis.late_resources` instead
110    pub late: Set<Ident>,
111
112    /// Resources that can be accessed from this context
113    pub resources: Resources,
114
115    /// Software tasks that can be spawned from this context
116    pub spawn: Set<Ident>,
117
118    /// Software tasks that can be scheduled from this context
119    pub schedule: Set<Ident>,
120
121    pub(crate) _extensible: (),
122}
123
124/// The `idle` context
125#[derive(Debug)]
126pub struct Idle {
127    /// `idle` context metadata
128    pub args: IdleArgs,
129
130    /// Attributes that will apply to this `idle` function
131    pub attrs: Vec<Attribute>,
132
133    /// The name of the `#[idle]` function
134    pub name: Ident,
135
136    /// The context argument
137    pub context: Box<Pat>,
138
139    /// Static variables local to this context
140    pub locals: Map<Local>,
141
142    /// The statements that make up this `idle` function
143    pub stmts: Vec<Stmt>,
144
145    pub(crate) _extensible: (),
146}
147
148/// `idle` context metadata
149#[derive(Debug)]
150pub struct IdleArgs {
151    /// Which core this context belongs to?
152    pub core: u8,
153
154    /// Resources that can be accessed from this context
155    pub resources: Resources,
156
157    /// Software tasks that can be spawned from this context
158    pub spawn: Set<Ident>,
159
160    /// Software tasks that can be scheduled from this context
161    pub schedule: Set<Ident>,
162
163    pub(crate) _extensible: (),
164}
165
166/// An early (compile time initialized) resource
167#[derive(Debug)]
168pub struct Resource {
169    pub(crate) late: LateResource,
170    /// The initial value of this resource
171    pub expr: Box<Expr>,
172}
173
174impl Deref for Resource {
175    type Target = LateResource;
176
177    fn deref(&self) -> &LateResource {
178        &self.late
179    }
180}
181
182/// A late (runtime initialized) resource
183#[derive(Debug)]
184pub struct LateResource {
185    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
186    pub cfgs: Vec<Attribute>,
187
188    /// Attributes that will apply to this resource
189    pub attrs: Vec<Attribute>,
190
191    /// Whether this contains the `#[shared]` attribute or not
192    ///
193    /// NOTE: Always `false` in single core mode
194    pub shared: bool,
195
196    /// The type of this resource
197    pub ty: Box<Type>,
198
199    pub(crate) _extensible: (),
200}
201
202/// A software task
203#[derive(Debug)]
204pub struct SoftwareTask {
205    /// Software task metadata
206    pub args: SoftwareTaskArgs,
207
208    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
209    pub cfgs: Vec<Attribute>,
210    /// Attributes that will apply to this interrupt handler
211    pub attrs: Vec<Attribute>,
212
213    /// The context argument
214    pub context: Box<Pat>,
215    /// The inputs of this software task
216    pub inputs: Vec<PatType>,
217
218    /// Static variables local to this context
219    pub locals: Map<Local>,
220    /// The statements that make up the task handler
221    pub stmts: Vec<Stmt>,
222
223    pub(crate) _extensible: (),
224}
225
226/// Software task metadata
227#[derive(Debug)]
228pub struct SoftwareTaskArgs {
229    /// The core this task will run on
230    pub core: u8,
231
232    /// The task capacity: the maximum number of pending messages that can be queued
233    pub capacity: u8,
234
235    /// The priority of this task
236    pub priority: u8,
237
238    /// Resources that can be accessed from this context
239    pub resources: Resources,
240
241    /// Software tasks that can be spawned from this context
242    pub spawn: Set<Ident>,
243
244    /// Software tasks that can be scheduled from this context
245    pub schedule: Set<Ident>,
246
247    pub(crate) _extensible: (),
248}
249
250impl Default for SoftwareTaskArgs {
251    fn default() -> Self {
252        Self {
253            core: 0,
254            capacity: 1,
255            priority: 1,
256            resources: Resources::new(),
257            spawn: Set::new(),
258            schedule: Set::new(),
259            _extensible: (),
260        }
261    }
262}
263
264/// A hardware task
265#[derive(Debug)]
266pub struct HardwareTask {
267    /// Hardware task metadata
268    pub args: HardwareTaskArgs,
269
270    /// Attributes that will apply to this interrupt handler
271    pub attrs: Vec<Attribute>,
272
273    /// The context argument
274    pub context: Box<Pat>,
275
276    /// Static variables local to this context
277    pub locals: Map<Local>,
278    /// The statements that make up the task handler
279    pub stmts: Vec<Stmt>,
280
281    pub(crate) _extensible: (),
282}
283
284/// Hardware task metadata
285#[derive(Debug)]
286pub struct HardwareTaskArgs {
287    /// The core on which this task will be executed
288    pub core: u8,
289
290    /// The interrupt or exception that this task is bound to
291    pub binds: Ident,
292
293    /// The priority of this task
294    pub priority: u8,
295
296    /// Resources that can be accessed from this context
297    pub resources: Resources,
298
299    /// Software tasks that can be spawned from this context
300    pub spawn: Set<Ident>,
301
302    /// Software tasks that can be scheduled from this context
303    pub schedule: Set<Ident>,
304
305    pub(crate) _extensible: (),
306}
307
308/// Interrupt that could be used to dispatch software tasks
309#[derive(Debug)]
310pub struct ExternInterrupt {
311    /// Attributes that will apply to this interrupt handler
312    pub attrs: Vec<Attribute>,
313
314    pub(crate) _extensible: (),
315}
316
317/// A `static mut` variable local to and owned by a context
318#[derive(Debug)]
319pub struct Local {
320    /// Attributes like `#[link_section]`
321    pub attrs: Vec<Attribute>,
322
323    /// `#[cfg]` attributes like `#[cfg(debug_assertions)]`
324    pub cfgs: Vec<Attribute>,
325
326    /// Whether this contains the `#[shared]` attribute or not
327    ///
328    /// NOTE: Always `false` in single core mode
329    pub shared: bool,
330
331    /// Type
332    pub ty: Box<Type>,
333
334    /// Initial value
335    pub expr: Box<Expr>,
336
337    pub(crate) _extensible: (),
338}
339
340/// Resource access
341#[derive(Clone, Copy, Debug, PartialEq)]
342pub enum Access {
343    /// `[x]`
344    Exclusive,
345
346    /// `[&x]`
347    Shared,
348}
349
350impl Access {
351    /// Is this enum in the `Exclusive` variant?
352    pub fn is_exclusive(&self) -> bool {
353        *self == Access::Exclusive
354    }
355
356    /// Is this enum in the `Shared` variant?
357    pub fn is_shared(&self) -> bool {
358        *self == Access::Shared
359    }
360}
361
362/// Resource access list
363pub type Resources = Map<Access>;