leo_passes/loop_unrolling/
duplicate.rsuse leo_ast::{Block, ExpressionReconstructor, Statement, StatementReconstructor, *};
use crate::SymbolTable;
pub fn duplicate(block: Block, symbol_table: &mut SymbolTable, node_builder: &NodeBuilder) -> Block {
Duplicator { symbol_table, node_builder }.reconstruct_block(block).0
}
struct Duplicator<'a> {
symbol_table: &'a mut SymbolTable,
node_builder: &'a NodeBuilder,
}
impl Duplicator<'_> {
fn in_scope_duped<T>(&mut self, new_id: NodeID, old_id: NodeID, func: impl FnOnce(&mut Self) -> T) -> T {
self.symbol_table.enter_scope_duped(new_id, old_id);
let result = func(self);
self.symbol_table.enter_parent();
result
}
}
impl ExpressionReconstructor for Duplicator<'_> {
type AdditionalOutput = ();
}
impl StatementReconstructor for Duplicator<'_> {
fn reconstruct_statement(&mut self, input: Statement) -> (Statement, Self::AdditionalOutput) {
match input {
Statement::Block(stmt) => {
let (stmt, output) = self.reconstruct_block(stmt);
(Statement::Block(stmt), output)
}
Statement::Conditional(stmt) => self.reconstruct_conditional(stmt),
Statement::Iteration(stmt) => self.reconstruct_iteration(*stmt),
stmt => (stmt, Default::default()),
}
}
fn reconstruct_block(&mut self, mut input: Block) -> (Block, Self::AdditionalOutput) {
let next_id = self.node_builder.next_id();
self.in_scope_duped(next_id, input.id(), |slf| {
input.id = next_id;
input.statements = input.statements.into_iter().map(|stmt| slf.reconstruct_statement(stmt).0).collect();
(input, Default::default())
})
}
fn reconstruct_conditional(&mut self, mut input: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
input.then = self.reconstruct_block(input.then).0;
if let Some(mut otherwise) = input.otherwise {
*otherwise = self.reconstruct_statement(*otherwise).0;
input.otherwise = Some(otherwise);
}
(Statement::Conditional(input), Default::default())
}
fn reconstruct_iteration(&mut self, mut input: IterationStatement) -> (Statement, Self::AdditionalOutput) {
let next_id = self.node_builder.next_id();
self.in_scope_duped(next_id, input.id(), |slf| {
input.id = next_id;
input.block = slf.reconstruct_block(input.block).0;
(Statement::Iteration(Box::new(input)), Default::default())
})
}
}