Skip to main content

xee_xpath_ast/ast/
rename.rs

1use 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        // this always returns a name, even if the
44        // name is unknown, in which case a unique bogus
45        // name is generated
46        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(&param.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    // ensure we know of the outer variable names too;
129    // these are never going to be changed as there isn't
130    // any other shadowing yet at this point
131    for name in variable_names {
132        renamer.push_name(name);
133    }
134    renamer.visit_xpath(expr);
135}