use crate::{CompilerState, Replacer};
use indexmap::{IndexMap, IndexSet};
use itertools::Itertools;
use leo_ast::{
CallExpression,
Composite,
CompositeExpression,
CompositeType,
Expression,
Function,
Identifier,
Location,
Path,
ProgramReconstructor,
};
use leo_span::Symbol;
pub struct MonomorphizationVisitor<'a> {
pub state: &'a mut CompilerState,
pub program: Symbol,
pub function_map: IndexMap<Location, Function>,
pub composite_map: IndexMap<Location, Composite>,
pub reconstructed_functions: IndexMap<Location, Function>,
pub monomorphized_functions: IndexSet<Location>,
pub reconstructed_composites: IndexMap<Location, Composite>,
pub monomorphized_composites: IndexSet<Location>,
pub unresolved_calls: Vec<CallExpression>,
pub unresolved_composite_exprs: Vec<CompositeExpression>,
pub unresolved_composite_types: Vec<CompositeType>,
pub changed: bool,
}
impl MonomorphizationVisitor<'_> {
pub(crate) fn monomorphize_composite(&mut self, path: &Path, const_arguments: &Vec<Expression>) -> Path {
let new_composite_path = path.clone().with_updated_last_symbol(leo_span::Symbol::intern(&format!(
"{}::[{}]",
path.identifier().name,
const_arguments.iter().format(", ")
)));
if self.reconstructed_composites.get(new_composite_path.expect_global_location()).is_none() {
let composite = self
.reconstructed_composites
.get(path.expect_global_location())
.expect("Composite should already be reconstructed (post-order traversal).");
let const_param_map: IndexMap<_, _> = composite
.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 composite = replacer.reconstruct_composite(composite.clone());
composite = self.reconstruct_composite(composite);
composite.identifier =
Identifier::new(new_composite_path.identifier().name, self.state.node_builder.next_id());
composite.const_parameters = vec![];
composite.id = self.state.node_builder.next_id();
self.reconstructed_composites.insert(new_composite_path.expect_global_location().clone(), composite);
self.monomorphized_composites.insert(path.expect_global_location().clone());
}
new_composite_path
}
}