leo_passes/destructuring/
visitor.rs1use crate::CompilerState;
18
19use leo_ast::{
20 DefinitionPlace,
21 DefinitionStatement,
22 Expression,
23 ExpressionReconstructor as _,
24 Identifier,
25 Node as _,
26 Statement,
27 TupleExpression,
28 Type,
29 TypeReconstructor,
30};
31use leo_span::Symbol;
32
33use indexmap::IndexMap;
34
35pub struct DestructuringVisitor<'a> {
36 pub state: &'a mut CompilerState,
37 pub tuples: IndexMap<Symbol, Vec<Identifier>>,
39 pub is_async: bool,
41}
42
43impl DestructuringVisitor<'_> {
44 pub fn reconstruct_expression_tuple(&mut self, expression: Expression) -> (Expression, Vec<Statement>) {
47 let Type::Tuple(tuple_type) =
48 self.state.type_table.get(&expression.id()).expect("Expressions should have types.")
49 else {
50 return self.reconstruct_expression(expression);
52 };
53
54 let (new_expression, mut statements) = self.reconstruct_expression(expression);
55
56 match new_expression {
57 Expression::Identifier(identifier) => {
58 let identifiers = self.tuples.get(&identifier.name).expect("Tuples should have been found");
60 let elements: Vec<Expression> =
61 identifiers.iter().map(|identifier| Expression::Identifier(*identifier)).collect();
62
63 let tuple: Expression =
64 TupleExpression { elements, span: Default::default(), id: self.state.node_builder.next_id() }
65 .into();
66
67 self.state.type_table.insert(tuple.id(), Type::Tuple(tuple_type.clone()));
68
69 (tuple, statements)
70 }
71
72 tuple @ Expression::Tuple(..) => {
73 (tuple, statements)
75 }
76
77 expr @ Expression::Call(..) => {
78 let definition_stmt = self.assign_tuple(expr, Symbol::intern("destructure"));
80 let Statement::Definition(DefinitionStatement {
81 place: DefinitionPlace::Multiple(identifiers), ..
82 }) = &definition_stmt
83 else {
84 panic!("`assign_tuple` always creates a definition with `Multiple`");
85 };
86
87 let elements = identifiers.iter().map(|identifier| Expression::Identifier(*identifier)).collect();
88
89 let expr = Expression::Tuple(TupleExpression {
90 elements,
91 span: Default::default(),
92 id: self.state.node_builder.next_id(),
93 });
94
95 self.state.type_table.insert(expr.id(), Type::Tuple(tuple_type.clone()));
96
97 statements.push(definition_stmt);
98
99 (expr, statements)
100 }
101
102 _ => panic!("Tuples may only be identifiers, tuple literals, or calls."),
103 }
104 }
105
106 pub fn assign_tuple(&mut self, expression: Expression, name: Symbol) -> Statement {
110 let Type::Tuple(tuple_type) =
111 self.state.type_table.get(&expression.id()).expect("Expressions should have types.")
112 else {
113 panic!("assign_tuple should only be called for tuple types.");
114 };
115
116 let new_identifiers: Vec<Identifier> = (0..tuple_type.length())
117 .map(|i| {
118 let new_symbol = self.state.assigner.unique_symbol(name, format_args!("#{i}#"));
119 Identifier::new(new_symbol, self.state.node_builder.next_id())
120 })
121 .collect();
122
123 Statement::Definition(DefinitionStatement {
124 place: DefinitionPlace::Multiple(new_identifiers),
125 type_: Some(Type::Tuple(tuple_type.clone())),
126 value: expression,
127 span: Default::default(),
128 id: self.state.node_builder.next_id(),
129 })
130 }
131}
132
133impl TypeReconstructor for DestructuringVisitor<'_> {}