use crate::StaticSingleAssigner;
use leo_ast::{
Block, Finalize, Function, FunctionConsumer, Member, Program, ProgramConsumer, ProgramScope, ProgramScopeConsumer,
StatementConsumer, Struct, StructConsumer,
};
use leo_span::{sym, Symbol};
use indexmap::IndexMap;
impl StructConsumer for StaticSingleAssigner<'_> {
type Output = Struct;
fn consume_struct(&mut self, struct_: Struct) -> 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.push(member_map.shift_remove(&sym::gates).unwrap());
members.extend(member_map.into_iter().map(|(_, member)| member));
Struct { members, ..struct_ }
}
}
}
}
impl FunctionConsumer for StaticSingleAssigner<'_> {
type Output = Function;
fn consume_function(&mut self, function: Function) -> Self::Output {
self.push();
for input_variable in function.input.iter() {
self.rename_table
.update(input_variable.identifier().name, input_variable.identifier().name);
}
let block = Block {
span: function.block.span,
statements: self.consume_block(function.block),
};
self.pop();
let finalize = function.finalize.map(|finalize| {
self.push();
for input_variable in finalize.input.iter() {
self.rename_table
.update(input_variable.identifier().name, input_variable.identifier().name);
}
let block = Block {
span: finalize.block.span,
statements: self.consume_block(finalize.block),
};
self.pop();
Finalize {
identifier: finalize.identifier,
input: finalize.input,
output: finalize.output,
output_type: finalize.output_type,
block,
span: finalize.span,
}
});
Function {
annotations: function.annotations,
call_type: function.call_type,
identifier: function.identifier,
input: function.input,
output: function.output,
output_type: function.output_type,
block,
finalize,
span: function.span,
}
}
}
impl ProgramScopeConsumer for StaticSingleAssigner<'_> {
type Output = ProgramScope;
fn consume_program_scope(&mut self, input: ProgramScope) -> Self::Output {
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(),
span: input.span,
}
}
}
impl ProgramConsumer for StaticSingleAssigner<'_> {
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(),
program_scopes: input
.program_scopes
.into_iter()
.map(|(name, scope)| (name, self.consume_program_scope(scope)))
.collect(),
}
}
}