program.rs
1 // Copyright (C) 2019-2025 ADnet Contributors 2 // This file is part of the ADL library. 3 4 // The ADL 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 ADL 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 ADL library. If not, see <https://www.gnu.org/licenses/>. 16 17 use super::ProcessingAsyncVisitor; 18 use adl_ast::{ 19 AstReconstructor, 20 ConstParameter, 21 Function, 22 Input, 23 Node, 24 Output, 25 ProgramReconstructor, 26 ProgramScope, 27 Statement, 28 }; 29 30 impl 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 composites, 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 composites: input.composites.into_iter().map(|(id, def)| (id, self.reconstruct_composite(def))).collect(), 55 mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(), 56 storage_variables: input 57 .storage_variables 58 .into_iter() 59 .map(|(id, storage_variable)| (id, self.reconstruct_storage_variable(storage_variable))) 60 .collect(), 61 functions: reconstructed_functions, 62 constructor: input.constructor, 63 consts: input 64 .consts 65 .into_iter() 66 .map(|(id, stmt)| match self.reconstruct_const(stmt) { 67 (Statement::Const(decl), _) => (id, decl), 68 _ => panic!("`reconstruct_const` must return `Statement::Const`"), 69 }) 70 .collect(), 71 span: input.span, 72 } 73 } 74 75 fn reconstruct_function(&mut self, input: Function) -> Function { 76 self.current_function = input.name(); 77 78 // Enter the scope of the function for correct symbols lookup later 79 self.in_scope(input.id(), |slf| Function { 80 annotations: input.annotations, 81 variant: input.variant, 82 identifier: input.identifier, 83 const_parameters: input 84 .const_parameters 85 .iter() 86 .map(|param| ConstParameter { type_: slf.reconstruct_type(param.type_.clone()).0, ..param.clone() }) 87 .collect(), 88 input: input 89 .input 90 .iter() 91 .map(|input| Input { type_: slf.reconstruct_type(input.type_.clone()).0, ..input.clone() }) 92 .collect(), 93 output: input 94 .output 95 .iter() 96 .map(|output| Output { type_: slf.reconstruct_type(output.type_.clone()).0, ..output.clone() }) 97 .collect(), 98 output_type: slf.reconstruct_type(input.output_type).0, 99 block: slf.reconstruct_block(input.block).0, 100 span: input.span, 101 id: input.id, 102 }) 103 } 104 }