use crate::{CompilerState, Replacer};
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use leo_ast::{
CallExpression,
Composite,
CompositeType,
Expression,
Function,
Identifier,
Path,
ProgramReconstructor,
StructExpression,
};
use leo_span::Symbol;
pub struct MonomorphizationVisitor<'a> {
pub state: &'a mut CompilerState,
pub program: Symbol,
pub function_map: IndexMap<Vec<Symbol>, Function>,
pub struct_map: IndexMap<Vec<Symbol>, Composite>,
pub reconstructed_functions: IndexMap<Vec<Symbol>, Function>,
pub monomorphized_functions: IndexSet<Vec<Symbol>>,
pub reconstructed_structs: IndexMap<Vec<Symbol>, Composite>,
pub monomorphized_structs: IndexSet<Vec<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, path: &Path, const_arguments: &Vec<Expression>) -> Path {
let new_struct_path = path.clone().with_updated_last_symbol(leo_span::Symbol::intern(&format!(
"{}::[{}]",
path.identifier().name,
const_arguments.iter().format(", ")
)));
if self.reconstructed_structs.get(&new_struct_path.absolute_path()).is_none() {
let full_name = path.absolute_path();
let struct_ = self
.reconstructed_structs
.get(&full_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_path = |expr: &Expression| match expr {
Expression::Path(path) => const_param_map
.get(&path.identifier().name)
.map_or(Expression::Path(path.clone()), |&expr| expr.clone()),
_ => expr.clone(),
};
let mut replacer = Replacer::new(replace_path, true , self.state);
let mut struct_ = replacer.reconstruct_struct(struct_.clone());
struct_ = self.reconstruct_struct(struct_);
struct_.identifier = Identifier::new(new_struct_path.identifier().name, self.state.node_builder.next_id());
struct_.const_parameters = vec![];
struct_.id = self.state.node_builder.next_id();
self.reconstructed_structs.insert(new_struct_path.absolute_path(), struct_);
self.monomorphized_structs.insert(full_name);
}
new_struct_path
}
}