1use super::DestructuringVisitor;
18use leo_ast::*;
19use leo_span::Symbol;
20
21use itertools::{Itertools, izip};
22
23impl AstReconstructor for DestructuringVisitor<'_> {
24 type AdditionalInput = ();
25 type AdditionalOutput = Vec<Statement>;
26
27 fn reconstruct_tuple_access(
29 &mut self,
30 input: TupleAccess,
31 _additional: &(),
32 ) -> (Expression, Self::AdditionalOutput) {
33 let Expression::Path(path) = &input.tuple else {
34 panic!("SSA guarantees that subexpressions are identifiers or literals.");
35 };
36
37 match self.tuples.get(&path.identifier().name).and_then(|tuple_names| tuple_names.get(input.index.value())) {
39 Some(id) => (Path::from(*id).into_absolute().into(), Default::default()),
40 None => {
41 if !matches!(self.state.type_table.get(&path.id), Some(Type::Future(_))) {
42 panic!("Type checking guarantees that all tuple accesses are declared and indices are valid.");
43 }
44
45 let index = Literal::integer(
46 IntegerType::U32,
47 input.index.to_string(),
48 input.span,
49 self.state.node_builder.next_id(),
50 );
51 self.state.type_table.insert(index.id(), Type::Integer(IntegerType::U32));
52
53 let expr =
54 ArrayAccess { array: path.clone().into(), index: index.into(), span: input.span, id: input.id }
55 .into();
56
57 (expr, Default::default())
58 }
59 }
60 }
61
62 fn reconstruct_ternary(
65 &mut self,
66 mut input: TernaryExpression,
67 _additional: &(),
68 ) -> (Expression, Self::AdditionalOutput) {
69 let (if_true, mut statements) = self.reconstruct_expression_tuple(std::mem::take(&mut input.if_true));
70 let (if_false, statements2) = self.reconstruct_expression_tuple(std::mem::take(&mut input.if_false));
71 statements.extend(statements2);
72
73 match (if_true, if_false) {
74 (Expression::Tuple(tuple_true), Expression::Tuple(tuple_false)) => {
75 let Some(Type::Tuple(tuple_type)) = self.state.type_table.get(&tuple_true.id()) else {
77 panic!("Should have tuple type");
78 };
79
80 let cond = if let Expression::Path(..) = input.condition {
82 input.condition
83 } else {
84 let place = Identifier::new(
85 self.state.assigner.unique_symbol("cond", "$$"),
86 self.state.node_builder.next_id(),
87 );
88
89 let definition = self.state.assigner.simple_definition(
90 place,
91 input.condition,
92 self.state.node_builder.next_id(),
93 );
94
95 statements.push(definition);
96
97 self.state.type_table.insert(place.id(), Type::Boolean);
98
99 Expression::Path(Path::from(place).into_absolute())
100 };
101
102 let mut elements = Vec::with_capacity(tuple_true.elements.len());
104
105 for (i, (lhs, rhs, ty)) in
108 izip!(tuple_true.elements, tuple_false.elements, tuple_type.elements()).enumerate()
109 {
110 let identifier = Identifier::new(
111 self.state.assigner.unique_symbol(format_args!("ternary_{i}"), "$$"),
112 self.state.node_builder.next_id(),
113 );
114
115 let expression: Expression = TernaryExpression {
116 condition: cond.clone(),
117 if_true: lhs,
118 if_false: rhs,
119 span: Default::default(),
120 id: self.state.node_builder.next_id(),
121 }
122 .into();
123
124 self.state.type_table.insert(identifier.id(), ty.clone());
125 self.state.type_table.insert(expression.id(), ty.clone());
126
127 let definition = self.state.assigner.simple_definition(
128 identifier,
129 expression,
130 self.state.node_builder.next_id(),
131 );
132
133 statements.push(definition);
134 elements.push(Path::from(identifier).into_absolute().into());
135 }
136
137 let expr: Expression =
138 TupleExpression { elements, span: Default::default(), id: self.state.node_builder.next_id() }
139 .into();
140
141 self.state.type_table.insert(expr.id(), Type::Tuple(tuple_type.clone()));
142
143 (expr, statements)
144 }
145 (if_true, if_false) => {
146 (TernaryExpression { if_true, if_false, ..input }.into(), statements)
148 }
149 }
150 }
151
152 fn reconstruct_assign(&mut self, mut assign: AssignStatement) -> (Statement, Self::AdditionalOutput) {
165 let (value, mut statements) = self.reconstruct_expression(assign.value, &());
166
167 if let Expression::Path(path) = &assign.place {
168 if let Type::Tuple(..) = self.state.type_table.get(&value.id()).expect("Expressions should have types.") {
169 let identifiers =
171 self.tuples.get(&path.identifier().name).expect("Tuple should have been encountered.");
172
173 let Expression::Path(rhs) = value else {
174 panic!("SSA should have ensured this is an identifier.");
175 };
176
177 let rhs_identifiers =
178 self.tuples.get(&rhs.identifier().name).expect("Tuple should have been encountered.");
179
180 for (&identifier, &rhs_identifier) in identifiers.iter().zip_eq(rhs_identifiers) {
182 let stmt = AssignStatement {
183 place: Path::from(identifier).into_absolute().into(),
184 value: Path::from(rhs_identifier).into_absolute().into(),
185 id: self.state.node_builder.next_id(),
186 span: Default::default(),
187 }
188 .into();
189
190 statements.push(stmt);
191 }
192
193 return (Statement::dummy(), statements);
195 }
196 }
197
198 assign.value = value;
201 let mut place = &mut assign.place;
202
203 loop {
204 match place {
206 Expression::TupleAccess(access) => {
207 let Expression::Path(path) = &access.tuple else {
209 panic!("SSA should have ensured this is an identifier.");
210 };
211
212 let tuple_ids =
213 self.tuples.get(&path.identifier().name).expect("Tuple should have been encountered.");
214
215 let identifier = tuple_ids[access.index.value()];
217
218 *place = Path::from(identifier).into_absolute().into();
219
220 return (assign.into(), statements);
221 }
222
223 Expression::ArrayAccess(access) => {
224 place = &mut access.array;
226 }
227
228 Expression::MemberAccess(access) => {
229 place = &mut access.inner;
231 }
232
233 Expression::Path(..) => {
234 return (assign.into(), statements);
236 }
237
238 _ => panic!("Type checking should have prevented this."),
239 }
240 }
241 }
242
243 fn reconstruct_block(&mut self, block: Block) -> (Block, Self::AdditionalOutput) {
244 let mut statements = Vec::with_capacity(block.statements.len());
245
246 for statement in block.statements {
248 let (reconstructed_statement, additional_statements) = self.reconstruct_statement(statement);
249 statements.extend(additional_statements);
250 if !reconstructed_statement.is_empty() {
251 statements.push(reconstructed_statement);
252 }
253 }
254
255 (Block { statements, ..block }, Default::default())
256 }
257
258 fn reconstruct_conditional(&mut self, input: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
259 let (condition, mut statements) = self.reconstruct_expression(input.condition, &());
260 let (then, statements2) = self.reconstruct_block(input.then);
261 statements.extend(statements2);
262 let otherwise = input.otherwise.map(|oth| {
263 let (expr, statements3) = self.reconstruct_statement(*oth);
264 statements.extend(statements3);
265 Box::new(expr)
266 });
267 (ConditionalStatement { condition, then, otherwise, ..input }.into(), statements)
268 }
269
270 fn reconstruct_definition(&mut self, definition: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
271 use DefinitionPlace::*;
272
273 let make_identifiers = |slf: &mut Self, single: Symbol, count: usize| -> Vec<Identifier> {
274 (0..count)
275 .map(|i| {
276 Identifier::new(
277 slf.state.assigner.unique_symbol(format_args!("{single}#tuple{i}"), "$"),
278 slf.state.node_builder.next_id(),
279 )
280 })
281 .collect()
282 };
283
284 let (value, mut statements) = self.reconstruct_expression(definition.value, &());
285 let ty = self.state.type_table.get(&value.id()).expect("Expressions should have a type.");
286 match (definition.place, value, ty) {
287 (Single(identifier), Expression::Path(rhs), Type::Tuple(tuple_type)) => {
288 let identifiers = make_identifiers(self, identifier.name, tuple_type.length());
290
291 let rhs_identifiers = self.tuples.get(&rhs.identifier().name).unwrap();
292
293 for (identifier, rhs_identifier, ty) in izip!(&identifiers, rhs_identifiers, tuple_type.elements()) {
294 let stmt = DefinitionStatement {
296 place: Single(*identifier),
297 type_: Some(ty.clone()),
298 value: Expression::Path(Path::from(*rhs_identifier).into_absolute()),
299 span: Default::default(),
300 id: self.state.node_builder.next_id(),
301 }
302 .into();
303 statements.push(stmt);
304
305 self.state.type_table.insert(identifier.id(), ty.clone());
307 }
308
309 self.tuples.insert(identifier.name, identifiers);
311 (Statement::dummy(), statements)
312 }
313 (Single(identifier), Expression::Tuple(tuple), Type::Tuple(tuple_type)) => {
314 let identifiers = make_identifiers(self, identifier.name, tuple_type.length());
316
317 for (identifier, expr, ty) in izip!(&identifiers, tuple.elements, tuple_type.elements()) {
318 let stmt = DefinitionStatement {
320 place: Single(*identifier),
321 type_: Some(ty.clone()),
322 value: expr,
323 span: Default::default(),
324 id: self.state.node_builder.next_id(),
325 }
326 .into();
327 statements.push(stmt);
328
329 self.state.type_table.insert(identifier.id(), ty.clone());
331 }
332
333 self.tuples.insert(identifier.name, identifiers);
335 (Statement::dummy(), statements)
336 }
337 (Single(identifier), rhs @ Expression::Call(..), Type::Tuple(tuple_type)) => {
338 let definition_stmt = self.assign_tuple(rhs, identifier.name);
339
340 let Statement::Definition(DefinitionStatement {
341 place: DefinitionPlace::Multiple(identifiers), ..
342 }) = &definition_stmt
343 else {
344 panic!("assign_tuple creates `Multiple`.");
345 };
346
347 self.tuples.insert(identifier.name, identifiers.clone());
349
350 for (identifier, ty) in identifiers.iter().zip(tuple_type.elements()) {
352 self.state.type_table.insert(identifier.id(), ty.clone());
353 }
354
355 (definition_stmt, statements)
356 }
357 (Multiple(identifiers), Expression::Tuple(tuple), Type::Tuple(..)) => {
358 for (identifier, expr) in identifiers.into_iter().zip_eq(tuple.elements) {
360 let stmt = DefinitionStatement {
361 place: Single(identifier),
362 type_: None,
363 value: expr,
364 span: Default::default(),
365 id: self.state.node_builder.next_id(),
366 }
367 .into();
368 statements.push(stmt);
369 }
370
371 (Statement::dummy(), statements)
373 }
374 (Multiple(identifiers), Expression::Path(rhs), Type::Tuple(..)) => {
375 let rhs_identifiers =
377 self.tuples.get(&rhs.identifier().name).expect("We should have encountered this tuple by now");
378 for (identifier, rhs_identifier) in identifiers.into_iter().zip_eq(rhs_identifiers.iter()) {
379 let stmt = DefinitionStatement {
380 place: Single(identifier),
381 type_: None,
382 value: Expression::Path(Path::from(*rhs_identifier).into_absolute()),
383 span: Default::default(),
384 id: self.state.node_builder.next_id(),
385 }
386 .into();
387 statements.push(stmt);
388 }
389
390 (Statement::dummy(), statements)
392 }
393 (m @ Multiple(..), value @ Expression::Call(..), Type::Tuple(..)) => {
394 let stmt =
396 DefinitionStatement { place: m, type_: None, value, span: definition.span, id: definition.id }
397 .into();
398 (stmt, statements)
399 }
400 (_, _, Type::Tuple(..)) => {
401 panic!("Expressions of tuple type can only be tuple literals, identifiers, or calls.");
402 }
403 (s @ Single(..), rhs, _) => {
404 let stmt = DefinitionStatement {
406 place: s,
407 type_: None,
408 value: rhs,
409 span: Default::default(),
410 id: definition.id,
411 }
412 .into();
413 (stmt, statements)
414 }
415 (Multiple(_), _, _) => panic!("A definition with multiple identifiers must have tuple type"),
416 }
417 }
418
419 fn reconstruct_iteration(&mut self, _: IterationStatement) -> (Statement, Self::AdditionalOutput) {
420 panic!("`IterationStatement`s should not be in the AST at this phase of compilation.");
421 }
422
423 fn reconstruct_return(&mut self, input: ReturnStatement) -> (Statement, Self::AdditionalOutput) {
424 let (expression, statements) = self.reconstruct_expression_tuple(input.expression);
425 (ReturnStatement { expression, ..input }.into(), statements)
426 }
427}