use crate::{CompilerState, Replacer};
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use leo_ast::{
CallExpression,
Composite,
CompositeType,
Expression,
Function,
Identifier,
ProgramReconstructor,
StructExpression,
};
use leo_span::Symbol;
pub struct MonomorphizationVisitor<'a> {
pub state: &'a mut CompilerState,
pub program: Symbol,
pub reconstructed_functions: IndexMap<Symbol, Function>,
pub monomorphized_functions: IndexSet<Symbol>,
pub reconstructed_structs: IndexMap<Symbol, Composite>,
pub monomorphized_structs: IndexSet<Symbol>,
pub unresolved_calls: Vec<CallExpression>,
pub unresolved_struct_exprs: Vec<StructExpression>,
pub unresolved_struct_types: Vec<CompositeType>,
pub changed: bool,
}
impl MonomorphizationVisitor<'_> {
pub(crate) fn monomorphize_struct(&mut self, name: &Symbol, const_arguments: &Vec<Expression>) -> Symbol {
let new_struct_name = leo_span::Symbol::intern(&format!("{}::[{}]", name, const_arguments.iter().format(", ")));
if self.reconstructed_structs.get(&new_struct_name).is_none() {
let struct_ = self
.reconstructed_structs
.get(name)
.expect("Struct should already be reconstructed (post-order traversal).");
let const_param_map: IndexMap<_, _> =
struct_.const_parameters.iter().map(|param| param.identifier().name).zip_eq(const_arguments).collect();
let replace_identifier = |ident: &Identifier| {
const_param_map.get(&ident.name).map_or(Expression::Identifier(*ident), |&expr| expr.clone())
};
let mut replacer = Replacer::new(replace_identifier, &self.state.node_builder);
let mut struct_ = replacer.reconstruct_struct(struct_.clone());
struct_ = self.reconstruct_struct(struct_);
struct_.identifier = Identifier {
name: new_struct_name,
span: leo_span::Span::default(),
id: self.state.node_builder.next_id(),
};
struct_.const_parameters = vec![];
struct_.id = self.state.node_builder.next_id();
self.reconstructed_structs.insert(new_struct_name, struct_);
self.monomorphized_structs.insert(*name);
}
new_struct_name
}
}