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>;