leo_passes/ssa_const_propagation/
visitor.rs1use crate::CompilerState;
18
19use leo_ast::{Expression, Node, NodeID, interpreter_value::Value};
20use leo_errors::StaticAnalyzerError;
21use leo_span::{Span, Symbol};
22
23use indexmap::IndexMap;
24
25pub struct SsaConstPropagationVisitor<'a> {
27 pub state: &'a mut CompilerState,
28 pub constants: IndexMap<Symbol, Value>,
31 pub changed: bool,
33}
34
35impl SsaConstPropagationVisitor<'_> {
36 pub fn emit_err(&self, err: StaticAnalyzerError) {
38 self.state.handler.emit_err(err);
39 }
40
41 pub fn value_to_expression(&mut self, value: &Value, span: Span, id: NodeID) -> Option<(Expression, NodeID)> {
45 let ty = self.state.type_table.get(&id)?.clone();
46 let symbol_table = &self.state.symbol_table;
47 let struct_lookup = |sym: &[Symbol]| {
48 symbol_table
49 .lookup_struct(sym)
50 .unwrap()
51 .members
52 .iter()
53 .map(|mem| (mem.identifier.name, mem.type_.clone()))
54 .collect()
55 };
56 let new_expr = value.to_expression(span, &self.state.node_builder, &ty, &struct_lookup)?;
57 let new_id = new_expr.id();
58
59 self.copy_types_recursively(&new_expr, &ty);
61
62 Some((new_expr, new_id))
63 }
64
65 fn copy_types_recursively(&mut self, expr: &Expression, ty: &leo_ast::Type) {
68 use leo_ast::Type;
69
70 self.state.type_table.insert(expr.id(), ty.clone());
71
72 match (expr, ty) {
74 (Expression::Array(array_expr), Type::Array(array_ty)) => {
75 for element in &array_expr.elements {
76 self.copy_types_recursively(element, array_ty.element_type());
77 }
78 }
79 (Expression::Tuple(tuple_expr), Type::Tuple(tuple_ty)) => {
80 for (element, elem_ty) in tuple_expr.elements.iter().zip(tuple_ty.elements()) {
81 self.copy_types_recursively(element, elem_ty);
82 }
83 }
84 (Expression::Struct(struct_expr), Type::Composite(composite_ty)) => {
85 let symbols = composite_ty.path.as_symbols();
86 let member_types: Vec<leo_ast::Type> = self
87 .state
88 .symbol_table
89 .lookup_struct(&symbols)
90 .map(|struct_def| struct_def.members.iter().map(|m| m.type_.clone()).collect())
91 .unwrap_or_default();
92 for (member, member_ty) in struct_expr.members.iter().zip(member_types.iter()) {
93 if let Some(expr) = &member.expression {
94 self.copy_types_recursively(expr, member_ty);
95 }
96 }
97 }
98 _ => {
99 }
101 }
102 }
103}