leo_passes/common/replacer/
mod.rs

1// Copyright (C) 2019-2025 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use leo_ast::{
18    Block,
19    Expression,
20    ExpressionReconstructor,
21    Identifier,
22    IterationStatement,
23    NodeBuilder,
24    ProgramReconstructor,
25    Statement,
26    StatementReconstructor,
27    TypeReconstructor,
28};
29
30/// A `Replacer` applies `replacer` to all `Identifier`s in an AST.
31/// `Replacer`s are used to rename identifiers.
32/// `Replacer`s are used to interpolate function arguments.
33///
34/// All scopes are given new node IDs to avoid stale parent/children relationship between nodes.
35///
36/// TODO: should we give new IDs to everything?
37pub struct Replacer<'a, F>
38where
39    F: Fn(&Identifier) -> Expression,
40{
41    node_builder: &'a NodeBuilder,
42    replace: F,
43}
44
45impl<'a, F> Replacer<'a, F>
46where
47    F: Fn(&Identifier) -> Expression,
48{
49    pub fn new(replace: F, node_builder: &'a NodeBuilder) -> Self {
50        Self { replace, node_builder }
51    }
52}
53
54impl<F> TypeReconstructor for Replacer<'_, F> where F: Fn(&Identifier) -> Expression {}
55
56impl<F> ExpressionReconstructor for Replacer<'_, F>
57where
58    F: Fn(&Identifier) -> Expression,
59{
60    type AdditionalOutput = ();
61
62    fn reconstruct_identifier(&mut self, input: Identifier) -> (Expression, Self::AdditionalOutput) {
63        ((self.replace)(&input), Default::default())
64    }
65}
66
67impl<F> StatementReconstructor for Replacer<'_, F>
68where
69    F: Fn(&Identifier) -> Expression,
70{
71    fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) {
72        (
73            Block {
74                statements: input.statements.into_iter().map(|s| self.reconstruct_statement(s).0).collect(),
75                span: input.span,
76                id: self.node_builder.next_id(),
77            },
78            Default::default(),
79        )
80    }
81
82    fn reconstruct_iteration(&mut self, input: IterationStatement) -> (Statement, Self::AdditionalOutput) {
83        (
84            IterationStatement {
85                type_: input.type_.map(|ty| self.reconstruct_type(ty).0),
86                start: self.reconstruct_expression(input.start).0,
87                stop: self.reconstruct_expression(input.stop).0,
88                block: self.reconstruct_block(input.block).0,
89                id: self.node_builder.next_id(),
90                ..input
91            }
92            .into(),
93            Default::default(),
94        )
95    }
96}
97
98impl<F> ProgramReconstructor for Replacer<'_, F> where F: Fn(&Identifier) -> Expression {}