leo_passes/processing_async/
program.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 super::ProcessingAsyncVisitor;
18use leo_ast::{
19    AstReconstructor,
20    ConstParameter,
21    Function,
22    Input,
23    Node,
24    Output,
25    ProgramReconstructor,
26    ProgramScope,
27    Statement,
28};
29
30impl ProgramReconstructor for ProcessingAsyncVisitor<'_> {
31    /// Reconstructs a `ProgramScope` by rewriting all contained elements:
32    /// - Updates the current program context.
33    /// - Reconstructs all functions using `reconstruct_function`.
34    /// - Reconstructs structs, mappings, and constants.
35    /// - Inserts reconstructed functions, including any newly created async functions,
36    ///   placing transitions before other functions.
37    ///
38    /// This prepares the scope for further analysis or compilation, ensuring all
39    /// components have gone through transformation.
40    fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
41        // Set the current program context
42        self.current_program = input.program_id.name.name;
43
44        // Reconstruct all functions and store them temporarily. This process also populates
45        // `new_async_functions`.
46        let mut reconstructed_functions: Vec<_> =
47            input.functions.iter().map(|(name, func)| (*name, self.reconstruct_function(func.clone()))).collect();
48
49        // Now append all newly created `async` functions. This ensures transition functions still show up before all other functions.
50        reconstructed_functions.append(&mut self.new_async_functions);
51
52        ProgramScope {
53            program_id: input.program_id,
54            structs: input.structs.into_iter().map(|(id, def)| (id, self.reconstruct_struct(def))).collect(),
55            mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(),
56            functions: reconstructed_functions,
57            constructor: input.constructor,
58            consts: input
59                .consts
60                .into_iter()
61                .map(|(id, stmt)| match self.reconstruct_const(stmt) {
62                    (Statement::Const(decl), _) => (id, decl),
63                    _ => panic!("`reconstruct_const` must return `Statement::Const`"),
64                })
65                .collect(),
66            span: input.span,
67        }
68    }
69
70    fn reconstruct_function(&mut self, input: Function) -> Function {
71        self.current_function = input.name();
72
73        // Enter the scope of the function for correct symbols lookup later
74        self.in_scope(input.id(), |slf| Function {
75            annotations: input.annotations,
76            variant: input.variant,
77            identifier: input.identifier,
78            const_parameters: input
79                .const_parameters
80                .iter()
81                .map(|param| ConstParameter { type_: slf.reconstruct_type(param.type_.clone()).0, ..param.clone() })
82                .collect(),
83            input: input
84                .input
85                .iter()
86                .map(|input| Input { type_: slf.reconstruct_type(input.type_.clone()).0, ..input.clone() })
87                .collect(),
88            output: input
89                .output
90                .iter()
91                .map(|output| Output { type_: slf.reconstruct_type(output.type_.clone()).0, ..output.clone() })
92                .collect(),
93            output_type: slf.reconstruct_type(input.output_type).0,
94            block: slf.reconstruct_block(input.block).0,
95            span: input.span,
96            id: input.id,
97        })
98    }
99}