xee_ir/
scope.rs

1#[derive(Debug)]
2pub(crate) struct Scope<N: Eq + Clone> {
3    names: Vec<N>,
4}
5
6impl<N: Eq + Clone> Scope<N> {
7    fn new() -> Self {
8        Self { names: Vec::new() }
9    }
10
11    fn get(&self, name: &N) -> Option<usize> {
12        for (i, n) in self.names.iter().enumerate().rev() {
13            if n == name {
14                return Some(i);
15            }
16        }
17        None
18    }
19
20    fn known_name(&self, name: &N) -> bool {
21        self.names.iter().any(|n| n == name)
22    }
23}
24
25#[derive(Debug, Default)]
26pub struct Scopes<N: Eq + Clone> {
27    scopes: Vec<Scope<N>>,
28}
29
30impl<N: Eq + Clone> Scopes<N> {
31    pub fn new() -> Self {
32        Self {
33            scopes: vec![Scope::new()],
34        }
35    }
36
37    pub(crate) fn push_scope(&mut self) {
38        self.scopes.push(Scope::new());
39    }
40
41    pub(crate) fn pop_scope(&mut self) {
42        self.scopes.pop();
43    }
44
45    pub(crate) fn push_name(&mut self, name: &N) {
46        self.scopes.last_mut().unwrap().names.push(name.clone());
47    }
48
49    pub(crate) fn pop_name(&mut self) {
50        self.scopes.last_mut().unwrap().names.pop();
51    }
52
53    pub(crate) fn get(&self, name: &N) -> Option<usize> {
54        self.scopes.last().unwrap().get(name)
55    }
56
57    pub(crate) fn is_closed_over_name(&self, name: &N) -> bool {
58        let mut scopes = self.scopes.iter();
59        scopes.next();
60        scopes.any(|s| s.known_name(name))
61    }
62}