use crate::CompilerState;
use leo_ast::{Expression, Location, Node, NodeID, interpreter_value::Value};
use leo_errors::StaticAnalyzerError;
use leo_span::{Span, Symbol};
use indexmap::IndexMap;
pub struct SsaConstPropagationVisitor<'a> {
pub state: &'a mut CompilerState,
pub program: Symbol,
pub constants: IndexMap<Symbol, Value>,
pub changed: bool,
}
impl SsaConstPropagationVisitor<'_> {
pub fn emit_err(&self, err: StaticAnalyzerError) {
self.state.handler.emit_err(err);
}
pub fn value_to_expression(&mut self, value: &Value, span: Span, id: NodeID) -> Option<(Expression, NodeID)> {
let ty = self.state.type_table.get(&id)?.clone();
let symbol_table = &self.state.symbol_table;
let struct_lookup = |loc: &Location| {
symbol_table
.lookup_struct(self.program, loc)
.unwrap()
.members
.iter()
.map(|mem| (mem.identifier.name, mem.type_.clone()))
.collect()
};
let new_expr = value.to_expression(span, &self.state.node_builder, &ty, &struct_lookup)?;
let new_id = new_expr.id();
self.copy_types_recursively(&new_expr, &ty);
Some((new_expr, new_id))
}
fn copy_types_recursively(&mut self, expr: &Expression, ty: &leo_ast::Type) {
use leo_ast::Type;
self.state.type_table.insert(expr.id(), ty.clone());
match (expr, ty) {
(Expression::Array(array_expr), Type::Array(array_ty)) => {
for element in &array_expr.elements {
self.copy_types_recursively(element, array_ty.element_type());
}
}
(Expression::Tuple(tuple_expr), Type::Tuple(tuple_ty)) => {
for (element, elem_ty) in tuple_expr.elements.iter().zip(tuple_ty.elements()) {
self.copy_types_recursively(element, elem_ty);
}
}
(Expression::Composite(composite_expr), Type::Composite(composite_ty)) => {
let member_types: Vec<leo_ast::Type> = self
.state
.symbol_table
.lookup_struct(self.program, composite_ty.path.expect_global_location())
.map(|struct_def| struct_def.members.iter().map(|m| m.type_.clone()).collect())
.unwrap_or_default();
for (member, member_ty) in composite_expr.members.iter().zip(member_types.iter()) {
if let Some(expr) = &member.expression {
self.copy_types_recursively(expr, member_ty);
}
}
}
_ => {
}
}
}
}