1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use syn::Ident;

use crate::{
    analyze::Priority,
    ast::{Access, App, Local, TaskLocal},
};

impl App {
    pub(crate) fn shared_resource_accesses(
        &self,
    ) -> impl Iterator<Item = (Option<Priority>, &Ident, Access)> {
        self.idle
            .iter()
            .flat_map(|idle| {
                idle.args
                    .shared_resources
                    .iter()
                    .map(move |(name, access)| (Some(0), name, *access))
            })
            .chain(self.hardware_tasks.values().flat_map(|task| {
                task.args
                    .shared_resources
                    .iter()
                    .map(move |(name, access)| (Some(task.args.priority), name, *access))
            }))
            .chain(self.software_tasks.values().flat_map(|task| {
                task.args
                    .shared_resources
                    .iter()
                    .map(move |(name, access)| (Some(task.args.priority), name, *access))
            }))
    }

    fn is_external(task_local: &TaskLocal) -> bool {
        match task_local {
            TaskLocal::External => true,
            _ => false,
        }
    }

    pub(crate) fn local_resource_accesses(&self) -> impl Iterator<Item = &Ident> {
        self.init
            .args
            .local_resources
            .iter()
            .filter(|(_, task_local)| Self::is_external(task_local)) // Only check the resources declared in `#[local]`
            .map(move |(name, _)| name)
            .chain(self.idle.iter().flat_map(|idle| {
                idle.args
                    .local_resources
                    .iter()
                    .filter(|(_, task_local)| Self::is_external(task_local)) // Only check the resources declared in `#[local]`
                    .map(move |(name, _)| name)
            }))
            .chain(self.hardware_tasks.values().flat_map(|task| {
                task.args
                    .local_resources
                    .iter()
                    .filter(|(_, task_local)| Self::is_external(task_local)) // Only check the resources declared in `#[local]`
                    .map(move |(name, _)| name)
            }))
            .chain(self.software_tasks.values().flat_map(|task| {
                task.args
                    .local_resources
                    .iter()
                    .filter(|(_, task_local)| Self::is_external(task_local)) // Only check the resources declared in `#[local]`
                    .map(move |(name, _)| name)
            }))
    }

    fn get_declared_local(tl: &TaskLocal) -> Option<&Local> {
        match tl {
            TaskLocal::External => None,
            TaskLocal::Declared(l) => Some(l),
        }
    }

    /// Get all declared local resources, i.e. `local = [NAME: TYPE = EXPR]`.
    ///
    /// Returns a vector of (task name, resource name, `Local` struct)
    pub fn declared_local_resources(&self) -> Vec<(&Ident, &Ident, &Local)> {
        self.init
            .args
            .local_resources
            .iter()
            .filter_map(move |(name, tl)| {
                Self::get_declared_local(tl).map(|l| (&self.init.name, name, l))
            })
            .chain(self.idle.iter().flat_map(|idle| {
                idle.args
                    .local_resources
                    .iter()
                    .filter_map(move |(name, tl)| {
                        Self::get_declared_local(tl)
                            .map(|l| (&self.idle.as_ref().unwrap().name, name, l))
                    })
            }))
            .chain(self.hardware_tasks.iter().flat_map(|(task_name, task)| {
                task.args
                    .local_resources
                    .iter()
                    .filter_map(move |(name, tl)| {
                        Self::get_declared_local(tl).map(|l| (task_name, name, l))
                    })
            }))
            .chain(self.software_tasks.iter().flat_map(|(task_name, task)| {
                task.args
                    .local_resources
                    .iter()
                    .filter_map(move |(name, tl)| {
                        Self::get_declared_local(tl).map(|l| (task_name, name, l))
                    })
            }))
            .collect()
    }
}