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
11pub trait Scope {
14 fn push(&mut self);
16 fn pop(&mut self);
19 fn insert(&mut self, identifier: &mut String);
22 fn insert_self(&mut self);
24 fn insert_local(&mut self, identifier: &mut String, value: Option<&mut Expression>);
26 fn insert_local_function(&mut self, function: &mut LocalFunctionStatement);
28}
29
30pub 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
232pub 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
534impl<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}