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 && let Type::Tuple(..) = self.state.type_table.get(&value.id()).expect("Expressions should have types.")
169 {
170 let identifiers = 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 = self.tuples.get(&rhs.identifier().name).expect("Tuple should have been encountered.");
178
179 for (&identifier, &rhs_identifier) in identifiers.iter().zip_eq(rhs_identifiers) {
181 let stmt = AssignStatement {
182 place: Path::from(identifier).into_absolute().into(),
183 value: Path::from(rhs_identifier).into_absolute().into(),
184 id: self.state.node_builder.next_id(),
185 span: Default::default(),
186 }
187 .into();
188
189 statements.push(stmt);
190 }
191
192 return (Statement::dummy(), statements);
194 }
195
196 assign.value = value;
199 let mut place = &mut assign.place;
200
201 loop {
202 match place {
204 Expression::TupleAccess(access) => {
205 let Expression::Path(path) = &access.tuple else {
207 panic!("SSA should have ensured this is an identifier.");
208 };
209
210 let tuple_ids =
211 self.tuples.get(&path.identifier().name).expect("Tuple should have been encountered.");
212
213 let identifier = tuple_ids[access.index.value()];
215
216 *place = Path::from(identifier).into_absolute().into();
217
218 return (assign.into(), statements);
219 }
220
221 Expression::ArrayAccess(access) => {
222 place = &mut access.array;
224 }
225
226 Expression::MemberAccess(access) => {
227 place = &mut access.inner;
229 }
230
231 Expression::Path(..) => {
232 return (assign.into(), statements);
234 }
235
236 _ => panic!("Type checking should have prevented this."),
237 }
238 }
239 }
240
241 fn reconstruct_block(&mut self, block: Block) -> (Block, Self::AdditionalOutput) {
242 let mut statements = Vec::with_capacity(block.statements.len());
243
244 for statement in block.statements {
246 let (reconstructed_statement, additional_statements) = self.reconstruct_statement(statement);
247 statements.extend(additional_statements);
248 if !reconstructed_statement.is_empty() {
249 statements.push(reconstructed_statement);
250 }
251 }
252
253 (Block { statements, ..block }, Default::default())
254 }
255
256 fn reconstruct_conditional(&mut self, input: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
257 let (condition, mut statements) = self.reconstruct_expression(input.condition, &());
258 let (then, statements2) = self.reconstruct_block(input.then);
259 statements.extend(statements2);
260 let otherwise = input.otherwise.map(|oth| {
261 let (expr, statements3) = self.reconstruct_statement(*oth);
262 statements.extend(statements3);
263 Box::new(expr)
264 });
265 (ConditionalStatement { condition, then, otherwise, ..input }.into(), statements)
266 }
267
268 fn reconstruct_definition(&mut self, definition: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
269 use DefinitionPlace::*;
270
271 let make_identifiers = |slf: &mut Self, single: Symbol, count: usize| -> Vec<Identifier> {
272 (0..count)
273 .map(|i| {
274 Identifier::new(
275 slf.state.assigner.unique_symbol(format_args!("{single}#tuple{i}"), "$"),
276 slf.state.node_builder.next_id(),
277 )
278 })
279 .collect()
280 };
281
282 let (value, mut statements) = self.reconstruct_expression(definition.value, &());
283 let ty = self.state.type_table.get(&value.id()).expect("Expressions should have a type.");
284 match (definition.place, value, ty) {
285 (Single(identifier), Expression::Path(rhs), Type::Tuple(tuple_type)) => {
286 let identifiers = make_identifiers(self, identifier.name, tuple_type.length());
288
289 let rhs_identifiers = self.tuples.get(&rhs.identifier().name).unwrap();
290
291 for (identifier, rhs_identifier, ty) in izip!(&identifiers, rhs_identifiers, tuple_type.elements()) {
292 let stmt = DefinitionStatement {
294 place: Single(*identifier),
295 type_: Some(ty.clone()),
296 value: Expression::Path(Path::from(*rhs_identifier).into_absolute()),
297 span: Default::default(),
298 id: self.state.node_builder.next_id(),
299 }
300 .into();
301 statements.push(stmt);
302
303 self.state.type_table.insert(identifier.id(), ty.clone());
305 }
306
307 self.tuples.insert(identifier.name, identifiers);
309 (Statement::dummy(), statements)
310 }
311 (Single(identifier), Expression::Tuple(tuple), Type::Tuple(tuple_type)) => {
312 let identifiers = make_identifiers(self, identifier.name, tuple_type.length());
314
315 for (identifier, expr, ty) in izip!(&identifiers, tuple.elements, tuple_type.elements()) {
316 let stmt = DefinitionStatement {
318 place: Single(*identifier),
319 type_: Some(ty.clone()),
320 value: expr,
321 span: Default::default(),
322 id: self.state.node_builder.next_id(),
323 }
324 .into();
325 statements.push(stmt);
326
327 self.state.type_table.insert(identifier.id(), ty.clone());
329 }
330
331 self.tuples.insert(identifier.name, identifiers);
333 (Statement::dummy(), statements)
334 }
335 (Single(identifier), rhs @ Expression::Call(..), Type::Tuple(tuple_type)) => {
336 let definition_stmt = self.assign_tuple(rhs, identifier.name);
337
338 let Statement::Definition(DefinitionStatement {
339 place: DefinitionPlace::Multiple(identifiers), ..
340 }) = &definition_stmt
341 else {
342 panic!("assign_tuple creates `Multiple`.");
343 };
344
345 self.tuples.insert(identifier.name, identifiers.clone());
347
348 for (identifier, ty) in identifiers.iter().zip(tuple_type.elements()) {
350 self.state.type_table.insert(identifier.id(), ty.clone());
351 }
352
353 (definition_stmt, statements)
354 }
355 (Multiple(identifiers), Expression::Tuple(tuple), Type::Tuple(..)) => {
356 for (identifier, expr) in identifiers.into_iter().zip_eq(tuple.elements) {
358 let stmt = DefinitionStatement {
359 place: Single(identifier),
360 type_: None,
361 value: expr,
362 span: Default::default(),
363 id: self.state.node_builder.next_id(),
364 }
365 .into();
366 statements.push(stmt);
367 }
368
369 (Statement::dummy(), statements)
371 }
372 (Multiple(identifiers), Expression::Path(rhs), Type::Tuple(..)) => {
373 let rhs_identifiers =
375 self.tuples.get(&rhs.identifier().name).expect("We should have encountered this tuple by now");
376 for (identifier, rhs_identifier) in identifiers.into_iter().zip_eq(rhs_identifiers.iter()) {
377 let stmt = DefinitionStatement {
378 place: Single(identifier),
379 type_: None,
380 value: Expression::Path(Path::from(*rhs_identifier).into_absolute()),
381 span: Default::default(),
382 id: self.state.node_builder.next_id(),
383 }
384 .into();
385 statements.push(stmt);
386 }
387
388 (Statement::dummy(), statements)
390 }
391 (m @ Multiple(..), value @ Expression::Call(..), Type::Tuple(..)) => {
392 let stmt =
394 DefinitionStatement { place: m, type_: None, value, span: definition.span, id: definition.id }
395 .into();
396 (stmt, statements)
397 }
398 (_, _, Type::Tuple(..)) => {
399 panic!("Expressions of tuple type can only be tuple literals, identifiers, or calls.");
400 }
401 (s @ Single(..), rhs, _) => {
402 let stmt = DefinitionStatement {
404 place: s,
405 type_: None,
406 value: rhs,
407 span: Default::default(),
408 id: definition.id,
409 }
410 .into();
411 (stmt, statements)
412 }
413 (Multiple(_), _, _) => panic!("A definition with multiple identifiers must have tuple type"),
414 }
415 }
416
417 fn reconstruct_iteration(&mut self, _: IterationStatement) -> (Statement, Self::AdditionalOutput) {
418 panic!("`IterationStatement`s should not be in the AST at this phase of compilation.");
419 }
420
421 fn reconstruct_return(&mut self, input: ReturnStatement) -> (Statement, Self::AdditionalOutput) {
422 let (expression, statements) = self.reconstruct_expression_tuple(input.expression);
423 (ReturnStatement { expression, ..input }.into(), statements)
424 }
425}