@@ -40,72 +40,83 @@ impl StatementReconstructor for DestructuringVisitor<'_> {
40
40
fn reconstruct_assign ( & mut self , mut assign : AssignStatement ) -> ( Statement , Self :: AdditionalOutput ) {
41
41
let ( value, mut statements) = self . reconstruct_expression ( assign. value ) ;
42
42
43
- match assign. place {
44
- Expression :: Identifier ( identifier) => {
45
- if let Type :: Tuple ( tuple_type) =
46
- self . state . type_table . get ( & value. id ( ) ) . expect ( "Expressions should have types." )
47
- {
48
- // It's a variable of tuple type. Aleo VM doesn't know about tuples, so
49
- // we'll need to handle this.
50
- let new_symbol = self . state . assigner . unique_symbol ( identifier, "##" ) ;
51
- let new_identifier = Identifier :: new ( new_symbol, self . state . node_builder . next_id ( ) ) ;
52
- self . state . type_table . insert ( new_identifier. id ( ) , Type :: Tuple ( tuple_type. clone ( ) ) ) ;
53
-
54
- let identifiers = self . tuples . get ( & identifier. name ) . expect ( "Tuple should have been encountered." ) ;
55
-
56
- let Expression :: Identifier ( rhs) = value else {
57
- panic ! ( "SSA should have ensured this is an identifier." ) ;
58
- } ;
59
-
60
- let rhs_identifiers = self . tuples . get ( & rhs. name ) . expect ( "Tuple should have been encountered." ) ;
43
+ if let Expression :: Identifier ( identifier) = assign. place {
44
+ if let Type :: Tuple ( tuple_type) =
45
+ self . state . type_table . get ( & value. id ( ) ) . expect ( "Expressions should have types." )
46
+ {
47
+ // It's a variable of tuple type. Aleo VM doesn't know about tuples, so
48
+ // we'll need to handle this.
49
+ let new_symbol = self . state . assigner . unique_symbol ( identifier, "##" ) ;
50
+ let new_identifier = Identifier :: new ( new_symbol, self . state . node_builder . next_id ( ) ) ;
51
+ self . state . type_table . insert ( new_identifier. id ( ) , Type :: Tuple ( tuple_type. clone ( ) ) ) ;
52
+
53
+ let identifiers = self . tuples . get ( & identifier. name ) . expect ( "Tuple should have been encountered." ) ;
54
+
55
+ let Expression :: Identifier ( rhs) = value else {
56
+ panic ! ( "SSA should have ensured this is an identifier." ) ;
57
+ } ;
61
58
62
- // Again, make an assignment for each identifier.
63
- for ( identifier, rhs_identifier) in identifiers. iter ( ) . zip_eq ( rhs_identifiers) {
64
- let stmt = AssignStatement {
65
- place : ( * identifier) . into ( ) ,
66
- value : ( * rhs_identifier) . into ( ) ,
67
- id : self . state . node_builder . next_id ( ) ,
68
- span : Default :: default ( ) ,
69
- }
70
- . into ( ) ;
59
+ let rhs_identifiers = self . tuples . get ( & rhs. name ) . expect ( "Tuple should have been encountered." ) ;
71
60
72
- statements. push ( stmt) ;
61
+ // Again, make an assignment for each identifier.
62
+ for ( identifier, rhs_identifier) in identifiers. iter ( ) . zip_eq ( rhs_identifiers) {
63
+ let stmt = AssignStatement {
64
+ place : ( * identifier) . into ( ) ,
65
+ value : ( * rhs_identifier) . into ( ) ,
66
+ id : self . state . node_builder . next_id ( ) ,
67
+ span : Default :: default ( ) ,
73
68
}
69
+ . into ( ) ;
74
70
75
- ( Statement :: dummy ( ) , statements)
76
- } else {
77
- assign. value = value;
78
- ( assign. into ( ) , statements)
71
+ statements. push ( stmt) ;
79
72
}
73
+
74
+ return ( Statement :: dummy ( ) , statements) ;
80
75
}
76
+ }
81
77
82
- Expression :: TupleAccess ( access) => {
83
- // We're assigning to a tuple member. Again, Aleo VM doesn't know about tuples,
84
- // so we'll need to handle this.
85
- let Expression :: Identifier ( identifier) = & access. tuple else {
86
- panic ! ( "SSA should have ensured this is an identifier." ) ;
87
- } ;
78
+ // We may be assigning to a tuple access followed by struct or array accesses, like
79
+ // `tupl.1[2u8].mem = 5u8`
80
+ // So we need to loop and see if we find a tuple.
88
81
89
- let tuple_ids = self . tuples . get ( & identifier. name ) . expect ( "Tuple should have been encountered." ) ;
82
+ assign. value = value;
83
+ let mut place = & mut assign. place ;
90
84
91
- // This is the correspondig variable name of the member we're assigning to.
92
- let identifier = tuple_ids[ access. index . value ( ) ] ;
85
+ loop {
86
+ match place {
87
+ Expression :: TupleAccess ( access) => {
88
+ // We're assigning to a tuple member. Again, Aleo VM doesn't know about tuples,
89
+ // so we'll need to handle this.
90
+ let Expression :: Identifier ( identifier) = & access. tuple else {
91
+ panic ! ( "SSA should have ensured this is an identifier." ) ;
92
+ } ;
93
93
94
- // So just assign to the variable.
95
- let assign = AssignStatement {
96
- place : Expression :: Identifier ( identifier) ,
97
- value,
98
- span : Default :: default ( ) ,
99
- id : self . state . node_builder . next_id ( ) ,
94
+ let tuple_ids = self . tuples . get ( & identifier. name ) . expect ( "Tuple should have been encountered." ) ;
95
+
96
+ // This is the corresponding variable name of the member we're assigning to.
97
+ let identifier = tuple_ids[ access. index . value ( ) ] ;
98
+
99
+ * place = identifier. into ( ) ;
100
+
101
+ return ( assign. into ( ) , statements) ;
100
102
}
101
- . into ( ) ;
102
103
103
- ( assign, statements)
104
- }
104
+ Expression :: ArrayAccess ( access) => {
105
+ // We need to investigate the array, as maybe it's inside a tuple access, like `tupl.0[1u8]`.
106
+ place = & mut access. array ;
107
+ }
108
+
109
+ Expression :: MemberAccess ( access) => {
110
+ // We need to investigate the struct, as maybe it's inside a tuple access, like `tupl.0.mem`.
111
+ place = & mut access. inner ;
112
+ }
113
+
114
+ Expression :: Identifier ( ..) => {
115
+ // There was no tuple access, so there's nothing to do.
116
+ return ( assign. into ( ) , statements) ;
117
+ }
105
118
106
- _ => {
107
- assign. value = value;
108
- ( assign. into ( ) , statements)
119
+ _ => panic ! ( "Type checking should have prevented this." ) ,
109
120
}
110
121
}
111
122
}
0 commit comments