leo_passes/
const_propagation_and_unrolling.rs1use crate::{
18 CompilerState,
19 ConstPropagation,
20 Monomorphization,
21 Pass,
22 SymbolTable,
23 SymbolTableCreation,
24 TypeChecking,
25 TypeCheckingInput,
26 Unrolling,
27};
28
29use leo_errors::{CompilerError, Result};
30
31pub struct ConstPropagationAndUnrolling;
33
34impl Pass for ConstPropagationAndUnrolling {
35 type Input = TypeCheckingInput;
36 type Output = ();
37
38 const NAME: &str = "ConstPropagationAndUnrolling";
39
40 fn do_pass(input: Self::Input, state: &mut CompilerState) -> Result<Self::Output> {
41 const LARGE_LOOP_BOUND: usize = 1024usize;
42
43 for _ in 0..LARGE_LOOP_BOUND {
44 let loop_unroll_output = Unrolling::do_pass((), state)?;
45
46 let const_prop_output = ConstPropagation::do_pass((), state)?;
47
48 let monomorphization_output = Monomorphization::do_pass((), state)?;
49
50 state.symbol_table = SymbolTable::default();
54 SymbolTableCreation::do_pass((), state)?;
55
56 TypeChecking::do_pass(input.clone(), state)?;
59
60 if !const_prop_output.changed
61 && !loop_unroll_output.loop_unrolled
62 && !monomorphization_output.resolved_some_calls
63 {
64 if let Some(not_evaluated_span) = const_prop_output.const_not_evaluated {
66 return Err(CompilerError::const_not_evaluated(not_evaluated_span).into());
67 }
68
69 if let Some(not_evaluated_span) = const_prop_output.array_index_not_evaluated {
70 return Err(CompilerError::array_index_not_evaluated(not_evaluated_span).into());
71 }
72
73 if let Some(not_evaluated_span) = const_prop_output.repeat_count_not_evaluated {
74 return Err(CompilerError::repeat_count_not_evaluated(not_evaluated_span).into());
75 }
76
77 if let Some(not_evaluated_span) = const_prop_output.array_length_not_evaluated {
78 return Err(CompilerError::array_length_not_evaluated(not_evaluated_span).into());
79 }
80
81 for call in &monomorphization_output.unresolved_calls {
83 if let Some(arg) =
84 call.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
85 {
86 state.handler.emit_err(CompilerError::call_to_generic_function_not_resolved(
87 call.function.name,
88 arg,
89 call.span,
90 ));
91 }
92 }
93
94 state.handler.last_err().map_err(|e| *e)?;
96
97 if let Some(not_unrolled_span) = loop_unroll_output.loop_not_unrolled {
98 return Err(CompilerError::loop_bounds_not_evaluated(not_unrolled_span).into());
99 }
100
101 return Ok(());
102 }
103 }
104
105 Err(CompilerError::const_prop_unroll_many_loops(LARGE_LOOP_BOUND, Default::default()).into())
108 }
109}