use super::SsaFormingVisitor;
use leo_ast::{
Block,
Composite,
Function,
FunctionConsumer,
Identifier,
Member,
Node as _,
Program,
ProgramConsumer,
ProgramScope,
ProgramScopeConsumer,
StatementConsumer,
StructConsumer,
};
use leo_span::{Symbol, sym};
use indexmap::IndexMap;
impl StructConsumer for SsaFormingVisitor<'_> {
type Output = Composite;
fn consume_struct(&mut self, struct_: Composite) -> Self::Output {
match struct_.is_record {
false => struct_,
true => {
let mut members = Vec::with_capacity(struct_.members.len());
let mut member_map: IndexMap<Symbol, Member> =
struct_.members.into_iter().map(|member| (member.identifier.name, member)).collect();
members.push(member_map.shift_remove(&sym::owner).unwrap());
members.extend(member_map.into_iter().map(|(_, member)| member));
Composite { members, ..struct_ }
}
}
}
}
impl FunctionConsumer for SsaFormingVisitor<'_> {
type Output = Function;
fn consume_function(&mut self, mut function: Function) -> Self::Output {
self.push();
if self.rename_defs {
for input_variable in function.input.iter_mut() {
let old_identifier = input_variable.identifier;
let new_symbol = self.state.assigner.unique_symbol(old_identifier, "$$");
let new_identifier = Identifier::new(new_symbol, self.state.node_builder.next_id());
input_variable.identifier = new_identifier;
self.state.type_table.insert(new_identifier.id(), input_variable.type_.clone());
self.rename_table.update(old_identifier.name, old_identifier.name, old_identifier.id);
self.rename_table.update(old_identifier.name, new_identifier.name, old_identifier.id);
}
}
function.block =
Block { span: function.block.span, id: function.block.id, statements: self.consume_block(function.block) };
self.pop();
function
}
}
impl ProgramScopeConsumer for SsaFormingVisitor<'_> {
type Output = ProgramScope;
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
self.program = input.program_id.name.name;
ProgramScope {
program_id: input.program_id,
structs: input.structs.into_iter().map(|(i, s)| (i, self.consume_struct(s))).collect(),
mappings: input.mappings,
functions: input.functions.into_iter().map(|(i, f)| (i, self.consume_function(f))).collect(),
consts: input.consts,
span: input.span,
}
}
}
impl ProgramConsumer for SsaFormingVisitor<'_> {
type Output = Program;
fn consume_program(&mut self, input: Program) -> Self::Output {
Program {
imports: input
.imports
.into_iter()
.map(|(name, (import, span))| (name, (self.consume_program(import), span)))
.collect(),
stubs: input.stubs,
program_scopes: input
.program_scopes
.into_iter()
.map(|(name, scope)| (name, self.consume_program_scope(scope)))
.collect(),
}
}
}