leo_passes/const_propagation/
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 crate::Pass;
18
19use leo_ast::ProgramReconstructor as _;
20use leo_errors::Result;
21use leo_span::{Span, Symbol};
22
23mod expression;
24
25mod program;
26
27mod statement;
28
29mod type_;
30
31mod visitor;
32use visitor::*;
33
34pub struct ConstPropagationOutput {
35    /// Something about the program was actually changed during the pass.
36    pub changed: bool,
37    /// A const declaration whose RHS was not able to be evaluated.
38    pub const_not_evaluated: Option<Span>,
39    /// An array index which was not able to be evaluated.
40    pub array_index_not_evaluated: Option<Span>,
41    /// An array length which was not able to be evaluated.
42    pub array_length_not_evaluated: Option<Span>,
43    /// A repeat expression count which was not able to be evaluated.
44    pub repeat_count_not_evaluated: Option<Span>,
45}
46
47/// A pass to perform const propagation and folding.
48///
49/// This pass should be used in conjunction with the Unroller so that
50/// loop bounds and consts in loop bodies can be evaluated.
51///
52/// Any of these expressions:
53/// 1. unary operation,
54/// 2. binary operation,
55/// 3. core functions other than cheat codes, mapping ops, or rand functions,
56///
57/// whose arguments are consts or literals will be subject to constant folding.
58/// The ternary conditional operator will also be folded if its condition is
59/// a constant or literal.
60///
61/// This includes the LHS of assignment statements which include array indices.
62pub struct ConstPropagation;
63
64impl Pass for ConstPropagation {
65    type Input = ();
66    type Output = ConstPropagationOutput;
67
68    const NAME: &str = "ConstPropagation";
69
70    fn do_pass(_input: Self::Input, state: &mut crate::CompilerState) -> Result<Self::Output> {
71        let mut ast = std::mem::take(&mut state.ast);
72        let mut visitor = ConstPropagationVisitor {
73            state,
74            program: Symbol::intern(""),
75            changed: false,
76            const_not_evaluated: None,
77            array_index_not_evaluated: None,
78            array_length_not_evaluated: None,
79            repeat_count_not_evaluated: None,
80        };
81        ast.ast = visitor.reconstruct_program(ast.ast);
82        visitor.state.handler.last_err().map_err(|e| *e)?;
83        visitor.state.ast = ast;
84        Ok(ConstPropagationOutput {
85            changed: visitor.changed,
86            const_not_evaluated: visitor.const_not_evaluated,
87            array_index_not_evaluated: visitor.array_index_not_evaluated,
88            array_length_not_evaluated: visitor.array_length_not_evaluated,
89            repeat_count_not_evaluated: visitor.repeat_count_not_evaluated,
90        })
91    }
92}