use crate::{
CompilerState,
ConstPropagation,
Monomorphization,
Pass,
SymbolTable,
SymbolTableCreation,
TypeChecking,
TypeCheckingInput,
Unrolling,
};
use leo_errors::{CompilerError, Result};
pub struct ConstPropagationAndUnrolling;
impl Pass for ConstPropagationAndUnrolling {
type Input = TypeCheckingInput;
type Output = ();
const NAME: &str = "ConstPropagationAndUnrolling";
fn do_pass(input: Self::Input, state: &mut CompilerState) -> Result<Self::Output> {
const LARGE_LOOP_BOUND: usize = 1024usize;
for _ in 0..LARGE_LOOP_BOUND {
let loop_unroll_output = Unrolling::do_pass((), state)?;
let const_prop_output = ConstPropagation::do_pass((), state)?;
let monomorphization_output = Monomorphization::do_pass((), state)?;
state.symbol_table = SymbolTable::default();
SymbolTableCreation::do_pass((), state)?;
TypeChecking::do_pass(input.clone(), state)?;
if !const_prop_output.changed && !loop_unroll_output.loop_unrolled && !monomorphization_output.changed {
if let Some(not_evaluated_span) = const_prop_output.const_not_evaluated {
return Err(CompilerError::const_not_evaluated(not_evaluated_span).into());
}
if let Some(not_evaluated_span) = const_prop_output.array_index_not_evaluated {
return Err(CompilerError::array_index_not_evaluated(not_evaluated_span).into());
}
if let Some(not_evaluated_span) = const_prop_output.repeat_count_not_evaluated {
return Err(CompilerError::repeat_count_not_evaluated(not_evaluated_span).into());
}
if let Some(not_evaluated_span) = const_prop_output.array_length_not_evaluated {
return Err(CompilerError::array_length_not_evaluated(not_evaluated_span).into());
}
for call in &monomorphization_output.unresolved_calls {
if let Some(arg) =
call.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
{
state.handler.emit_err(CompilerError::const_generic_not_resolved(
"call to generic function",
call.function.name,
arg,
call.span,
));
}
}
for expr in &monomorphization_output.unresolved_struct_exprs {
if let Some(arg) =
expr.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
{
state.handler.emit_err(CompilerError::const_generic_not_resolved(
"struct expression",
expr.name.name,
arg,
expr.span,
));
}
}
for ty in &monomorphization_output.unresolved_struct_types {
if let Some(arg) =
ty.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
{
state.handler.emit_err(CompilerError::const_generic_not_resolved(
"struct type",
ty.id.name,
arg,
ty.id.span,
));
}
}
state.handler.last_err().map_err(|e| *e)?;
if let Some(not_unrolled_span) = loop_unroll_output.loop_not_unrolled {
return Err(CompilerError::loop_bounds_not_evaluated(not_unrolled_span).into());
}
return Ok(());
}
}
Err(CompilerError::const_prop_unroll_many_loops(LARGE_LOOP_BOUND, Default::default()).into())
}
}