leo_passes/
const_prop_unroll_and_morphing.rs1use crate::{
18 CompilerState,
19 ConstPropagation,
20 Monomorphization,
21 Pass,
22 RemoveUnreachable,
23 SymbolTableCreation,
24 TypeChecking,
25 TypeCheckingInput,
26 Unrolling,
27};
28
29use leo_ast::Node;
30use leo_errors::{CompilerError, Result};
31
32pub struct ConstPropUnrollAndMorphing;
34
35impl Pass for ConstPropUnrollAndMorphing {
36 type Input = TypeCheckingInput;
37 type Output = ();
38
39 const NAME: &str = "ConstantPropogation+LoopUnrolling+Monomorphization";
40
41 fn do_pass(input: Self::Input, state: &mut CompilerState) -> Result<Self::Output> {
42 const LARGE_LOOP_BOUND: usize = 1024usize;
43
44 for _ in 0..LARGE_LOOP_BOUND {
45 let loop_unroll_output = Unrolling::do_pass((), state)?;
46
47 let const_prop_output = ConstPropagation::do_pass((), state)?;
48
49 let remove_unreachable_output = RemoveUnreachable::do_pass((), state)?;
50
51 let monomorphization_output = Monomorphization::do_pass((), state)?;
52
53 state.symbol_table.reset_but_consts();
57 SymbolTableCreation::do_pass((), state)?;
58
59 TypeChecking::do_pass(input.clone(), state)?;
62
63 if !const_prop_output.changed
64 && !loop_unroll_output.loop_unrolled
65 && !monomorphization_output.changed
66 && !remove_unreachable_output.changed
67 {
68 if let Some(not_evaluated_span) = const_prop_output.const_not_evaluated {
70 return Err(CompilerError::const_not_evaluated(not_evaluated_span).into());
71 }
72
73 if let Some(not_evaluated_span) = const_prop_output.array_index_not_evaluated {
74 return Err(CompilerError::array_index_not_evaluated(not_evaluated_span).into());
75 }
76
77 if let Some(not_evaluated_span) = const_prop_output.repeat_count_not_evaluated {
78 return Err(CompilerError::repeat_count_not_evaluated(not_evaluated_span).into());
79 }
80
81 if let Some(not_evaluated_span) = const_prop_output.array_length_not_evaluated {
82 return Err(CompilerError::array_length_not_evaluated(not_evaluated_span).into());
83 }
84
85 for call in &monomorphization_output.unresolved_calls {
87 if let Some(arg) =
88 call.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
89 {
90 state.handler.emit_err(CompilerError::const_generic_not_resolved(
91 "call to generic function",
92 call.function.clone(),
93 arg.span(),
94 ));
95 }
96 }
97
98 for expr in &monomorphization_output.unresolved_struct_exprs {
100 if let Some(arg) =
101 expr.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
102 {
103 state.handler.emit_err(CompilerError::const_generic_not_resolved(
104 "struct expression",
105 expr.path.clone(),
106 arg.span(),
107 ));
108 }
109 }
110
111 for ty in &monomorphization_output.unresolved_struct_types {
113 if let Some(arg) =
114 ty.const_arguments.iter().find(|arg| !matches!(arg, leo_ast::Expression::Literal(_)))
115 {
116 state.handler.emit_err(CompilerError::const_generic_not_resolved(
117 "struct type",
118 ty.path.clone(),
119 arg.span(),
120 ));
121 }
122 }
123
124 state.handler.last_err()?;
126
127 if let Some(not_unrolled_span) = loop_unroll_output.loop_not_unrolled {
128 return Err(CompilerError::loop_bounds_not_evaluated(not_unrolled_span).into());
129 }
130
131 return Ok(());
132 }
133 }
134
135 Err(CompilerError::const_prop_unroll_many_loops(LARGE_LOOP_BOUND, Default::default()).into())
138 }
139}