xee_xpath_ast/ast/
rename.rs1use ahash::{HashSet, HashSetExt};
2
3use crate::Name;
4use crate::{ast, span::WithSpan, VariableNames};
5
6use super::visitor::AstVisitor;
7
8struct UniqueNameGenerator {
9 names: HashSet<Name>,
10}
11
12impl UniqueNameGenerator {
13 fn new() -> Self {
14 UniqueNameGenerator {
15 names: HashSet::new(),
16 }
17 }
18
19 fn generate(&mut self, name: &Name) -> Name {
20 let mut name = name.clone();
21 while self.names.contains(&name) {
22 name = name.with_suffix();
23 }
24 self.names.insert(name.clone());
25 name
26 }
27}
28
29struct Names {
30 names: Vec<(Name, Name)>,
31 generator: UniqueNameGenerator,
32}
33
34impl Names {
35 fn new() -> Self {
36 Names {
37 names: Vec::new(),
38 generator: UniqueNameGenerator::new(),
39 }
40 }
41
42 fn get(&mut self, name: &Name) -> Name {
43 self.names
47 .iter()
48 .rev()
49 .find(|(old_name, _)| old_name == name)
50 .map(|(_, new_name)| new_name.clone())
51 .unwrap_or_else(|| self.generator.generate(name))
52 }
53
54 fn push_name(&mut self, name: &Name) -> Name {
55 let new_name = self.generator.generate(name);
56 self.names.push((name.clone(), new_name.clone()));
57 new_name
58 }
59
60 fn pop_name(&mut self) {
61 self.names.pop();
62 }
63}
64
65struct Renamer {
66 names: Names,
67}
68
69impl Renamer {
70 fn new() -> Self {
71 Renamer {
72 names: Names::new(),
73 }
74 }
75
76 fn push_name(&mut self, name: &Name) -> Name {
77 self.names.push_name(name)
78 }
79
80 fn pop_name(&mut self) {
81 self.names.pop_name();
82 }
83}
84
85impl AstVisitor for Renamer {
86 fn visit_let_expr(&mut self, expr: &mut ast::LetExpr) {
87 self.visit_expr_single(&mut expr.var_expr);
88 let old_span = expr.var_name.span;
89 expr.var_name = self.push_name(&expr.var_name.value).with_span(old_span);
90 self.visit_expr_single(&mut expr.return_expr);
91 self.pop_name();
92 }
93
94 fn visit_for_expr(&mut self, expr: &mut ast::ForExpr) {
95 self.visit_expr_single(&mut expr.var_expr);
96 let old_span = expr.var_name.span;
97 expr.var_name = self.push_name(&expr.var_name.value).with_span(old_span);
98 self.visit_expr_single(&mut expr.return_expr);
99 self.pop_name();
100 }
101
102 fn visit_quantified_expr(&mut self, expr: &mut ast::QuantifiedExpr) {
103 self.visit_expr_single(&mut expr.var_expr);
104 let old_span = expr.var_name.span;
105 expr.var_name = self.push_name(&expr.var_name.value).with_span(old_span);
106 self.visit_expr_single(&mut expr.satisfies_expr);
107 self.pop_name();
108 }
109
110 fn visit_inline_function(&mut self, expr: &mut ast::InlineFunction) {
111 for param in &mut expr.params {
112 param.name = self.push_name(¶m.name);
113 }
114 self.visit_expr_or_empty(&mut expr.body);
115 for _ in &expr.params {
116 self.pop_name();
117 }
118 }
119
120 fn visit_var_ref(&mut self, name: &mut Name) {
121 let new_name = self.names.get(name);
122 *name = new_name;
123 }
124}
125
126pub(crate) fn unique_names(expr: &mut ast::XPath, variable_names: &VariableNames) {
127 let mut renamer = Renamer::new();
128 for name in variable_names {
132 renamer.push_name(name);
133 }
134 renamer.visit_xpath(expr);
135}