leo_passes/loop_unrolling/
duplicate.rs1use leo_ast::{Block, ExpressionReconstructor, Statement, StatementReconstructor, *};
18
19use crate::SymbolTable;
20
21pub fn duplicate(block: Block, symbol_table: &mut SymbolTable, node_builder: &NodeBuilder) -> Block {
24 Duplicator { symbol_table, node_builder }.reconstruct_block(block).0
25}
26
27struct Duplicator<'a> {
28 symbol_table: &'a mut SymbolTable,
29 node_builder: &'a NodeBuilder,
30}
31
32impl Duplicator<'_> {
33 fn in_scope_duped<T>(&mut self, new_id: NodeID, old_id: NodeID, func: impl FnOnce(&mut Self) -> T) -> T {
34 self.symbol_table.enter_scope_duped(new_id, old_id);
35 let result = func(self);
36 self.symbol_table.enter_parent();
37 result
38 }
39}
40
41impl TypeReconstructor for Duplicator<'_> {}
42
43impl ExpressionReconstructor for Duplicator<'_> {
44 type AdditionalOutput = ();
45}
46
47impl StatementReconstructor for Duplicator<'_> {
48 fn reconstruct_statement(&mut self, input: Statement) -> (Statement, Self::AdditionalOutput) {
49 match input {
50 Statement::Block(stmt) => {
51 let (stmt, output) = self.reconstruct_block(stmt);
52 (stmt.into(), output)
53 }
54 Statement::Conditional(stmt) => self.reconstruct_conditional(stmt),
55 Statement::Iteration(stmt) => self.reconstruct_iteration(*stmt),
56 stmt => (stmt, Default::default()),
57 }
58 }
59
60 fn reconstruct_block(&mut self, mut input: Block) -> (Block, Self::AdditionalOutput) {
61 let next_id = self.node_builder.next_id();
62 self.in_scope_duped(next_id, input.id(), |slf| {
63 input.id = next_id;
64 input.statements = input.statements.into_iter().map(|stmt| slf.reconstruct_statement(stmt).0).collect();
65 (input, Default::default())
66 })
67 }
68
69 fn reconstruct_conditional(&mut self, mut input: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
70 input.then = self.reconstruct_block(input.then).0;
71 if let Some(mut otherwise) = input.otherwise {
72 *otherwise = self.reconstruct_statement(*otherwise).0;
73 input.otherwise = Some(otherwise);
74 }
75
76 (input.into(), Default::default())
77 }
78
79 fn reconstruct_iteration(&mut self, mut input: IterationStatement) -> (Statement, Self::AdditionalOutput) {
80 let next_id = self.node_builder.next_id();
81 self.in_scope_duped(next_id, input.id(), |slf| {
82 input.id = next_id;
83 input.block = slf.reconstruct_block(input.block).0;
84 (input.into(), Default::default())
85 })
86 }
87}