1use serde::{Deserialize, Serialize};
2
3use crate::chunk::FunctionType;
4
5#[derive(Debug, Clone)]
13pub struct Resolver {
14 stack: Vec<ResolverNode>,
15}
16
17impl Default for Resolver {
18 fn default() -> Self {
19 Self::new()
20 }
21}
22
23macro_rules! delegate_to_latest {
25 ($fn_name: ident, $ret: ty) => {
26 pub fn $fn_name(&mut self) -> $ret {
28 self.current_node().$fn_name()
29 }
30 };
31 ($fn_name: ident, $ret: ty, $param: ty) => {
32 pub fn $fn_name(&mut self, x: $param) -> $ret {
34 self.current_node().$fn_name(x)
35 }
36 };
37}
38
39impl Resolver {
40 fn current_node(&mut self) -> &mut ResolverNode {
41 self.stack.last_mut().unwrap()
42 }
43
44 delegate_to_latest!(begin_scope, ());
45 delegate_to_latest!(end_scope, usize);
46 delegate_to_latest!(is_global, bool);
47 delegate_to_latest!(mark_initialized, ());
48 delegate_to_latest!(declare_variable, bool, String);
49 delegate_to_latest!(resolve_local, Option<Option<usize>>, &str);
50
51 pub fn resolve_upvalue(&mut self, name: &str) -> Option<usize> {
55 let n = self.stack.len();
56 if n >= 3 {
57 self.recursive_resolve(name, n - 1)
59 } else {
60 None
61 }
62 }
63
64 fn recursive_resolve(&mut self, name: &str, child_index: usize) -> Option<usize> {
69 if child_index == 0 {
70 return None;
71 } let parent = self.stack.get(child_index - 1)?;
74 let mut upval_index = None;
75 for (i, local) in parent.locals.iter().enumerate() {
76 if local.name.eq(name) {
77 upval_index = Some(i);
78 break;
79 }
80 }
81
82 if let Some(index) = upval_index {
83 let child = self.stack.get_mut(child_index)?;
84 Some(child.add_upvalue(index, true))
85 } else if let Some(index) = self.recursive_resolve(name, child_index - 1) {
86 let child = self.stack.get_mut(child_index)?;
87 return Some(child.add_upvalue(index, false));
88 } else {
89 None
90 }
91 }
92
93 pub fn push(&mut self, fn_type: FunctionType) {
95 let mut locals = Vec::new();
96 let first_local = match fn_type {
97 FunctionType::Method | FunctionType::Initializer => Local {
98 name: String::from("this"),
99 depth: Some(1),
100 }, _ => Local {
102 name: String::from(""),
103 depth: None,
104 }, };
106 locals.push(first_local);
107
108 let new = ResolverNode {
109 upvalues: Vec::new(),
110 locals,
111 scope_depth: self.stack.last().unwrap().scope_depth, };
113
114 self.stack.push(new);
115 }
116
117 pub fn pop(&mut self) -> Vec<UpValue> {
119 let latest = self.stack.pop().unwrap(); latest.upvalues
121 }
122
123 pub fn new() -> Resolver {
124 let locals = vec![Local {
125 name: String::from(""),
127 depth: None,
128 }];
129
130 let top = ResolverNode {
131 upvalues: Vec::new(),
132 locals,
133 scope_depth: 0,
134 };
135
136 let stack = vec![top];
137
138 Resolver { stack }
139 }
140}
141
142#[derive(Debug, Clone)]
143struct ResolverNode {
144 upvalues: Vec<UpValue>,
145 locals: Vec<Local>,
146 scope_depth: usize,
147}
148
149impl ResolverNode {
150 pub fn begin_scope(&mut self) {
151 self.scope_depth += 1;
152 }
153
154 pub fn end_scope(&mut self) -> usize {
161 self.scope_depth -= 1;
162 let mut pops = 0;
163 for local in self.locals.iter().rev() {
164 if let Some(x) = local.depth {
165 if x > self.scope_depth {
166 pops += 1;
167 } else {
168 break;
169 }
170 }
171 }
172 for _ in 0..pops {
173 self.locals.pop();
174 }
175 pops
176 }
177
178 pub fn is_global(&self) -> bool {
179 self.scope_depth == 0
180 }
181
182 fn add_local(&mut self, name: String) {
183 let local = Local { name, depth: None };
184 self.locals.push(local);
185 }
186
187 pub fn mark_initialized(&mut self) {
190 if self.scope_depth == 0 {
191 return;
192 }
193 self.locals.last_mut().unwrap().depth = Some(self.scope_depth);
194 }
195
196 pub fn declare_variable(&mut self, str_val: String) -> bool {
203 if !self.is_global() {
204 let mut found_eq = false; for local in self.locals.iter() {
208 if let Some(x) = local.depth {
209 if x < self.scope_depth {
210 break;
211 }
212 }
213 if str_val.eq(&local.name) {
214 found_eq = true;
215 break;
216 }
217 }
218
219 self.add_local(str_val);
220 !found_eq
221 } else {
222 true
223 }
224 }
225
226 pub fn resolve_local(&self, name: &str) -> Option<Option<usize>> {
234 let mut error = false;
235 for (i, local) in self.locals.iter().enumerate() {
236 if local.name.eq(name) {
237 if local.depth.is_none() {
238 error = true;
239 break;
240 } else {
241 return Some(Some(i));
242 }
243 }
244 }
245
246 if error {
247 None
248 } else {
249 Some(None)
250 }
251 }
252
253 fn add_upvalue(&mut self, index: usize, is_local: bool) -> usize {
254 for (i, existing_upvalue) in self.upvalues.iter().enumerate() {
255 if existing_upvalue.index == index {
256 return i;
257 }
258 }
259
260 self.upvalues.push(UpValue { is_local, index });
261 self.upvalues.len() - 1
262 }
263}
264
265#[derive(Debug, Clone)]
266pub struct Local {
267 name: String,
268 depth: Option<usize>,
269}
270
271#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
274pub struct UpValue {
275 pub is_local: bool,
276 pub index: usize,
277}