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 original_loc = path.expect_global_location();
let monomorphized_name =
leo_span::Symbol::intern(&format!("{}::[{}]", path.identifier().name, const_arguments.iter().format(", ")));
let mut path_segs = Vec::with_capacity(original_loc.path.len());
path_segs.extend_from_slice(&original_loc.path[..original_loc.path.len() - 1]);
path_segs.push(monomorphized_name);
let storage_loc = Location::new(original_loc.program, path_segs);
let new_composite_path =
path.clone().with_updated_last_symbol(monomorphized_name).to_global(storage_loc.clone());
if self.reconstructed_composites.get(&storage_loc).is_none() {
let composite = self
.reconstructed_composites
.get(original_loc)
.unwrap_or_else(|| panic!("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(monomorphized_name, self.state.node_builder.next_id());
composite.const_parameters = vec![];
composite.id = self.state.node_builder.next_id();
self.reconstructed_composites.insert(storage_loc.clone(), composite);
self.monomorphized_composites.insert(original_loc.clone());
}
new_composite_path
}
}