darklua_core/process/
scope_visitor.rs

1use std::collections::HashSet;
2use std::ops::DerefMut;
3
4use crate::nodes::*;
5use crate::process::utils::is_valid_identifier;
6use crate::process::{NodeProcessor, NodeVisitor};
7
8use super::utils::{identifier_permutator, Permutator};
9use super::{NodePostProcessor, NodePostVisitor};
10
11/// Defines methods to interact with the concept of lexical scoping. The struct implementing this
12/// trait should be able to keep track of identifiers when used along the ScopeVisitor.
13pub trait Scope {
14    /// This method is called when a new block is entered.
15    fn push(&mut self);
16    /// When a block is left, this method should should free all identifiers inserted in the
17    /// previous block.
18    fn pop(&mut self);
19    /// Called when entering a function block (with each parameters of the function), with the
20    /// identifiers from a generic for statement or the identifier from a numeric for loop.
21    fn insert(&mut self, identifier: &mut String);
22    /// Called when entering a function defined with a method
23    fn insert_self(&mut self);
24    /// Called when a new local variable is initialized.
25    fn insert_local(&mut self, identifier: &mut String, value: Option<&mut Expression>);
26    /// Called when a new local function is initialized.
27    fn insert_local_function(&mut self, function: &mut LocalFunctionStatement);
28}
29
30/// A visitor that can be used only with a NodeProcessor that also implements the Scope trait.
31pub struct ScopeVisitor;
32
33impl ScopeVisitor {
34    fn visit_block_without_push<T: NodeProcessor + Scope>(block: &mut Block, scope: &mut T) {
35        scope.process_block(block);
36
37        block
38            .iter_mut_statements()
39            .for_each(|statement| Self::visit_statement(statement, scope));
40
41        if let Some(last_statement) = block.mutate_last_statement() {
42            Self::visit_last_statement(last_statement, scope);
43        };
44    }
45}
46
47impl<T: NodeProcessor + Scope> NodeVisitor<T> for ScopeVisitor {
48    fn visit_block(block: &mut Block, scope: &mut T) {
49        scope.push();
50        Self::visit_block_without_push(block, scope);
51        scope.pop();
52    }
53
54    fn visit_local_assign(statement: &mut LocalAssignStatement, scope: &mut T) {
55        scope.process_local_assign_statement(statement);
56
57        statement
58            .iter_mut_values()
59            .for_each(|value| Self::visit_expression(value, scope));
60
61        for r#type in statement
62            .iter_mut_variables()
63            .filter_map(TypedIdentifier::mutate_type)
64        {
65            Self::visit_type(r#type, scope);
66        }
67
68        statement.for_each_assignment(|variable, expression| {
69            scope.insert_local(variable.mutate_name(), expression)
70        });
71    }
72
73    fn visit_function_expression(function: &mut FunctionExpression, scope: &mut T) {
74        scope.process_function_expression(function);
75
76        for r#type in function
77            .iter_mut_parameters()
78            .filter_map(TypedIdentifier::mutate_type)
79        {
80            Self::visit_type(r#type, scope);
81        }
82
83        if let Some(variadic_type) = function.mutate_variadic_type() {
84            Self::visit_function_variadic_type(variadic_type, scope);
85        }
86
87        if let Some(return_type) = function.mutate_return_type() {
88            Self::visit_function_return_type(return_type, scope);
89        }
90
91        scope.push();
92        function
93            .mutate_parameters()
94            .iter_mut()
95            .for_each(|parameter| scope.insert(parameter.mutate_name()));
96
97        scope.process_scope(function.mutate_block(), None);
98
99        Self::visit_block(function.mutate_block(), scope);
100        scope.pop();
101    }
102
103    fn visit_function_statement(statement: &mut FunctionStatement, scope: &mut T) {
104        scope.process_function_statement(statement);
105        scope.process_variable_expression(statement.mutate_function_name().mutate_identifier());
106
107        for r#type in statement
108            .iter_mut_parameters()
109            .filter_map(TypedIdentifier::mutate_type)
110        {
111            Self::visit_type(r#type, scope);
112        }
113
114        if let Some(variadic_type) = statement.mutate_variadic_type() {
115            Self::visit_function_variadic_type(variadic_type, scope);
116        }
117
118        if let Some(return_type) = statement.mutate_return_type() {
119            Self::visit_function_return_type(return_type, scope);
120        }
121
122        scope.push();
123        if statement.get_name().has_method() {
124            scope.insert_self();
125        }
126        statement
127            .mutate_parameters()
128            .iter_mut()
129            .for_each(|parameter| scope.insert(parameter.mutate_name()));
130
131        scope.process_scope(statement.mutate_block(), None);
132
133        Self::visit_block(statement.mutate_block(), scope);
134        scope.pop();
135    }
136
137    fn visit_local_function(statement: &mut LocalFunctionStatement, scope: &mut T) {
138        scope.process_local_function_statement(statement);
139
140        scope.insert_local_function(statement);
141
142        for r#type in statement
143            .iter_mut_parameters()
144            .filter_map(TypedIdentifier::mutate_type)
145        {
146            Self::visit_type(r#type, scope);
147        }
148
149        if let Some(variadic_type) = statement.mutate_variadic_type() {
150            Self::visit_function_variadic_type(variadic_type, scope);
151        }
152
153        if let Some(return_type) = statement.mutate_return_type() {
154            Self::visit_function_return_type(return_type, scope);
155        }
156
157        scope.push();
158        statement
159            .mutate_parameters()
160            .iter_mut()
161            .for_each(|parameter| scope.insert(parameter.mutate_name()));
162
163        scope.process_scope(statement.mutate_block(), None);
164
165        Self::visit_block(statement.mutate_block(), scope);
166        scope.pop();
167    }
168
169    fn visit_generic_for(statement: &mut GenericForStatement, scope: &mut T) {
170        scope.process_generic_for_statement(statement);
171
172        statement
173            .iter_mut_expressions()
174            .for_each(|expression| Self::visit_expression(expression, scope));
175
176        scope.push();
177        statement
178            .iter_mut_identifiers()
179            .for_each(|identifier| scope.insert(identifier.mutate_name()));
180
181        for r#type in statement
182            .iter_mut_identifiers()
183            .filter_map(TypedIdentifier::mutate_type)
184        {
185            Self::visit_type(r#type, scope);
186        }
187
188        scope.process_scope(statement.mutate_block(), None);
189
190        Self::visit_block(statement.mutate_block(), scope);
191        scope.pop();
192    }
193
194    fn visit_numeric_for(statement: &mut NumericForStatement, scope: &mut T) {
195        scope.process_numeric_for_statement(statement);
196
197        Self::visit_expression(statement.mutate_start(), scope);
198        Self::visit_expression(statement.mutate_end(), scope);
199
200        if let Some(step) = statement.mutate_step() {
201            Self::visit_expression(step, scope);
202        };
203
204        if let Some(r#type) = statement.mutate_identifier().mutate_type() {
205            Self::visit_type(r#type, scope);
206        }
207
208        scope.push();
209        scope.insert(statement.mutate_identifier().mutate_name());
210
211        scope.process_scope(statement.mutate_block(), None);
212
213        Self::visit_block(statement.mutate_block(), scope);
214        scope.pop();
215    }
216
217    fn visit_repeat_statement(statement: &mut RepeatStatement, scope: &mut T) {
218        scope.process_repeat_statement(statement);
219
220        scope.push();
221
222        let (block, condition) = statement.mutate_block_and_condition();
223        scope.process_scope(block, Some(condition));
224
225        Self::visit_block_without_push(statement.mutate_block(), scope);
226        Self::visit_expression(statement.mutate_condition(), scope);
227
228        scope.pop();
229    }
230}
231
232/// A visitor that can be used only with a NodeProcessor that also implements the Scope trait.
233pub struct ScopePostVisitor;
234
235impl ScopePostVisitor {
236    fn visit_block_without_push<T: NodeProcessor + NodePostProcessor + Scope>(
237        block: &mut Block,
238        scope: &mut T,
239    ) {
240        scope.process_block(block);
241
242        block
243            .iter_mut_statements()
244            .for_each(|statement| Self::visit_statement(statement, scope));
245
246        if let Some(last_statement) = block.mutate_last_statement() {
247            Self::visit_last_statement(last_statement, scope);
248        };
249        scope.process_after_block(block);
250    }
251}
252
253impl<T: NodeProcessor + NodePostProcessor + Scope> NodePostVisitor<T> for ScopePostVisitor {
254    fn visit_block(block: &mut Block, scope: &mut T) {
255        scope.push();
256        Self::visit_block_without_push(block, scope);
257        scope.pop();
258    }
259
260    fn visit_local_assign(statement: &mut LocalAssignStatement, scope: &mut T) {
261        scope.process_local_assign_statement(statement);
262
263        statement
264            .iter_mut_values()
265            .for_each(|value| Self::visit_expression(value, scope));
266
267        for r#type in statement
268            .iter_mut_variables()
269            .filter_map(TypedIdentifier::mutate_type)
270        {
271            Self::visit_type(r#type, scope);
272        }
273
274        statement.for_each_assignment(|variable, expression| {
275            scope.insert_local(variable.mutate_name(), expression)
276        });
277
278        scope.process_after_local_assign_statement(statement);
279    }
280
281    fn visit_function_expression(function: &mut FunctionExpression, scope: &mut T) {
282        scope.process_function_expression(function);
283
284        for r#type in function
285            .iter_mut_parameters()
286            .filter_map(TypedIdentifier::mutate_type)
287        {
288            Self::visit_type(r#type, scope);
289        }
290
291        if let Some(variadic_type) = function.mutate_variadic_type() {
292            Self::visit_function_variadic_type(variadic_type, scope);
293        }
294
295        if let Some(return_type) = function.mutate_return_type() {
296            Self::visit_function_return_type(return_type, scope);
297        }
298
299        scope.push();
300        function
301            .mutate_parameters()
302            .iter_mut()
303            .for_each(|parameter| scope.insert(parameter.mutate_name()));
304
305        scope.process_scope(function.mutate_block(), None);
306
307        Self::visit_block(function.mutate_block(), scope);
308        scope.pop();
309
310        scope.process_after_function_expression(function);
311    }
312
313    fn visit_function_statement(statement: &mut FunctionStatement, scope: &mut T) {
314        scope.process_function_statement(statement);
315        scope.process_variable_expression(statement.mutate_function_name().mutate_identifier());
316
317        for r#type in statement
318            .iter_mut_parameters()
319            .filter_map(TypedIdentifier::mutate_type)
320        {
321            Self::visit_type(r#type, scope);
322        }
323
324        if let Some(variadic_type) = statement.mutate_variadic_type() {
325            Self::visit_function_variadic_type(variadic_type, scope);
326        }
327
328        if let Some(return_type) = statement.mutate_return_type() {
329            Self::visit_function_return_type(return_type, scope);
330        }
331
332        scope.push();
333        if statement.get_name().has_method() {
334            scope.insert_self();
335        }
336        statement
337            .mutate_parameters()
338            .iter_mut()
339            .for_each(|parameter| scope.insert(parameter.mutate_name()));
340
341        scope.process_scope(statement.mutate_block(), None);
342
343        Self::visit_block(statement.mutate_block(), scope);
344        scope.pop();
345
346        scope.process_after_function_statement(statement);
347    }
348
349    fn visit_local_function(statement: &mut LocalFunctionStatement, scope: &mut T) {
350        scope.process_local_function_statement(statement);
351
352        scope.insert_local_function(statement);
353
354        for r#type in statement
355            .iter_mut_parameters()
356            .filter_map(TypedIdentifier::mutate_type)
357        {
358            Self::visit_type(r#type, scope);
359        }
360
361        if let Some(variadic_type) = statement.mutate_variadic_type() {
362            Self::visit_function_variadic_type(variadic_type, scope);
363        }
364
365        if let Some(return_type) = statement.mutate_return_type() {
366            Self::visit_function_return_type(return_type, scope);
367        }
368
369        scope.push();
370        statement
371            .mutate_parameters()
372            .iter_mut()
373            .for_each(|parameter| scope.insert(parameter.mutate_name()));
374
375        scope.process_scope(statement.mutate_block(), None);
376
377        Self::visit_block(statement.mutate_block(), scope);
378        scope.pop();
379
380        scope.process_after_local_function_statement(statement);
381    }
382
383    fn visit_generic_for(statement: &mut GenericForStatement, scope: &mut T) {
384        scope.process_generic_for_statement(statement);
385
386        statement
387            .iter_mut_expressions()
388            .for_each(|expression| Self::visit_expression(expression, scope));
389
390        scope.push();
391        statement
392            .iter_mut_identifiers()
393            .for_each(|identifier| scope.insert(identifier.mutate_name()));
394
395        for r#type in statement
396            .iter_mut_identifiers()
397            .filter_map(TypedIdentifier::mutate_type)
398        {
399            Self::visit_type(r#type, scope);
400        }
401
402        scope.process_scope(statement.mutate_block(), None);
403
404        Self::visit_block(statement.mutate_block(), scope);
405        scope.pop();
406
407        scope.process_after_generic_for_statement(statement);
408    }
409
410    fn visit_numeric_for(statement: &mut NumericForStatement, scope: &mut T) {
411        scope.process_numeric_for_statement(statement);
412
413        Self::visit_expression(statement.mutate_start(), scope);
414        Self::visit_expression(statement.mutate_end(), scope);
415
416        if let Some(step) = statement.mutate_step() {
417            Self::visit_expression(step, scope);
418        };
419
420        if let Some(r#type) = statement.mutate_identifier().mutate_type() {
421            Self::visit_type(r#type, scope);
422        }
423
424        scope.push();
425        scope.insert(statement.mutate_identifier().mutate_name());
426
427        scope.process_scope(statement.mutate_block(), None);
428
429        Self::visit_block(statement.mutate_block(), scope);
430        scope.pop();
431
432        scope.process_after_numeric_for_statement(statement);
433    }
434
435    fn visit_repeat_statement(statement: &mut RepeatStatement, scope: &mut T) {
436        scope.process_repeat_statement(statement);
437
438        scope.push();
439
440        let (block, condition) = statement.mutate_block_and_condition();
441        scope.process_scope(block, Some(condition));
442
443        Self::visit_block_without_push(statement.mutate_block(), scope);
444        Self::visit_expression(statement.mutate_condition(), scope);
445
446        scope.pop();
447
448        scope.process_after_repeat_statement(statement);
449    }
450}
451
452#[derive(Debug, Clone, Default)]
453pub(crate) struct IdentifierTracker {
454    identifiers: Vec<HashSet<String>>,
455}
456
457impl IdentifierTracker {
458    fn insert_identifier(&mut self, identifier: &str) {
459        if let Some(set) = self.identifiers.last_mut() {
460            set.insert(identifier.to_string());
461        } else {
462            let mut set = HashSet::new();
463            set.insert(identifier.to_string());
464            self.identifiers.push(set);
465        }
466    }
467
468    pub fn new() -> IdentifierTracker {
469        Self {
470            identifiers: Vec::new(),
471        }
472    }
473
474    pub fn is_identifier_used(&self, identifier: &str) -> bool {
475        self.identifiers.iter().any(|set| set.contains(identifier))
476    }
477
478    pub fn generate_identifier(&mut self) -> String {
479        let mut permutator = identifier_permutator();
480
481        let identifier = permutator
482            .find(|identifier| {
483                is_valid_identifier(identifier) && !self.is_identifier_used(identifier)
484            })
485            .expect("the permutator should always ultimately return a valid identifier");
486        self.insert_identifier(&identifier);
487        identifier
488    }
489
490    pub fn generate_identifier_with_prefix(&mut self, prefix: impl Into<String>) -> String {
491        let mut identifier = prefix.into();
492        if identifier.is_empty() {
493            return self.generate_identifier();
494        }
495        let initial_length = identifier.len();
496        let mut permutator = Permutator::new("012345689".chars());
497
498        while self.is_identifier_used(&identifier) {
499            identifier.truncate(initial_length);
500            let next_suffix = permutator.next().unwrap_or_else(|| "_".to_owned());
501            identifier.push_str(&next_suffix);
502        }
503        self.insert_identifier(&identifier);
504        identifier
505    }
506}
507
508impl Scope for IdentifierTracker {
509    fn push(&mut self) {
510        self.identifiers.push(HashSet::new())
511    }
512
513    fn pop(&mut self) {
514        self.identifiers.pop();
515    }
516
517    fn insert(&mut self, identifier: &mut String) {
518        self.insert_identifier(identifier);
519    }
520
521    fn insert_self(&mut self) {
522        self.insert_identifier("self");
523    }
524
525    fn insert_local(&mut self, identifier: &mut String, _value: Option<&mut Expression>) {
526        self.insert_identifier(identifier);
527    }
528
529    fn insert_local_function(&mut self, function: &mut LocalFunctionStatement) {
530        self.insert_identifier(function.mutate_identifier().get_name());
531    }
532}
533
534// implement Scope on anything that can deref into a Scope
535impl<T, U> Scope for T
536where
537    T: DerefMut<Target = U>,
538    U: Scope,
539{
540    #[inline]
541    fn push(&mut self) {
542        self.deref_mut().push()
543    }
544
545    #[inline]
546    fn pop(&mut self) {
547        self.deref_mut().pop()
548    }
549
550    #[inline]
551    fn insert(&mut self, identifier: &mut String) {
552        self.deref_mut().insert(identifier);
553    }
554
555    #[inline]
556    fn insert_self(&mut self) {
557        self.deref_mut().insert_self();
558    }
559
560    #[inline]
561    fn insert_local(&mut self, identifier: &mut String, value: Option<&mut Expression>) {
562        self.deref_mut().insert_local(identifier, value)
563    }
564
565    #[inline]
566    fn insert_local_function(&mut self, function: &mut LocalFunctionStatement) {
567        self.deref_mut().insert_local_function(function)
568    }
569}