Skip to main content

lora_analyzer/
scope.rs

1use crate::symbols::VarId;
2use std::collections::{BTreeMap, HashMap};
3
4#[derive(Debug, Clone, Default)]
5pub struct Scope {
6    vars: HashMap<String, VarId>,
7}
8
9impl Scope {
10    pub fn new() -> Self {
11        Self {
12            vars: HashMap::new(),
13        }
14    }
15
16    pub fn declare(&mut self, name: String, id: VarId) {
17        self.vars.insert(name, id);
18    }
19
20    pub fn resolve(&self, name: &str) -> Option<VarId> {
21        self.vars.get(name).copied()
22    }
23
24    pub fn iter(&self) -> impl Iterator<Item = (&String, &VarId)> {
25        self.vars.iter()
26    }
27
28    pub fn clear(&mut self) {
29        self.vars.clear();
30    }
31
32    pub fn contains(&self, name: &str) -> bool {
33        self.vars.contains_key(name)
34    }
35}
36
37#[derive(Debug, Clone)]
38pub struct ScopeStack {
39    scopes: Vec<Scope>,
40}
41
42impl Default for ScopeStack {
43    fn default() -> Self {
44        Self::new()
45    }
46}
47
48impl ScopeStack {
49    pub fn new() -> Self {
50        Self {
51            scopes: vec![Scope::new()],
52        }
53    }
54
55    pub fn push(&mut self) {
56        self.scopes.push(Scope::new());
57    }
58
59    pub fn pop(&mut self) {
60        if self.scopes.len() > 1 {
61            self.scopes.pop();
62        } else if let Some(scope) = self.scopes.last_mut() {
63            scope.clear();
64        }
65    }
66
67    pub fn clear(&mut self) {
68        self.scopes.clear();
69        self.scopes.push(Scope::new());
70    }
71
72    pub fn declare(&mut self, name: String, id: VarId) {
73        if self.scopes.is_empty() {
74            self.scopes.push(Scope::new());
75        }
76
77        if let Some(scope) = self.scopes.last_mut() {
78            scope.declare(name, id);
79        }
80    }
81
82    pub fn resolve(&self, name: &str) -> Option<VarId> {
83        for scope in self.scopes.iter().rev() {
84            if let Some(id) = scope.resolve(name) {
85                return Some(id);
86            }
87        }
88        None
89    }
90
91    pub fn contains_in_current_scope(&self, name: &str) -> bool {
92        self.scopes
93            .last()
94            .map(|scope| scope.contains(name))
95            .unwrap_or(false)
96    }
97
98    pub fn visible_bindings(&self) -> BTreeMap<String, VarId> {
99        let mut out = BTreeMap::new();
100
101        for scope in &self.scopes {
102            for (name, id) in scope.iter() {
103                out.insert(name.clone(), *id);
104            }
105        }
106
107        out
108    }
109}