rtfm_syntax/
accessors.rs

1use syn::{Expr, Ident};
2
3use crate::{
4    analyze::{Analysis, Location, Priority},
5    ast::{Access, App, LateResource},
6    Context, Core, Set,
7};
8
9impl App {
10    /// Whether this `core` uses the `schedule` API
11    pub fn uses_schedule(&self, core: u8) -> bool {
12        assert!(core < self.args.cores);
13
14        self.inits
15            .get(&core)
16            .map(|init| !init.args.schedule.is_empty())
17            .unwrap_or(false)
18            || self
19                .idles
20                .get(&core)
21                .map(|idle| !idle.args.schedule.is_empty())
22                .unwrap_or(false)
23            || self
24                .hardware_tasks
25                .values()
26                .any(|task| task.args.core == core && !task.args.schedule.is_empty())
27            || self
28                .software_tasks
29                .values()
30                .any(|task| task.args.core == core && !task.args.schedule.is_empty())
31    }
32
33    /// Returns information about the resource that matches `name`
34    pub fn resource(&self, name: &Ident) -> Option<(&LateResource, Option<&Expr>)> {
35        self.late_resources
36            .get(name)
37            .map(|late| (late, None))
38            .or_else(|| {
39                self.resources
40                    .get(name)
41                    .map(|res| (&res.late, Some(&*res.expr)))
42            })
43    }
44
45    /// Returns an iterator over all *live* resources
46    pub fn resources<'a>(
47        &'a self,
48        analysis: &'a Analysis,
49    ) -> impl Iterator<Item = (&'a Ident, &'a LateResource, Option<&'a Expr>, &'a Location)> {
50        analysis.locations.iter().map(move |(name, loc)| {
51            let (res, expr) = self.resource(name).expect("UNREACHABLE");
52
53            (name, res, expr, loc)
54        })
55    }
56
57    /// Iterates over all spawn callers
58    pub fn schedule_callers<'a>(&'a self) -> impl Iterator<Item = (Context<'a>, &'a Set<Ident>)> {
59        self.inits
60            .iter()
61            .filter_map(|(&core, init)| {
62                if !init.args.schedule.is_empty() {
63                    Some((Context::Init(core), &init.args.schedule))
64                } else {
65                    None
66                }
67            })
68            .chain(self.idles.iter().filter_map(|(&core, idle)| {
69                if !idle.args.schedule.is_empty() {
70                    Some((Context::Idle(core), &idle.args.schedule))
71                } else {
72                    None
73                }
74            }))
75            .chain(self.hardware_tasks.iter().filter_map(|(name, task)| {
76                if !task.args.schedule.is_empty() {
77                    Some((Context::HardwareTask(name), &task.args.schedule))
78                } else {
79                    None
80                }
81            }))
82            .chain(self.software_tasks.iter().filter_map(|(name, task)| {
83                if !task.args.schedule.is_empty() {
84                    Some((Context::SoftwareTask(name), &task.args.schedule))
85                } else {
86                    None
87                }
88            }))
89    }
90
91    /// Iterates over all spawn callers
92    pub fn spawn_callers<'a>(&'a self) -> impl Iterator<Item = (Context<'a>, &'a Set<Ident>)> {
93        self.inits
94            .iter()
95            .filter_map(|(&core, init)| {
96                if !init.args.spawn.is_empty() {
97                    Some((Context::Init(core), &init.args.spawn))
98                } else {
99                    None
100                }
101            })
102            .chain(self.idles.iter().filter_map(|(&core, idle)| {
103                if !idle.args.spawn.is_empty() {
104                    Some((Context::Idle(core), &idle.args.spawn))
105                } else {
106                    None
107                }
108            }))
109            .chain(self.hardware_tasks.iter().filter_map(|(name, task)| {
110                if !task.args.spawn.is_empty() {
111                    Some((Context::HardwareTask(name), &task.args.spawn))
112                } else {
113                    None
114                }
115            }))
116            .chain(self.software_tasks.iter().filter_map(|(name, task)| {
117                if !task.args.spawn.is_empty() {
118                    Some((Context::SoftwareTask(name), &task.args.spawn))
119                } else {
120                    None
121                }
122            }))
123    }
124
125    pub(crate) fn resource_accesses(
126        &self,
127    ) -> impl Iterator<Item = (Core, Option<Priority>, &Ident, Access)> {
128        self.inits
129            .iter()
130            .flat_map(|(core, init)| {
131                init.args
132                    .resources
133                    .iter()
134                    .map(move |(name, access)| (*core, None, name, *access))
135            })
136            .chain(self.idles.iter().flat_map(|(core, idle)| {
137                idle.args
138                    .resources
139                    .iter()
140                    .map(move |(name, access)| (*core, Some(0), name, *access))
141            }))
142            .chain(self.hardware_tasks.values().flat_map(|task| {
143                task.args.resources.iter().map(move |(name, access)| {
144                    (task.args.core, Some(task.args.priority), name, *access)
145                })
146            }))
147            .chain(self.software_tasks.values().flat_map(|task| {
148                task.args.resources.iter().map(move |(name, access)| {
149                    (task.args.core, Some(task.args.priority), name, *access)
150                })
151            }))
152    }
153
154    pub(crate) fn schedule_calls(&self) -> impl Iterator<Item = (Core, Option<Priority>, &Ident)> {
155        self.inits
156            .iter()
157            .flat_map(|(&core, init)| {
158                init.args
159                    .schedule
160                    .iter()
161                    .map(move |task| (core, None, task))
162            })
163            .chain(self.idles.iter().flat_map(|(&core, idle)| {
164                idle.args
165                    .schedule
166                    .iter()
167                    .map(move |task| (core, Some(0), task))
168            }))
169            .chain(self.hardware_tasks.values().flat_map(|scheduler| {
170                scheduler.args.schedule.iter().map(move |schedulee| {
171                    (
172                        scheduler.args.core,
173                        Some(scheduler.args.priority),
174                        schedulee,
175                    )
176                })
177            }))
178            .chain(self.software_tasks.values().flat_map(|scheduler| {
179                scheduler.args.schedule.iter().map(move |schedulee| {
180                    (
181                        scheduler.args.core,
182                        Some(scheduler.args.priority),
183                        schedulee,
184                    )
185                })
186            }))
187    }
188
189    /// Returns an iterator over all `spawn` calls
190    ///
191    /// Each spawn call includes the core spawning the task, the priority of the spawner task and
192    /// the name of the spawnee. A task may appear more that once in this iterator.
193    ///
194    /// A priority of `None` means that this being called from `init`
195    pub(crate) fn spawn_calls(&self) -> impl Iterator<Item = (Core, Option<Priority>, &Ident)> {
196        self.inits
197            .iter()
198            .flat_map(|(&core, init)| init.args.spawn.iter().map(move |task| (core, None, task)))
199            .chain(self.idles.iter().flat_map(|(&core, idle)| {
200                idle.args
201                    .spawn
202                    .iter()
203                    .map(move |task| (core, Some(0), task))
204            }))
205            .chain(self.hardware_tasks.values().flat_map(|spawner| {
206                spawner
207                    .args
208                    .spawn
209                    .iter()
210                    .map(move |spawnee| (spawner.args.core, Some(spawner.args.priority), spawnee))
211            }))
212            .chain(self.software_tasks.values().flat_map(|spawner| {
213                spawner
214                    .args
215                    .spawn
216                    .iter()
217                    .map(move |spawnee| (spawner.args.core, Some(spawner.args.priority), spawnee))
218            }))
219    }
220
221    pub(crate) fn task_references(&self) -> impl Iterator<Item = &Ident> {
222        self.inits
223            .values()
224            .flat_map(|init| init.args.spawn.iter().chain(&init.args.schedule))
225            .chain(
226                self.idles
227                    .values()
228                    .flat_map(|idle| idle.args.spawn.iter().chain(&idle.args.schedule)),
229            )
230            .chain(
231                self.hardware_tasks
232                    .values()
233                    .flat_map(|task| task.args.spawn.iter().chain(&task.args.schedule)),
234            )
235            .chain(
236                self.software_tasks
237                    .values()
238                    .flat_map(|task| task.args.spawn.iter().chain(&task.args.schedule)),
239            )
240    }
241}