leo_passes/function_inlining/
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
17//! The Function Inlining pass traverses the AST and inlines function at their call site.
18//! See https://en.wikipedia.org/wiki/Inline_expansion for more information.
19//! The pass also reorders `Function`s in a reconstructed `ProgramScope` so that they are in a post-order of the call graph.
20//! In other words, a callee function will appear before a caller function in the order.
21//!
22//! Consider the following flattened Leo code.
23//! ```leo
24//! function main(flag: u8, value: u8) -> u8 {
25//!     $var$0 = flag == 0u8;
26//!     $var$1 = foo(value);
27//!     value$2 = $var$1;
28//!     value$3 = $var$0 ? value$2 : value;
29//!     return value$3;
30//! }
31//!
32//! inline foo(x: u8) -> u8 {
33//!     $var$4 = x * x;
34//!     return $var$4;
35//! }
36//! ```
37//!
38//! The inlining pass produces the following code.
39//! ```leo
40//! inline foo(x: u8) -> u8 {
41//!     $var$4 = x * x;
42//!     return $var$4;
43//! }
44//!
45//! function main(flag: u8, value: u8) -> u8 {
46//!     $var$0 = flag == 0u8;
47//!     $var$4$5 = value * value;
48//!     $var$1 = $var$4$5;
49//!     value$2 = $var$1;
50//!     value$3 = $var$0 ? value$2 : value;
51//!     return value$3;
52//! }
53//! ```
54
55use crate::Pass;
56
57use leo_ast::ProgramReconstructor as _;
58use leo_errors::Result;
59use leo_span::Symbol;
60
61mod expression;
62
63mod program;
64
65mod statement;
66
67mod visitor;
68use visitor::*;
69
70pub struct FunctionInlining;
71
72impl Pass for FunctionInlining {
73    type Input = ();
74    type Output = ();
75
76    const NAME: &str = "FunctionInlining";
77
78    fn do_pass(_input: Self::Input, state: &mut crate::CompilerState) -> Result<Self::Output> {
79        let mut ast = std::mem::take(&mut state.ast);
80        let mut visitor = FunctionInliningVisitor {
81            state,
82            reconstructed_functions: Vec::new(),
83            program: Symbol::intern(""),
84            is_async: false,
85        };
86        ast.ast = visitor.reconstruct_program(ast.ast);
87        visitor.state.handler.last_err().map_err(|e| *e)?;
88        visitor.state.ast = ast;
89        Ok(())
90    }
91}