use crate::CompilerState;
use leo_ast::*;
use leo_span::{Span, Symbol, sym};
use indexmap::IndexMap;
pub struct StorageLoweringVisitor<'a> {
pub state: &'a mut CompilerState,
pub program: Symbol,
pub new_mappings: IndexMap<Symbol, Mapping>,
}
impl StorageLoweringVisitor<'_> {
pub fn generate_mapping_names_for_vector(&self, expr: &Expression) -> (Symbol, Symbol) {
let path = match expr {
Expression::Path(path) => path,
_ => panic!("Expected path expression for vector"),
};
let base_sym = path.identifier().name;
let vec_values_mapping_name = Symbol::intern(&format!("{base_sym}__"));
let vec_length_mapping_name = Symbol::intern(&format!("{base_sym}__len__"));
(vec_values_mapping_name, vec_length_mapping_name)
}
pub fn symbol_to_path_expr(&mut self, sym: Symbol) -> Expression {
Expression::Path(Path::from(Identifier::new(sym, self.state.node_builder.next_id())).into_absolute())
}
pub fn literal_false(&mut self) -> Expression {
Literal::boolean(false, Span::default(), self.state.node_builder.next_id()).into()
}
pub fn literal_zero_u32(&mut self) -> Expression {
Literal::integer(IntegerType::U32, "0".to_string(), Span::default(), self.state.node_builder.next_id()).into()
}
pub fn literal_one_u32(&mut self) -> Expression {
Literal::integer(IntegerType::U32, "1".to_string(), Span::default(), self.state.node_builder.next_id()).into()
}
pub fn get_vector_len_expr(&mut self, len_path_expr: Expression, span: Span) -> Expression {
AssociatedFunctionExpression {
variant: Identifier::new(sym::Mapping, self.state.node_builder.next_id()),
name: Identifier::new(Symbol::intern("get_or_use"), self.state.node_builder.next_id()),
type_parameters: vec![],
arguments: vec![len_path_expr, self.literal_false(), self.literal_zero_u32()],
span,
id: self.state.node_builder.next_id(),
}
.into()
}
pub fn set_mapping_expr(
&mut self,
path_expr: Expression,
key_expr: Expression,
value_expr: Expression,
span: Span,
) -> Expression {
AssociatedFunctionExpression {
variant: Identifier::new(sym::Mapping, self.state.node_builder.next_id()),
name: Identifier::new(Symbol::intern("set"), self.state.node_builder.next_id()),
type_parameters: vec![],
arguments: vec![path_expr, key_expr, value_expr],
span,
id: self.state.node_builder.next_id(),
}
.into()
}
pub fn get_mapping_expr(&mut self, path_expr: Expression, key_expr: Expression, span: Span) -> Expression {
AssociatedFunctionExpression {
variant: Identifier::new(sym::Mapping, self.state.node_builder.next_id()),
name: Identifier::new(Symbol::intern("get"), self.state.node_builder.next_id()),
type_parameters: vec![],
arguments: vec![path_expr, key_expr],
span,
id: self.state.node_builder.next_id(),
}
.into()
}
pub fn get_or_use_mapping_expr(
&mut self,
path_expr: Expression,
key_expr: Expression,
default_expr: Expression,
span: Span,
) -> Expression {
AssociatedFunctionExpression {
variant: Identifier::new(sym::Mapping, self.state.node_builder.next_id()),
name: Identifier::new(Symbol::intern("get_or_use"), self.state.node_builder.next_id()),
type_parameters: vec![],
arguments: vec![path_expr, key_expr, default_expr],
span,
id: self.state.node_builder.next_id(),
}
.into()
}
pub fn ternary_expr(
&mut self,
condition: Expression,
if_true: Expression,
if_false: Expression,
span: Span,
) -> Expression {
TernaryExpression { condition, if_true, if_false, span, id: self.state.node_builder.next_id() }.into()
}
pub fn binary_expr(&mut self, left: Expression, op: BinaryOperation, right: Expression) -> Expression {
BinaryExpression { op, left, right, span: Span::default(), id: self.state.node_builder.next_id() }.into()
}
pub fn zero(&self, ty: &Type) -> Expression {
let symbol_table = &self.state.symbol_table;
let struct_lookup = |sym: &[Symbol]| {
symbol_table
.lookup_struct(sym)
.unwrap()
.members
.iter()
.map(|mem| (mem.identifier.name, mem.type_.clone()))
.collect()
};
Expression::zero(ty, Span::default(), &self.state.node_builder, &struct_lookup)
.expect("zero value generation failed")
}
}