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}