[rust] Support destructuring
Adds a `Destructure` instruction closely following the design of the TS-based compiler. The main change is fairly small: the TS compiler doesn't support rest spreads that are not identifiers, such as the `...y[]` in `const [x, ...[y]] = z`. I added support for this in the Rust compiler.
Joe Savona committed
Aug 11, 2023 at 15:13 UTC
a49335f72a84a76ac7b39f1e6b3a7701bd6e53f7
21 files changed
+781
-333
compiler/forget/crates/forget_build_hir/src/build.rs
+151
-8
@@ -2,14 +2,15 @@ use std::collections::HashSet;
2
3
use forget_diagnostics::Diagnostic;
4
use forget_estree::{
5
- AssignmentTarget, BlockStatement, Expression, ExpressionOrSpread, ExpressionOrSuper, ForInit,
6
- Function, IntoFunction, JsValue, Pattern, Statement, VariableDeclaration,
7
- VariableDeclarationKind,
5
+ AssignmentPropertyOrRestElement, AssignmentTarget, BlockStatement, Expression,
6
+ ExpressionOrSpread, ExpressionOrSuper, ForInit, Function, IntoFunction, JsValue, Pattern,
7
+ Statement, VariableDeclaration, VariableDeclarationKind,
8
};
9
use forget_hir::{
10
- BlockKind, BranchTerminal, Environment, ForTerminal, GotoKind, IdentifierOperand,
11
- InstructionKind, InstructionValue, JSXAttribute, JSXElement, LValue, LoadGlobal, LoadLocal,
12
- PlaceOrSpread, TerminalValue,
10
+ ArrayDestructureItem, BlockKind, BranchTerminal, Destructure, DestructurePattern, Environment,
11
+ ForTerminal, GotoKind, Identifier, IdentifierOperand, InstructionKind, InstructionValue,
12
+ JSXAttribute, JSXElement, LValue, LoadGlobal, LoadLocal, ObjectDestructureItem,
13
+ ObjectDestructureProperty, PlaceOrSpread, TerminalValue,
14
};
15
16
use crate::builder::{Builder, LoopScope};
@@ -303,8 +304,8 @@ fn lower_variable_declaration(
304
}
305
}
306
_ => {
306
- return Err(Diagnostic::todo(
307
- "Handle non-identifier variable declarations",
307
+ return Err(Diagnostic::invalid_syntax(
308
+ "Expected an identifier for variable declaration without an intializer. Destructuring requires an initial value",
309
declaration.range,
310
));
311
}
@@ -543,6 +544,7 @@ fn lower_assignment(
544
})
545
}
546
547
+// TODO: change the success type to void, no caller uses it
548
fn lower_assignment_pattern(
549
env: &Environment,
550
builder: &mut Builder,
@@ -558,6 +560,147 @@ fn lower_assignment_pattern(
560
value,
561
}))
562
}
563
+ Pattern::ArrayPattern(lvalue) => {
564
+ let mut items = Vec::with_capacity(lvalue.elements.len());
565
+ let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
566
+ for element in &lvalue.elements {
567
+ match element {
568
+ None => items.push(ArrayDestructureItem::Hole),
569
+ Some(Pattern::Identifier(element)) => {
570
+ let identifier =
571
+ lower_identifier_for_assignment(env, builder, kind, &element)?;
572
+ items.push(ArrayDestructureItem::Value(identifier));
573
+ }
574
+ Some(Pattern::RestElement(element)) => {
575
+ if let Pattern::Identifier(element) = &element.argument {
576
+ let identifier = lower_identifier_for_assignment(
577
+ env,
578
+ builder,
579
+ kind,
580
+ element.as_ref(),
581
+ )?;
582
+ items.push(ArrayDestructureItem::Spread(identifier));
583
+ } else {
584
+ let temporary = env.new_temporary();
585
+ items.push(ArrayDestructureItem::Spread(IdentifierOperand {
586
+ identifier: temporary.clone(),
587
+ effect: None,
588
+ }));
589
+ followups.push((temporary, &element.argument));
590
+ }
591
+ }
592
+ Some(element) => {
593
+ let temporary = env.new_temporary();
594
+ items.push(ArrayDestructureItem::Value(IdentifierOperand {
595
+ identifier: temporary.clone(),
596
+ effect: None,
597
+ }));
598
+ followups.push((temporary, element));
599
+ }
600
+ }
601
+ }
602
+ let temporary = builder.push(InstructionValue::Destructure(Destructure {
603
+ kind,
604
+ pattern: DestructurePattern::Array(items),
605
+ value,
606
+ }));
607
+ for (temporary, pattern) in followups {
608
+ lower_assignment_pattern(
609
+ env,
610
+ builder,
611
+ kind,
612
+ pattern,
613
+ IdentifierOperand {
614
+ identifier: temporary,
615
+ effect: None,
616
+ },
617
+ )?;
618
+ }
619
+ temporary
620
+ }
621
+ Pattern::ObjectPattern(lvalue) => {
622
+ let mut properties = Vec::with_capacity(lvalue.properties.len());
623
+ let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
624
+
625
+ for property in &lvalue.properties {
626
+ match property {
627
+ AssignmentPropertyOrRestElement::RestElement(property) => {
628
+ if let Pattern::Identifier(element) = &property.argument {
629
+ let identifier = lower_identifier_for_assignment(
630
+ env,
631
+ builder,
632
+ kind,
633
+ element.as_ref(),
634
+ )?;
635
+ properties.push(ObjectDestructureItem::Spread(identifier));
636
+ } else {
637
+ let temporary = env.new_temporary();
638
+ properties.push(ObjectDestructureItem::Spread(IdentifierOperand {
639
+ identifier: temporary.clone(),
640
+ effect: None,
641
+ }));
642
+ followups.push((temporary, &property.argument));
643
+ }
644
+ }
645
+ AssignmentPropertyOrRestElement::AssignmentProperty(property) => {
646
+ if property.is_computed {
647
+ return Err(Diagnostic::todo(
648
+ "Handle computed properties in ObjectPattern",
649
+ property.range,
650
+ ));
651
+ }
652
+ let key = if let Expression::Identifier(key) = &property.key {
653
+ key.name.as_str()
654
+ } else {
655
+ return Err(Diagnostic::todo(
656
+ "Support non-identifier object keys in non-computed ObjectPattern",
657
+ property.range,
658
+ ));
659
+ };
660
+ if let Pattern::Identifier(value) = &property.value {
661
+ let value = lower_identifier_for_assignment(env, builder, kind, value)?;
662
+ properties.push(ObjectDestructureItem::Property(
663
+ ObjectDestructureProperty {
664
+ name: key.to_string(),
665
+ value,
666
+ },
667
+ ));
668
+ } else {
669
+ let temporary = env.new_temporary();
670
+ properties.push(ObjectDestructureItem::Property(
671
+ ObjectDestructureProperty {
672
+ name: key.to_string(),
673
+ value: IdentifierOperand {
674
+ identifier: temporary.clone(),
675
+ effect: None,
676
+ },
677
+ },
678
+ ));
679
+ followups.push((temporary, &property.value));
680
+ }
681
+ }
682
+ }
683
+ }
684
+
685
+ let temporary = builder.push(InstructionValue::Destructure(Destructure {
686
+ kind,
687
+ pattern: DestructurePattern::Object(properties),
688
+ value,
689
+ }));
690
+ for (temporary, pattern) in followups {
691
+ lower_assignment_pattern(
692
+ env,
693
+ builder,
694
+ kind,
695
+ pattern,
696
+ IdentifierOperand {
697
+ identifier: temporary,
698
+ effect: None,
699
+ },
700
+ )?;
701
+ }
702
+ temporary
703
+ }
704
_ => todo!("lower assignment pattern for {:#?}", lvalue),
705
})
706
}
compiler/forget/crates/forget_fixtures/tests/fixtures/destructure-array.js
new
+5
@@ -0,0 +1,5 @@
1
+function Component(a, b) {
2
+ const [c, , ...d] = a;
3
+ const [[[e]], ...[f]] = b;
4
+ return [c, d, e, f];
5
+}
compiler/forget/crates/forget_fixtures/tests/fixtures/destructure-object.js
new
+15
@@ -0,0 +1,15 @@
1
+function Component(a, b) {
2
+ const {
3
+ c,
4
+ d,
5
+ e: { e },
6
+ f: { _f: f },
7
+ g: {
8
+ g: {
9
+ g: { g, ...h },
10
+ },
11
+ },
12
+ ...i
13
+ } = a;
14
+ return [c, d, e, f, g, h, i];
15
+}
compiler/forget/crates/forget_fixtures/tests/fixtures_test.rs
+1
@@ -38,6 +38,7 @@ fn fixtures() {
38
match build(&environment, &fun.function) {
39
Ok(mut fun) => {
40
println!("ok build");
41
+ fun.debug();
42
enter_ssa(&environment, &mut fun).unwrap();
43
println!("ok enter_ssa");
44
eliminate_redundant_phis(&environment, &mut fun);
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@constant-propagation-constant-if-condition.js.snap
+70
-26
@@ -45,29 +45,73 @@ function Component(
45
)
46
entry bb0
47
bb0 (block)
48
- [0] unknown $0 = 1
49
- [1] unknown $2 = StoreLocal Let unknown a$39 = unknown $0
50
- [2] unknown $4 = DeclareLocal Let unknown b$40
51
- [3] unknown $9 = 1
52
- [4] unknown $10 = 1
53
- [5] unknown $11 = true
54
- [6] unknown $5 = true
55
- [7] unknown $6 = StoreLocal Reassign unknown b$41 = unknown $5
56
- [8] unknown $13 = DeclareLocal Let unknown c$43
57
- [9] unknown $18 = true
58
- [10] unknown $14 = "hello"
59
- [11] unknown $15 = StoreLocal Reassign unknown c$45 = unknown $14
60
- [12] unknown $20 = DeclareLocal Let unknown d$47
61
- [13] unknown $25 = "hello"
62
- [14] unknown $26 = "hello"
63
- [15] unknown $27 = true
64
- [16] unknown $21 = 42
65
- [17] unknown $22 = StoreLocal Reassign unknown d$49 = unknown $21
66
- [18] unknown $29 = DeclareLocal Let unknown e$51
67
- [19] unknown $34 = 42
68
- [20] unknown $35 = 42
69
- [21] unknown $36 = true
70
- [22] unknown $30 = "ok"
71
- [23] unknown $31 = StoreLocal Reassign unknown e$53 = unknown $30
72
- [24] unknown $37 = "ok"
73
- [25] Return unknown $37
48
+ [0] unknown $39 = 1
49
+ [1] unknown $40 = StoreLocal Let unknown a$41 = unknown $39
50
+ [2] unknown $42 = DeclareLocal Let unknown b$43
51
+ [3] unknown $44 = LoadLocal unknown a$1
52
+ [4] unknown $45 = 1
53
+ [5] unknown $46 = Binary unknown $44 === unknown $45
54
+ [6] If unknown $11 consequent=bb2 alternate=bb3 fallthrough=bb1
55
+bb2 (block)
56
+ predecessors: bb0
57
+ [7] unknown $47 = true
58
+ [8] unknown $48 = StoreLocal Reassign unknown b$49 = unknown $47
59
+ [9] Goto bb1
60
+bb3 (block)
61
+ predecessors: bb0
62
+ [10] unknown $50 = false
63
+ [11] unknown $51 = StoreLocal Reassign unknown b$52 = unknown $50
64
+ [12] Goto bb1
65
+bb1 (block)
66
+ predecessors: bb2, bb3
67
+ [13] unknown $53 = DeclareLocal Let unknown c$54
68
+ [14] unknown $55 = LoadLocal unknown b$3
69
+ [15] If unknown $18 consequent=bb5 alternate=bb6 fallthrough=bb4
70
+bb5 (block)
71
+ predecessors: bb1
72
+ [16] unknown $56 = "hello"
73
+ [17] unknown $57 = StoreLocal Reassign unknown c$58 = unknown $56
74
+ [18] Goto bb4
75
+bb6 (block)
76
+ predecessors: bb1
77
+ [19] unknown $59 = null
78
+ [20] unknown $60 = StoreLocal Reassign unknown c$61 = unknown $59
79
+ [21] Goto bb4
80
+bb4 (block)
81
+ predecessors: bb5, bb6
82
+ [22] unknown $62 = DeclareLocal Let unknown d$63
83
+ [23] unknown $64 = LoadLocal unknown c$12
84
+ [24] unknown $65 = "hello"
85
+ [25] unknown $66 = Binary unknown $64 === unknown $65
86
+ [26] If unknown $27 consequent=bb8 alternate=bb9 fallthrough=bb7
87
+bb8 (block)
88
+ predecessors: bb4
89
+ [27] unknown $67 = 42
90
+ [28] unknown $68 = StoreLocal Reassign unknown d$69 = unknown $67
91
+ [29] Goto bb7
92
+bb9 (block)
93
+ predecessors: bb4
94
+ [30] unknown $70 = 42.001
95
+ [31] unknown $71 = StoreLocal Reassign unknown d$72 = unknown $70
96
+ [32] Goto bb7
97
+bb7 (block)
98
+ predecessors: bb8, bb9
99
+ [33] unknown $73 = DeclareLocal Let unknown e$74
100
+ [34] unknown $75 = LoadLocal unknown d$19
101
+ [35] unknown $76 = 42
102
+ [36] unknown $77 = Binary unknown $75 === unknown $76
103
+ [37] If unknown $36 consequent=bb11 alternate=bb12 fallthrough=bb10
104
+bb11 (block)
105
+ predecessors: bb7
106
+ [38] unknown $78 = "ok"
107
+ [39] unknown $79 = StoreLocal Reassign unknown e$80 = unknown $78
108
+ [40] Goto bb10
109
+bb12 (block)
110
+ predecessors: bb7
111
+ [41] unknown $81 = "nope"
112
+ [42] unknown $82 = StoreLocal Reassign unknown e$83 = unknown $81
113
+ [43] Goto bb10
114
+bb10 (block)
115
+ predecessors: bb11, bb12
116
+ [44] unknown $84 = LoadLocal unknown e$28
117
+ [45] Return unknown $37
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@constant-propagation.js.snap
+103
-105
@@ -72,127 +72,125 @@ function Component(
72
)
73
entry bb0
74
bb0 (block)
75
- [0] unknown $2 = DeclareLocal Let unknown a$109
76
- [1] unknown $3 = LoadGlobal Math
77
- [2] unknown $4 = StoreLocal Reassign unknown a$110 = unknown $3
78
- [3] unknown $5 = LoadGlobal Math
79
- [4] unknown $7 = DeclareLocal Let unknown b$111
80
- [5] unknown $12 = LoadLocal unknown props$108
75
+ [0] unknown $109 = DeclareLocal Let unknown a$110
76
+ [1] unknown $111 = LoadGlobal Math
77
+ [2] unknown $112 = StoreLocal Reassign unknown a$113 = unknown $111
78
+ [3] unknown $114 = LoadLocal unknown a$1
79
+ [4] unknown $115 = DeclareLocal Let unknown b$116
80
+ [5] unknown $117 = LoadLocal unknown props$0
81
[6] If unknown $12 consequent=bb2 alternate=bb3 fallthrough=bb1
82
bb2 (block)
83
predecessors: bb0
84
- [7] unknown $8 = true
85
- [8] unknown $9 = StoreLocal Reassign unknown b$112 = unknown $8
84
+ [7] unknown $118 = true
85
+ [8] unknown $119 = StoreLocal Reassign unknown b$120 = unknown $118
86
[9] Goto bb1
87
bb3 (block)
88
predecessors: bb0
89
- [10] unknown $10 = true
90
- [11] unknown $11 = StoreLocal Reassign unknown b$113 = unknown $10
89
+ [10] unknown $121 = true
90
+ [11] unknown $122 = StoreLocal Reassign unknown b$123 = unknown $121
91
[12] Goto bb1
92
bb1 (block)
93
predecessors: bb2, bb3
94
- b$114: phi(bb2: b$112, bb3: b$113)
95
- [13] unknown $13 = true
96
- [14] unknown $15 = DeclareLocal Let unknown c$115
97
- [15] unknown $20 = LoadLocal unknown props$108
94
+ [13] unknown $124 = LoadLocal unknown b$6
95
+ [14] unknown $125 = DeclareLocal Let unknown c$126
96
+ [15] unknown $127 = LoadLocal unknown props$0
97
[16] If unknown $20 consequent=bb5 alternate=bb6 fallthrough=bb4
98
bb5 (block)
99
predecessors: bb1
101
- [17] unknown $16 = true
102
- [18] unknown $17 = StoreLocal Reassign unknown c$117 = unknown $16
100
+ [17] unknown $128 = true
101
+ [18] unknown $129 = StoreLocal Reassign unknown c$130 = unknown $128
102
[19] Goto bb4
103
bb6 (block)
104
predecessors: bb1
106
- [20] unknown $18 = 42
107
- [21] unknown $19 = StoreLocal Reassign unknown c$118 = unknown $18
105
+ [20] unknown $131 = 42
106
+ [21] unknown $132 = StoreLocal Reassign unknown c$133 = unknown $131
107
[22] Goto bb4
108
bb4 (block)
109
predecessors: bb5, bb6
111
- c$119: phi(bb5: c$117, bb6: c$118)
112
- [23] unknown $21 = LoadLocal unknown c$119
113
- [24] unknown $22 = 42
114
- [25] unknown $23 = 1
115
- [26] unknown $24 = 43
116
- [27] unknown $25 = 42
117
- [28] unknown $26 = 1
118
- [29] unknown $27 = 41
119
- [30] unknown $28 = 42
120
- [31] unknown $29 = 2
121
- [32] unknown $30 = 84
122
- [33] unknown $31 = 42
123
- [34] unknown $32 = 2
124
- [35] unknown $33 = 21
125
- [36] unknown $34 = 0
126
- [37] unknown $35 = 1
127
- [38] unknown $36 = false
128
- [39] unknown $37 = 0
129
- [40] unknown $38 = 1
130
- [41] unknown $39 = true
131
- [42] unknown $40 = 0
132
- [43] unknown $41 = 1
133
- [44] unknown $42 = false
134
- [45] unknown $43 = 0
135
- [46] unknown $44 = 1
136
- [47] unknown $45 = true
137
- [48] unknown $46 = 0
138
- [49] unknown $47 = 0
139
- [50] unknown $48 = true
140
- [51] unknown $49 = LoadGlobal NaN
141
- [52] unknown $50 = LoadGlobal NaN
142
- [53] unknown $51 = Binary unknown $49 == unknown $50
143
- [54] unknown $52 = LoadGlobal NaN
144
- [55] unknown $53 = LoadGlobal NaN
145
- [56] unknown $54 = Binary unknown $52 != unknown $53
146
- [57] unknown $55 = LoadGlobal NaN
147
- [58] unknown $56 = LoadGlobal NaN
148
- [59] unknown $57 = Binary unknown $55 !== unknown $56
149
- [60] unknown $58 = LoadGlobal NaN
150
- [61] unknown $59 = LoadGlobal NaN
151
- [62] unknown $60 = Binary unknown $58 !== unknown $59
152
- [63] unknown $61 = "hello"
153
- [64] unknown $62 = "hello"
154
- [65] unknown $63 = true
155
- [66] unknown $64 = "hello"
156
- [67] unknown $65 = "hello"
157
- [68] unknown $66 = false
158
- [69] unknown $67 = "hello"
159
- [70] unknown $68 = "hello"
160
- [71] unknown $69 = true
161
- [72] unknown $70 = "hello"
162
- [73] unknown $71 = "hello"
163
- [74] unknown $72 = false
164
- [75] unknown $73 = "hello"
165
- [76] unknown $74 = "world"
166
- [77] unknown $75 = false
167
- [78] unknown $76 = "hello"
168
- [79] unknown $77 = "world"
169
- [80] unknown $78 = true
170
- [81] unknown $79 = "hello"
171
- [82] unknown $80 = "world"
172
- [83] unknown $81 = false
173
- [84] unknown $82 = "hello"
174
- [85] unknown $83 = "world"
175
- [86] unknown $84 = true
176
- [87] unknown $85 = true
177
- [88] unknown $86 = true
178
- [89] unknown $87 = true
179
- [90] unknown $88 = true
180
- [91] unknown $89 = true
181
- [92] unknown $90 = false
182
- [93] unknown $91 = true
183
- [94] unknown $92 = true
184
- [95] unknown $93 = true
185
- [96] unknown $94 = true
186
- [97] unknown $95 = true
187
- [98] unknown $96 = false
188
- [99] unknown $97 = 5
189
- [100] unknown $98 = 60
190
- [101] unknown $99 = 300
191
- [102] unknown $100 = 60
192
- [103] unknown $101 = 18000
193
- [104] unknown $102 = 1000
194
- [105] unknown $103 = 18000000
195
- [106] unknown $105 = StoreLocal Let unknown x$120 = unknown $103
196
- [107] unknown $106 = 18000000
197
- [108] unknown $107 = <undefined>
110
+ [23] unknown $134 = LoadLocal unknown c$14
111
+ [24] unknown $135 = 42
112
+ [25] unknown $136 = 1
113
+ [26] unknown $137 = 43
114
+ [27] unknown $138 = 42
115
+ [28] unknown $139 = 1
116
+ [29] unknown $140 = 41
117
+ [30] unknown $141 = 42
118
+ [31] unknown $142 = 2
119
+ [32] unknown $143 = 84
120
+ [33] unknown $144 = 42
121
+ [34] unknown $145 = 2
122
+ [35] unknown $146 = 21
123
+ [36] unknown $147 = 0
124
+ [37] unknown $148 = 1
125
+ [38] unknown $149 = false
126
+ [39] unknown $150 = 0
127
+ [40] unknown $151 = 1
128
+ [41] unknown $152 = true
129
+ [42] unknown $153 = 0
130
+ [43] unknown $154 = 1
131
+ [44] unknown $155 = false
132
+ [45] unknown $156 = 0
133
+ [46] unknown $157 = 1
134
+ [47] unknown $158 = true
135
+ [48] unknown $159 = 0
136
+ [49] unknown $160 = 0
137
+ [50] unknown $161 = true
138
+ [51] unknown $162 = LoadGlobal NaN
139
+ [52] unknown $163 = LoadGlobal NaN
140
+ [53] unknown $164 = Binary unknown $162 == unknown $163
141
+ [54] unknown $165 = LoadGlobal NaN
142
+ [55] unknown $166 = LoadGlobal NaN
143
+ [56] unknown $167 = Binary unknown $165 != unknown $166
144
+ [57] unknown $168 = LoadGlobal NaN
145
+ [58] unknown $169 = LoadGlobal NaN
146
+ [59] unknown $170 = Binary unknown $168 !== unknown $169
147
+ [60] unknown $171 = LoadGlobal NaN
148
+ [61] unknown $172 = LoadGlobal NaN
149
+ [62] unknown $173 = Binary unknown $171 !== unknown $172
150
+ [63] unknown $174 = "hello"
151
+ [64] unknown $175 = "hello"
152
+ [65] unknown $176 = true
153
+ [66] unknown $177 = "hello"
154
+ [67] unknown $178 = "hello"
155
+ [68] unknown $179 = false
156
+ [69] unknown $180 = "hello"
157
+ [70] unknown $181 = "hello"
158
+ [71] unknown $182 = true
159
+ [72] unknown $183 = "hello"
160
+ [73] unknown $184 = "hello"
161
+ [74] unknown $185 = false
162
+ [75] unknown $186 = "hello"
163
+ [76] unknown $187 = "world"
164
+ [77] unknown $188 = false
165
+ [78] unknown $189 = "hello"
166
+ [79] unknown $190 = "world"
167
+ [80] unknown $191 = true
168
+ [81] unknown $192 = "hello"
169
+ [82] unknown $193 = "world"
170
+ [83] unknown $194 = false
171
+ [84] unknown $195 = "hello"
172
+ [85] unknown $196 = "world"
173
+ [86] unknown $197 = true
174
+ [87] unknown $198 = true
175
+ [88] unknown $199 = true
176
+ [89] unknown $200 = true
177
+ [90] unknown $201 = true
178
+ [91] unknown $202 = true
179
+ [92] unknown $203 = false
180
+ [93] unknown $204 = true
181
+ [94] unknown $205 = true
182
+ [95] unknown $206 = true
183
+ [96] unknown $207 = true
184
+ [97] unknown $208 = true
185
+ [98] unknown $209 = false
186
+ [99] unknown $210 = 5
187
+ [100] unknown $211 = 60
188
+ [101] unknown $212 = 300
189
+ [102] unknown $213 = 60
190
+ [103] unknown $214 = 18000
191
+ [104] unknown $215 = 1000
192
+ [105] unknown $216 = 18000000
193
+ [106] unknown $217 = StoreLocal Let unknown x$218 = unknown $216
194
+ [107] unknown $219 = LoadLocal unknown x$104
195
+ [108] unknown $220 = <undefined>
196
[109] Return unknown $107
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@destructure-array.js.snap
new
+33
@@ -0,0 +1,33 @@
1
+---
2
+source: crates/forget_fixtures/tests/fixtures_test.rs
3
+expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
4
+input_file: crates/forget_fixtures/tests/fixtures/destructure-array.js
5
+---
6
+Input:
7
+function Component(a, b) {
8
+ const [c, , ...d] = a;
9
+ const [[[e]], ...[f]] = b;
10
+ return [c, d, e, f];
11
+}
12
+
13
+
14
+Output:
15
+function Component(
16
+ unknown a$22,
17
+ unknown b$23,
18
+)
19
+entry bb0
20
+bb0 (block)
21
+ [0] unknown $24 = LoadLocal unknown a$0
22
+ [1] unknown $25 = Destructure [ unknown c$26, <hole>, ...unknown d$27 ] = unknown $24
23
+ [2] unknown $28 = LoadLocal unknown b$1
24
+ [3] unknown $29 = Destructure [ unknown $30, ...unknown $31 ] = unknown $28
25
+ [4] unknown $32 = Destructure [ unknown $33 ] = unknown $30
26
+ [5] unknown $34 = Destructure [ unknown e$35 ] = unknown $33
27
+ [6] unknown $36 = Destructure [ unknown f$37 ] = unknown $31
28
+ [7] unknown $38 = LoadLocal unknown c$3
29
+ [8] unknown $39 = LoadLocal unknown d$4
30
+ [9] unknown $40 = LoadLocal unknown e$12
31
+ [10] unknown $41 = LoadLocal unknown f$14
32
+ [11] unknown $42 = Array [unknown $38, unknown $39, unknown $40, unknown $41]
33
+ [12] Return unknown $20
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@destructure-object.js.snap
new
+46
@@ -0,0 +1,46 @@
1
+---
2
+source: crates/forget_fixtures/tests/fixtures_test.rs
3
+expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
4
+input_file: crates/forget_fixtures/tests/fixtures/destructure-object.js
5
+---
6
+Input:
7
+function Component(a, b) {
8
+ const {
9
+ c,
10
+ d,
11
+ e: { e },
12
+ f: { _f: f },
13
+ g: {
14
+ g: {
15
+ g: { g, ...h },
16
+ },
17
+ },
18
+ ...i
19
+ } = a;
20
+ return [c, d, e, f, g, h, i];
21
+}
22
+
23
+
24
+Output:
25
+function Component(
26
+ unknown a$30,
27
+ unknown b$31,
28
+)
29
+entry bb0
30
+bb0 (block)
31
+ [0] unknown $32 = LoadLocal unknown a$0
32
+ [1] unknown $33 = Destructure { c: unknown c$34, d: unknown d$35, e: unknown $36, f: unknown $37, g: unknown $38, ...unknown i$39 } = unknown $32
33
+ [2] unknown $40 = Destructure { e: unknown e$41 } = unknown $36
34
+ [3] unknown $42 = Destructure { _f: unknown f$43 } = unknown $37
35
+ [4] unknown $44 = Destructure { g: unknown $45 } = unknown $38
36
+ [5] unknown $46 = Destructure { g: unknown $47 } = unknown $45
37
+ [6] unknown $48 = Destructure { g: unknown g$49, ...unknown h$50 } = unknown $47
38
+ [7] unknown $51 = LoadLocal unknown c$3
39
+ [8] unknown $52 = LoadLocal unknown d$4
40
+ [9] unknown $53 = LoadLocal unknown e$10
41
+ [10] unknown $54 = LoadLocal unknown f$12
42
+ [11] unknown $55 = LoadLocal unknown g$18
43
+ [12] unknown $56 = LoadLocal unknown h$19
44
+ [13] unknown $57 = LoadLocal unknown i$8
45
+ [14] unknown $58 = Array [unknown $51, unknown $52, unknown $53, unknown $54, unknown $55, unknown $56, unknown $57]
46
+ [15] Return unknown $28
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@for-statement.js.snap
+16
-18
@@ -18,37 +18,35 @@ function foo(
18
)
19
entry bb0
20
bb0 (block)
21
- [0] unknown $0 = 0
22
- [1] unknown $2 = StoreLocal Let unknown x$19 = unknown $0
21
+ [0] unknown $19 = 0
22
+ [1] unknown $20 = StoreLocal Let unknown x$21 = unknown $19
23
[2] For init=bb3 test=bb1 update=bb4 body=bb5 fallthrough=bb2
24
bb3 (loop)
25
predecessors: bb0
26
- [3] unknown $3 = 0
27
- [4] unknown $5 = StoreLocal Let unknown i$20 = unknown $3
26
+ [3] unknown $22 = 0
27
+ [4] unknown $23 = StoreLocal Let unknown i$24 = unknown $22
28
[5] Goto bb1
29
bb1 (loop)
30
predecessors: bb3, bb4
31
- i$21: phi(bb3: i$20, bb4: i$24)
32
- x$22: phi(bb3: x$19, bb4: x$23)
33
- [6] unknown $14 = LoadLocal unknown i$21
34
- [7] unknown $15 = 10
35
- [8] unknown $16 = Binary unknown $14 < unknown $15
31
+ [6] unknown $25 = LoadLocal unknown i$4
32
+ [7] unknown $26 = 10
33
+ [8] unknown $27 = Binary unknown $25 < unknown $26
34
[9] Branch unknown $16 consequent=bb5 alternate=bb2
35
bb5 (block)
36
predecessors: bb1
39
- [10] unknown $10 = LoadLocal unknown x$22
40
- [11] unknown $11 = LoadLocal unknown i$21
41
- [12] unknown $12 = Binary unknown $10 + unknown $11
42
- [13] unknown $13 = StoreLocal Reassign unknown x$23 = unknown $12
37
+ [10] unknown $28 = LoadLocal unknown x$1
38
+ [11] unknown $29 = LoadLocal unknown i$4
39
+ [12] unknown $30 = Binary unknown $28 + unknown $29
40
+ [13] unknown $31 = StoreLocal Reassign unknown x$32 = unknown $30
41
[14] Goto bb4
42
bb4 (loop)
43
predecessors: bb5
46
- [15] unknown $6 = LoadLocal unknown i$21
47
- [16] unknown $7 = 1
48
- [17] unknown $8 = Binary unknown $6 + unknown $7
49
- [18] unknown $9 = StoreLocal Reassign unknown i$24 = unknown $8
44
+ [15] unknown $33 = LoadLocal unknown i$4
45
+ [16] unknown $34 = 1
46
+ [17] unknown $35 = Binary unknown $33 + unknown $34
47
+ [18] unknown $36 = StoreLocal Reassign unknown i$37 = unknown $35
48
[19] Goto bb1
49
bb2 (block)
50
predecessors: bb1
53
- [20] unknown $17 = LoadLocal unknown x$22
51
+ [20] unknown $38 = LoadLocal unknown x$1
52
[21] Return unknown $17
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@function-expressions.js.snap
+61
-49
@@ -33,62 +33,74 @@ function Component(
33
)
34
entry bb0
35
bb0 (block)
36
- [0] unknown $1 = 2
37
- [1] unknown $3 = StoreLocal Const unknown x$59 = unknown $1
38
- [2] unknown $54 = Function @deps[] @context[unknown x$59]:
36
+ [0] unknown $59 = 2
37
+ [1] unknown $60 = StoreLocal Const unknown x$61 = unknown $59
38
+ [2] unknown $62 = Function @deps[] @context[unknown x$61]:
39
function foo(
40
- unknown y$60,
40
+ unknown y$63,
41
)
42
entry bb1
43
bb1 (block)
44
- [0] unknown $5 = 1
45
- [1] unknown $7 = StoreLocal Let unknown a$61 = unknown $5
46
- [2] unknown $9 = DeclareLocal Let unknown b$62
47
- [3] unknown $16 = 1
48
- [4] unknown $17 = 1
49
- [5] unknown $18 = true
50
- [6] unknown $10 = 5
51
- [7] unknown $11 = 3
52
- [8] unknown $12 = 8
53
- [9] unknown $13 = StoreLocal Reassign unknown b$63 = unknown $12
54
- [10] unknown $19 = 2
55
- [11] unknown $20 = LoadLocal unknown y$60
56
- [12] unknown $21 = Binary unknown $19 + unknown $20
57
- [13] unknown $22 = 1
58
- [14] unknown $23 = Binary unknown $21 + unknown $22
59
- [15] unknown $24 = 8
60
- [16] unknown $25 = Binary unknown $23 + unknown $24
61
- [17] unknown $48 = Function @deps[] @context[unknown x$59, unknown y$60, unknown a$61, unknown b$63]:
44
+ [0] unknown $64 = 1
45
+ [1] unknown $65 = StoreLocal Let unknown a$66 = unknown $64
46
+ [2] unknown $67 = DeclareLocal Let unknown b$68
47
+ [3] unknown $69 = LoadLocal unknown a$6
48
+ [4] unknown $70 = 1
49
+ [5] unknown $71 = Binary unknown $69 === unknown $70
50
+ [6] If unknown $18 consequent=bb3 alternate=bb4 fallthrough=bb2
51
+ bb3 (block)
52
+ predecessors: bb1
53
+ [7] unknown $72 = 5
54
+ [8] unknown $73 = 3
55
+ [9] unknown $74 = 8
56
+ [10] unknown $75 = StoreLocal Reassign unknown b$76 = unknown $74
57
+ [11] Goto bb2
58
+ bb4 (block)
59
+ predecessors: bb1
60
+ [12] unknown $77 = false
61
+ [13] unknown $78 = StoreLocal Reassign unknown b$79 = unknown $77
62
+ [14] Goto bb2
63
+ bb2 (block)
64
+ predecessors: bb3, bb4
65
+ b$91: phi(bb3: b$76, bb4: b$79)
66
+ [15] unknown $80 = LoadLocal unknown x$2
67
+ [16] unknown $81 = LoadLocal unknown y$4
68
+ [17] unknown $82 = Binary unknown $80 + unknown $81
69
+ [18] unknown $83 = LoadLocal unknown a$6
70
+ [19] unknown $84 = Binary unknown $82 + unknown $83
71
+ [20] unknown $85 = LoadLocal unknown b$8
72
+ [21] unknown $86 = Binary unknown $84 + unknown $85
73
+ [22] unknown $87 = Function @deps[] @context[unknown x$61, unknown y$63, unknown a$66, unknown b$91]:
74
function bar(
63
- unknown z$69,
75
+ unknown z$92,
76
)
77
entry bb5
78
bb5 (block)
67
- [0] unknown $27 = 2
68
- [1] unknown $29 = StoreLocal Let unknown c$70 = unknown $27
69
- [2] unknown $31 = DeclareLocal Let unknown d$71
70
- [3] unknown $32 = 3
71
- [4] unknown $33 = StoreLocal Reassign unknown d$72 = unknown $32
72
- [5] unknown $34 = LoadLocal unknown x$65
73
- [6] unknown $35 = LoadLocal unknown y$66
74
- [7] unknown $36 = Binary unknown $34 + unknown $35
75
- [8] unknown $37 = LoadLocal unknown a$67
76
- [9] unknown $38 = Binary unknown $36 + unknown $37
77
- [10] unknown $39 = LoadLocal unknown b$68
78
- [11] unknown $40 = Binary unknown $38 + unknown $39
79
- [12] unknown $41 = LoadLocal unknown z$69
80
- [13] unknown $42 = Binary unknown $40 + unknown $41
81
- [14] unknown $43 = 2
82
- [15] unknown $44 = Binary unknown $42 + unknown $43
83
- [16] unknown $45 = 3
84
- [17] unknown $46 = Binary unknown $44 + unknown $45
85
- [18] unknown $47 = <undefined>
79
+ [0] unknown $93 = 2
80
+ [1] unknown $94 = StoreLocal Let unknown c$95 = unknown $93
81
+ [2] unknown $96 = DeclareLocal Let unknown d$97
82
+ [3] unknown $98 = 3
83
+ [4] unknown $99 = StoreLocal Reassign unknown d$100 = unknown $98
84
+ [5] unknown $101 = LoadLocal unknown x$2
85
+ [6] unknown $102 = LoadLocal unknown y$4
86
+ [7] unknown $103 = Binary unknown $101 + unknown $102
87
+ [8] unknown $104 = LoadLocal unknown a$6
88
+ [9] unknown $105 = Binary unknown $103 + unknown $104
89
+ [10] unknown $106 = LoadLocal unknown b$8
90
+ [11] unknown $107 = Binary unknown $105 + unknown $106
91
+ [12] unknown $108 = LoadLocal unknown z$26
92
+ [13] unknown $109 = Binary unknown $107 + unknown $108
93
+ [14] unknown $110 = LoadLocal unknown c$28
94
+ [15] unknown $111 = Binary unknown $109 + unknown $110
95
+ [16] unknown $112 = LoadLocal unknown d$30
96
+ [17] unknown $113 = Binary unknown $111 + unknown $112
97
+ [18] unknown $114 = <undefined>
98
[19] Return unknown $47
87
- [18] unknown $50 = StoreLocal Const unknown bar$73 = unknown $48
88
- [19] unknown $51 = LoadLocal unknown bar$73
89
- [20] unknown $52 = LoadGlobal foo
90
- [21] unknown $53 = <undefined>
91
- [22] Return unknown $53
92
- [3] unknown $56 = StoreLocal Const unknown foo$74 = unknown $54
93
- [4] unknown $57 = <undefined>
99
+ [23] unknown $115 = StoreLocal Const unknown bar$116 = unknown $87
100
+ [24] unknown $117 = LoadLocal unknown bar$49
101
+ [25] unknown $118 = LoadGlobal foo
102
+ [26] unknown $119 = <undefined>
103
+ [27] Return unknown $53
104
+ [3] unknown $120 = StoreLocal Const unknown foo$121 = unknown $62
105
+ [4] unknown $122 = <undefined>
106
[5] Return unknown $57
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@identifiers.js.snap
+10
-10
@@ -28,14 +28,14 @@ function id(
28
)
29
entry bb0
30
bb0 (block)
31
- [0] unknown $1 = LoadGlobal Math
32
- [1] unknown $2 = LoadGlobal id
33
- [2] unknown $3 = true
34
- [3] unknown $5 = StoreLocal Let unknown y$15 = unknown $3
35
- [4] unknown $6 = false
36
- [5] unknown $7 = StoreLocal Reassign unknown y$16 = unknown $6
37
- [6] unknown $8 = false
38
- [7] unknown $10 = DeclareLocal Let unknown z$17
39
- [8] unknown $11 = LoadLocal unknown z$17
40
- [9] unknown $12 = LoadLocal unknown x$14
31
+ [0] unknown $15 = LoadGlobal Math
32
+ [1] unknown $16 = LoadGlobal id
33
+ [2] unknown $17 = true
34
+ [3] unknown $18 = StoreLocal Let unknown y$19 = unknown $17
35
+ [4] unknown $20 = false
36
+ [5] unknown $21 = StoreLocal Reassign unknown y$22 = unknown $20
37
+ [6] unknown $23 = LoadLocal unknown y$4
38
+ [7] unknown $24 = DeclareLocal Let unknown z$25
39
+ [8] unknown $26 = LoadLocal unknown z$9
40
+ [9] unknown $27 = LoadLocal unknown x$0
41
[10] Return unknown $12
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@if-statement.js.snap
+5
-5
@@ -23,18 +23,18 @@ function foo(
23
)
24
entry bb0
25
bb0 (block)
26
- [0] unknown $6 = LoadLocal unknown a$9
26
+ [0] unknown $13 = LoadLocal unknown a$0
27
[1] If unknown $6 consequent=bb2 alternate=bb4 fallthrough=bb1
28
bb2 (block)
29
predecessors: bb0
30
- [2] unknown $4 = LoadLocal unknown b$10
30
+ [2] unknown $14 = LoadLocal unknown b$1
31
[3] Return unknown $4
32
bb4 (block)
33
predecessors: bb0
34
- [4] unknown $5 = LoadLocal unknown c$11
34
+ [4] unknown $15 = LoadLocal unknown c$2
35
[5] Goto bb1
36
bb1 (block)
37
predecessors: bb4
38
- [6] unknown $7 = LoadLocal unknown d$12
39
- [7] unknown $8 = <undefined>
38
+ [6] unknown $16 = LoadLocal unknown d$3
39
+ [7] unknown $17 = <undefined>
40
[8] Return unknown $8
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@simple-function.js.snap
+17
-17
@@ -21,26 +21,26 @@ function Component(
21
)
22
entry bb0
23
bb0 (block)
24
- [0] unknown $1 = LoadGlobal Math
25
- [1] unknown $2 = 0
26
- [2] unknown $4 = StoreLocal Let unknown b$24 = unknown $2
27
- [3] unknown $17 = Function @deps[] @context[unknown a$23, unknown b$24]:
24
+ [0] unknown $24 = LoadGlobal Math
25
+ [1] unknown $25 = 0
26
+ [2] unknown $26 = StoreLocal Let unknown b$27 = unknown $25
27
+ [3] unknown $28 = Function @deps[] @context[unknown a$23, unknown b$27]:
28
function foo_(
29
- unknown c$25,
29
+ unknown c$29,
30
)
31
entry bb1
32
bb1 (block)
33
- [0] unknown $6 = 1
34
- [1] unknown $8 = StoreLocal Let unknown d$26 = unknown $6
35
- [2] unknown $9 = LoadLocal unknown a$23
36
- [3] unknown $10 = 0
37
- [4] unknown $11 = Binary unknown $9 + unknown $10
38
- [5] unknown $12 = LoadLocal unknown c$25
39
- [6] unknown $13 = Binary unknown $11 + unknown $12
40
- [7] unknown $14 = 1
41
- [8] unknown $15 = Binary unknown $13 + unknown $14
33
+ [0] unknown $30 = 1
34
+ [1] unknown $31 = StoreLocal Let unknown d$32 = unknown $30
35
+ [2] unknown $33 = LoadLocal unknown a$0
36
+ [3] unknown $34 = LoadLocal unknown b$3
37
+ [4] unknown $35 = Binary unknown $33 + unknown $34
38
+ [5] unknown $36 = LoadLocal unknown c$5
39
+ [6] unknown $37 = Binary unknown $35 + unknown $36
40
+ [7] unknown $38 = LoadLocal unknown d$7
41
+ [8] unknown $39 = Binary unknown $37 + unknown $38
42
[9] Return unknown $15
43
- [4] unknown $19 = StoreLocal Const unknown foo$27 = unknown $17
44
- [5] unknown $20 = LoadLocal unknown foo$27
45
- [6] unknown $21 = Call unknown $20()
43
+ [4] unknown $40 = StoreLocal Const unknown foo$41 = unknown $28
44
+ [5] unknown $42 = LoadLocal unknown foo$18
45
+ [6] unknown $43 = Call unknown $42()
46
[7] Return unknown $21
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@simple.js.snap
+9
-9
@@ -15,13 +15,13 @@ function test(
15
)
16
entry bb0
17
bb0 (block)
18
- [0] unknown $0 = true
19
- [1] unknown $1 = false
20
- [2] unknown $2 = null
21
- [3] unknown $3 = 1
22
- [4] unknown $4 = 3.14
23
- [5] unknown $5 = "hello world!"
24
- [6] unknown $6 = Array [unknown $5]
25
- [7] unknown $7 = Array [unknown $0, unknown $1, unknown $2, unknown $3, unknown $4, ...unknown $6]
26
- [8] unknown $8 = 2
18
+ [0] unknown $10 = true
19
+ [1] unknown $11 = false
20
+ [2] unknown $12 = null
21
+ [3] unknown $13 = 1
22
+ [4] unknown $14 = 3.14
23
+ [5] unknown $15 = "hello world!"
24
+ [6] unknown $16 = Array [unknown $15]
25
+ [7] unknown $17 = Array [unknown $10, unknown $11, unknown $12, unknown $13, unknown $14, ...unknown $16]
26
+ [8] unknown $18 = 2
27
[9] Return unknown $8
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@ssa-reassign-if.js.snap
+20
-23
@@ -29,45 +29,42 @@ function Component(
29
)
30
entry bb0
31
bb0 (block)
32
- [0] unknown $3 = DeclareLocal Let unknown x$28
33
- [1] unknown $4 = 0
34
- [2] unknown $6 = StoreLocal Let unknown y$29 = unknown $4
35
- [3] unknown $7 = 10
36
- [4] unknown $9 = StoreLocal Let unknown z$30 = unknown $7
37
- [5] unknown $19 = LoadLocal unknown a$26
32
+ [0] unknown $28 = DeclareLocal Let unknown x$29
33
+ [1] unknown $30 = 0
34
+ [2] unknown $31 = StoreLocal Let unknown y$32 = unknown $30
35
+ [3] unknown $33 = 10
36
+ [4] unknown $34 = StoreLocal Let unknown z$35 = unknown $33
37
+ [5] unknown $36 = LoadLocal unknown a$0
38
[6] If unknown $19 consequent=bb2 alternate=bb6 fallthrough=bb1
39
bb2 (block)
40
predecessors: bb0
41
- [7] unknown $10 = 1
42
- [8] unknown $11 = StoreLocal Reassign unknown x$31 = unknown $10
43
- [9] unknown $16 = LoadLocal unknown b$27
41
+ [7] unknown $37 = 1
42
+ [8] unknown $38 = StoreLocal Reassign unknown x$39 = unknown $37
43
+ [9] unknown $40 = LoadLocal unknown b$1
44
[10] If unknown $16 consequent=bb4 alternate=bb5 fallthrough=bb3
45
bb4 (block)
46
predecessors: bb2
47
- [11] unknown $12 = 20
48
- [12] unknown $13 = StoreLocal Reassign unknown z$32 = unknown $12
47
+ [11] unknown $41 = 20
48
+ [12] unknown $42 = StoreLocal Reassign unknown z$43 = unknown $41
49
[13] Goto bb3
50
bb5 (block)
51
predecessors: bb2
52
- [14] unknown $14 = 30
53
- [15] unknown $15 = StoreLocal Reassign unknown z$33 = unknown $14
52
+ [14] unknown $44 = 30
53
+ [15] unknown $45 = StoreLocal Reassign unknown z$46 = unknown $44
54
[16] Goto bb3
55
bb3 (block)
56
predecessors: bb4, bb5
57
- z$40: phi(bb4: z$32, bb5: z$33)
57
[17] Goto bb1
58
bb6 (block)
59
predecessors: bb0
61
- [18] unknown $17 = 2
62
- [19] unknown $18 = StoreLocal Reassign unknown x$34 = unknown $17
60
+ [18] unknown $47 = 2
61
+ [19] unknown $48 = StoreLocal Reassign unknown x$49 = unknown $47
62
[20] Goto bb1
63
bb1 (block)
64
predecessors: bb3, bb6
66
- x$35: phi(bb3: x$31, bb6: x$34)
67
- z$39: phi(bb3: z$40, bb6: z$30)
68
- [21] unknown $20 = LoadLocal unknown x$35
69
- [22] unknown $21 = 0
70
- [23] unknown $22 = Binary unknown $20 + unknown $21
71
- [24] unknown $23 = LoadLocal unknown z$39
72
- [25] unknown $24 = Binary unknown $22 + unknown $23
65
+ [21] unknown $50 = LoadLocal unknown x$2
66
+ [22] unknown $51 = LoadLocal unknown y$5
67
+ [23] unknown $52 = Binary unknown $50 + unknown $51
68
+ [24] unknown $53 = LoadLocal unknown z$8
69
+ [25] unknown $54 = Binary unknown $52 + unknown $53
70
[26] Return unknown $24
compiler/forget/crates/forget_fixtures/tests/snapshots/fixtures_test__fixtures@use-memo.js.snap
+7
-7
@@ -18,17 +18,17 @@ function Component(
18
)
19
entry bb0
20
bb0 (block)
21
- [0] unknown $1 = LoadGlobal useMemo
22
- [1] unknown $14 = DeclareLocal Let unknown t$12
21
+ [0] unknown $11 = LoadGlobal useMemo
22
+ [1] unknown $20 = DeclareLocal Let unknown t$18
23
[2] Label block=bb1 fallthrough=bb6
24
bb1 (block)
25
predecessors: bb0
26
- [3] unknown $2 = LoadGlobal y
27
- [4] unknown $13 = StoreLocal Reassign unknown t$12 = unknown $2
26
+ [3] unknown $13 = LoadGlobal y
27
+ [4] unknown $19 = StoreLocal Reassign unknown t$18 = unknown $2
28
[5] Goto bb6
29
bb6 (block)
30
predecessors: bb1
31
- [6] unknown $5 = LoadLocal unknown t$12
32
- [7] unknown $7 = StoreLocal Const unknown x$11 = unknown $5
33
- [8] unknown $8 = LoadLocal unknown x$11
31
+ [6] unknown $14 = LoadLocal unknown t$18
32
+ [7] unknown $15 = StoreLocal Const unknown x$16 = unknown $14
33
+ [8] unknown $17 = LoadLocal unknown x$6
34
[9] Return unknown $8
compiler/forget/crates/forget_hir/src/instruction.rs
+121
-24
@@ -16,17 +16,20 @@ pub struct Instruction {
16
impl Instruction {
17
pub fn each_identifier_store<F>(&mut self, mut f: F) -> ()
18
where
19
- F: FnMut(&mut LValue) -> (),
19
+ F: FnMut(&mut IdentifierOperand) -> (),
20
{
21
match &mut self.value {
22
InstructionValue::DeclareContext(instr) => {
23
- f(&mut instr.lvalue);
23
+ f(&mut instr.lvalue.identifier);
24
}
25
InstructionValue::DeclareLocal(instr) => {
26
- f(&mut instr.lvalue);
26
+ f(&mut instr.lvalue.identifier);
27
}
28
InstructionValue::StoreLocal(instr) => {
29
- f(&mut instr.lvalue);
29
+ f(&mut instr.lvalue.identifier);
30
+ }
31
+ InstructionValue::Destructure(instr) => {
32
+ instr.pattern.each_operand(f);
33
}
34
InstructionValue::Array(_)
35
| InstructionValue::Binary(_)
@@ -43,18 +46,19 @@ impl Instruction {
46
47
pub fn try_each_identifier_store<F, E>(&mut self, mut f: F) -> Result<(), E>
48
where
46
- F: FnMut(&mut LValue) -> Result<(), E>,
49
+ F: FnMut(&mut IdentifierOperand) -> Result<(), E>,
50
{
51
match &mut self.value {
52
InstructionValue::DeclareContext(instr) => {
50
- f(&mut instr.lvalue)?;
53
+ f(&mut instr.lvalue.identifier)?;
54
}
55
InstructionValue::DeclareLocal(instr) => {
53
- f(&mut instr.lvalue)?;
56
+ f(&mut instr.lvalue.identifier)?;
57
}
58
InstructionValue::StoreLocal(instr) => {
56
- f(&mut instr.lvalue)?;
59
+ f(&mut instr.lvalue.identifier)?;
60
}
61
+ InstructionValue::Destructure(instr) => instr.pattern.try_each_operand(f)?,
62
InstructionValue::Array(_)
63
| InstructionValue::Binary(_)
64
| InstructionValue::Call(_)
@@ -73,21 +77,23 @@ impl Instruction {
77
where
78
F: FnMut(&mut IdentifierOperand) -> (),
79
{
76
- match &mut self.value {
77
- InstructionValue::LoadLocal(instr) => f(&mut instr.place),
78
- InstructionValue::Array(_)
79
- | InstructionValue::Binary(_)
80
- | InstructionValue::Call(_)
81
- | InstructionValue::DeclareContext(_)
82
- | InstructionValue::DeclareLocal(_)
83
- | InstructionValue::LoadContext(_)
84
- | InstructionValue::LoadGlobal(_)
85
- | InstructionValue::Primitive(_)
86
- | InstructionValue::StoreLocal(_)
87
- | InstructionValue::Function(_)
88
- | InstructionValue::JSXElement(_)
89
- | InstructionValue::Tombstone => {}
90
- }
80
+ // match &mut self.value {
81
+ // InstructionValue::LoadLocal(instr) => f(&mut instr.place),
82
+ // InstructionValue::Array(_)
83
+ // | InstructionValue::Binary(_)
84
+ // | InstructionValue::Call(_)
85
+ // | InstructionValue::DeclareContext(_)
86
+ // | InstructionValue::DeclareLocal(_)
87
+ // | InstructionValue::Destructure(_)
88
+ // | InstructionValue::LoadContext(_)
89
+ // | InstructionValue::LoadGlobal(_)
90
+ // | InstructionValue::Primitive(_)
91
+ // | InstructionValue::StoreLocal(_)
92
+ // | InstructionValue::Function(_)
93
+ // | InstructionValue::JSXElement(_)
94
+ // | InstructionValue::Tombstone => {}
95
+ // }
96
+ self.each_operand(f);
97
}
98
99
pub fn each_operand<F>(&mut self, mut f: F) -> ()
@@ -139,6 +145,9 @@ impl Instruction {
145
}
146
}
147
}
148
+ InstructionValue::Destructure(value) => {
149
+ f(&mut value.value);
150
+ }
151
InstructionValue::DeclareContext(_)
152
| InstructionValue::LoadContext(_)
153
| InstructionValue::LoadGlobal(_)
@@ -162,7 +171,7 @@ pub enum InstructionValue {
171
// Debugger(Debugger),
172
DeclareContext(DeclareContext),
173
DeclareLocal(DeclareLocal),
165
- // Destructure(Destructure),
174
+ Destructure(Destructure),
175
Function(FunctionExpression),
176
JSXElement(JSXElement),
177
// JsxFragment(JsxFragment),
@@ -272,6 +281,94 @@ pub enum JSXAttribute {
281
},
282
}
283
284
+#[derive(Debug)]
285
+pub struct Destructure {
286
+ pub kind: InstructionKind,
287
+ pub pattern: DestructurePattern,
288
+ pub value: IdentifierOperand,
289
+}
290
+
291
+#[derive(Debug)]
292
+pub enum DestructurePattern {
293
+ Array(Vec<ArrayDestructureItem>),
294
+ Object(Vec<ObjectDestructureItem>),
295
+}
296
+
297
+impl DestructurePattern {
298
+ pub fn try_each_operand<E, F>(&mut self, mut f: F) -> Result<(), E>
299
+ where
300
+ F: FnMut(&mut IdentifierOperand) -> Result<(), E>,
301
+ {
302
+ match self {
303
+ Self::Array(elements) => {
304
+ for item in elements {
305
+ match item {
306
+ ArrayDestructureItem::Hole => { /* no-op */ }
307
+ ArrayDestructureItem::Value(item) => f(item)?,
308
+ ArrayDestructureItem::Spread(item) => f(item)?,
309
+ }
310
+ }
311
+ }
312
+ Self::Object(properties) => {
313
+ for property in properties {
314
+ match property {
315
+ ObjectDestructureItem::Property(property) => {
316
+ f(&mut property.value)?;
317
+ }
318
+ ObjectDestructureItem::Spread(property) => f(property)?,
319
+ }
320
+ }
321
+ }
322
+ }
323
+ Ok(())
324
+ }
325
+ pub fn each_operand<F>(&mut self, mut f: F) -> ()
326
+ where
327
+ F: FnMut(&mut IdentifierOperand) -> (),
328
+ {
329
+ match self {
330
+ Self::Array(elements) => {
331
+ for item in elements {
332
+ match item {
333
+ ArrayDestructureItem::Hole => { /* no-op */ }
334
+ ArrayDestructureItem::Value(item) => f(item),
335
+ ArrayDestructureItem::Spread(item) => f(item),
336
+ }
337
+ }
338
+ }
339
+ Self::Object(properties) => {
340
+ for property in properties {
341
+ match property {
342
+ ObjectDestructureItem::Property(property) => {
343
+ f(&mut property.value);
344
+ }
345
+ ObjectDestructureItem::Spread(property) => f(property),
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
351
+}
352
+
353
+#[derive(Debug)]
354
+pub enum ArrayDestructureItem {
355
+ Hole,
356
+ Value(IdentifierOperand),
357
+ Spread(IdentifierOperand),
358
+}
359
+
360
+#[derive(Debug)]
361
+pub enum ObjectDestructureItem {
362
+ Property(ObjectDestructureProperty),
363
+ Spread(IdentifierOperand),
364
+}
365
+
366
+#[derive(Debug)]
367
+pub struct ObjectDestructureProperty {
368
+ pub name: String,
369
+ pub value: IdentifierOperand,
370
+}
371
+
372
#[derive(Clone, Debug)]
373
pub struct IdentifierOperand {
374
pub identifier: Identifier,
compiler/forget/crates/forget_hir/src/print.rs
+57
-2
@@ -4,8 +4,9 @@ use forget_estree::JsValue;
4
use forget_utils::ensure_sufficient_stack;
5
6
use crate::{
7
- BasicBlock, Function, Identifier, IdentifierOperand, Instruction, InstructionValue, LValue,
8
- Phi, PlaceOrSpread, Terminal, TerminalValue, HIR,
7
+ ArrayDestructureItem, BasicBlock, DestructurePattern, Function, Identifier, IdentifierOperand,
8
+ Instruction, InstructionValue, LValue, ObjectDestructureItem, Phi, PlaceOrSpread, Terminal,
9
+ TerminalValue, HIR,
10
};
11
12
/// Trait for HIR types to describe how they print themselves.
@@ -205,6 +206,12 @@ impl Print for InstructionValue {
206
.collect();
207
write!(out, "{}", lines.join("\n"))?;
208
}
209
+ InstructionValue::Destructure(value) => {
210
+ write!(out, "Destructure ")?;
211
+ value.pattern.print(hir, out)?;
212
+ write!(out, " = ")?;
213
+ value.value.print(hir, out)?;
214
+ }
215
InstructionValue::Tombstone => {
216
write!(out, "Tombstone!")?;
217
}
@@ -262,6 +269,54 @@ impl Print for Identifier {
269
}
270
}
271
272
+impl Print for DestructurePattern {
273
+ fn print(&self, hir: &HIR, out: &mut impl Write) -> Result {
274
+ match self {
275
+ DestructurePattern::Array(items) => {
276
+ write!(out, "[ ")?;
277
+ for (index, item) in items.iter().enumerate() {
278
+ if index != 0 {
279
+ write!(out, ", ")?;
280
+ }
281
+ match item {
282
+ ArrayDestructureItem::Hole => {
283
+ write!(out, "<hole>")?;
284
+ }
285
+ ArrayDestructureItem::Value(item) => {
286
+ item.print(hir, out)?;
287
+ }
288
+ ArrayDestructureItem::Spread(item) => {
289
+ write!(out, "...")?;
290
+ item.print(hir, out)?;
291
+ }
292
+ }
293
+ }
294
+ write!(out, " ]")?;
295
+ }
296
+ DestructurePattern::Object(properties) => {
297
+ write!(out, "{{ ")?;
298
+ for (index, property) in properties.iter().enumerate() {
299
+ if index != 0 {
300
+ write!(out, ", ")?;
301
+ }
302
+ match property {
303
+ ObjectDestructureItem::Property(property) => {
304
+ write!(out, "{}: ", &property.name)?;
305
+ property.value.print(hir, out)?;
306
+ }
307
+ ObjectDestructureItem::Spread(property) => {
308
+ write!(out, "...")?;
309
+ property.print(hir, out)?;
310
+ }
311
+ }
312
+ }
313
+ write!(out, " }}")?;
314
+ }
315
+ }
316
+ Ok(())
317
+ }
318
+}
319
+
320
impl Print for Terminal {
321
fn print(&self, hir: &HIR, out: &mut impl Write) -> Result {
322
write!(out, " {} ", self.id)?;
compiler/forget/crates/forget_semantic_analysis/src/analyzer.rs
+28
-23
@@ -6,7 +6,8 @@ use forget_estree::{
6
};
7
8
use crate::{
9
- AstNode, DeclarationKind, LabelId, LabelKind, ReferenceKind, ScopeId, ScopeKind, ScopeManager,
9
+ AstNode, DeclarationKind, Label, LabelId, LabelKind, ReferenceKind, ScopeId, ScopeKind,
10
+ ScopeManager,
11
};
12
13
pub fn analyze(ast: &Program) -> ScopeManager {
@@ -43,18 +44,18 @@ impl Analyzer {
44
assert_eq!(last, id);
45
}
46
46
- fn lookup_break(&self, name: Option<&str>) -> Option<LabelId> {
47
+ fn lookup_break(&self, name: Option<&str>) -> Option<&Label> {
48
for id in self.labels.iter().rev() {
49
let label = self.manager.label(*id);
50
match (name, &label.name) {
51
// If this is a labeled break, only return if an exact match
52
// is in scope
53
(Some(name), Some(label_name)) if name == label_name => {
53
- return Some(label.id);
54
+ return Some(label);
55
}
56
// If this is an unlabeld break, return the innermost label id
57
(None, _) => {
57
- return Some(label.id);
58
+ return Some(label);
59
}
60
_ => { /* no-op */ }
61
}
@@ -62,22 +63,18 @@ impl Analyzer {
63
None
64
}
65
65
- fn lookup_continue(&self, name: Option<&str>) -> Option<LabelId> {
66
+ fn lookup_continue(&self, name: Option<&str>) -> Option<&Label> {
67
for id in self.labels.iter().rev() {
68
let label = self.manager.label(*id);
68
- // Skip labels that are not for loops, can only continue to a loop
69
- if label.kind != LabelKind::Loop {
70
- continue;
71
- }
69
match (name, &label.name) {
70
// If this is a labeled break, only return if an exact match
71
// is in scope
72
(Some(name), Some(label_name)) if &name == label_name => {
76
- return Some(label.id);
73
+ return Some(label);
74
}
75
// If this is an unlabeld break, return the innermost label id
76
(None, _) => {
80
- return Some(label.id);
77
+ return Some(label);
78
}
79
_ => { /* no-op */ }
80
}
@@ -425,16 +422,14 @@ impl Visitor for Analyzer {
422
}
423
424
fn visit_break_statement(&mut self, ast: &forget_estree::BreakStatement) {
428
- if let Some(label_id) =
429
- self.lookup_break(ast.label.as_ref().map(|ident| ident.name.as_str()))
425
+ if let Some(label) = self.lookup_break(ast.label.as_ref().map(|ident| ident.name.as_str()))
426
{
431
- self.manager
432
- .node_labels
433
- .insert(AstNode::from(ast), label_id);
427
+ let id = label.id;
428
+ self.manager.node_labels.insert(AstNode::from(ast), id);
429
if let Some(label_node) = &ast.label {
430
self.manager
431
.node_labels
437
- .insert(AstNode::from(label_node), label_id);
432
+ .insert(AstNode::from(label_node), id);
433
}
434
} else {
435
self.manager.diagnostics.push(Diagnostic::invalid_syntax(
@@ -462,21 +457,31 @@ impl Visitor for Analyzer {
457
}
458
459
fn visit_continue_statement(&mut self, ast: &forget_estree::ContinueStatement) {
465
- if let Some(label_id) =
460
+ let range = ast
461
+ .label
462
+ .as_ref()
463
+ .map(|label| label.range)
464
+ .unwrap_or(ast.range);
465
+ if let Some(label) =
466
self.lookup_continue(ast.label.as_ref().map(|ident| ident.name.as_str()))
467
{
468
- self.manager
469
- .node_labels
470
- .insert(AstNode::from(ast), label_id);
468
+ let id = label.id;
469
+ if label.kind != LabelKind::Loop {
470
+ self.manager.diagnostics.push(Diagnostic::invalid_syntax(
471
+ "Invalid continue statement, the named label must be for a loop",
472
+ range,
473
+ ));
474
+ }
475
+ self.manager.node_labels.insert(AstNode::from(ast), id);
476
if let Some(label_node) = &ast.label {
477
self.manager
478
.node_labels
474
- .insert(AstNode::from(label_node), label_id);
479
+ .insert(AstNode::from(label_node), id);
480
}
481
} else {
482
self.manager.diagnostics.push(Diagnostic::invalid_syntax(
483
"Non-syntactic continue, could not resolve continue target",
479
- ast.range,
484
+ range,
485
));
486
}
487
}
compiler/forget/crates/forget_ssa/src/eliminate_redundant_phis.rs
+1
-3
@@ -70,9 +70,7 @@ pub fn eliminate_redundant_phis(env: &Environment, fun: &mut Function) {
70
71
for instr_ix in block.instructions.iter() {
72
let instr = &mut hir.instructions[usize::from(*instr_ix)];
73
- instr.each_identifier_store(|store| {
74
- rewrite(&rewrites, &mut store.identifier.identifier)
75
- });
73
+ instr.each_identifier_store(|store| rewrite(&rewrites, &mut store.identifier));
74
instr.each_identifier_load(|load| rewrite(&rewrites, &mut load.identifier));
75
76
if let InstructionValue::Function(fun) = &mut instr.value {
compiler/forget/crates/forget_ssa/src/enter.rs
+5
-4
@@ -47,6 +47,7 @@ fn visit_instructions<'e, 'f>(
47
builder.each_block(|block, builder| {
48
for instr_ix in &block.instructions {
49
let instr = &mut instructions[usize::from(*instr_ix)];
50
+ builder.visit_store(&mut instr.lvalue)?;
51
instr.try_each_identifier_store(|store| builder.visit_store(store))?;
52
instr.each_identifier_load(|load| builder.visit_load(load));
53
@@ -139,8 +140,8 @@ impl<'e, 'f> Builder<'e, 'f> {
140
self.env.next_identifier_id()
141
}
142
142
- fn visit_store(&mut self, lvalue: &mut LValue) -> Result<(), Diagnostic> {
143
- let old_identifier = &lvalue.identifier.identifier;
143
+ fn visit_store(&mut self, lvalue: &mut IdentifierOperand) -> Result<(), Diagnostic> {
144
+ let old_identifier = &lvalue.identifier;
145
// TODO: use Result (?)
146
invariant(!self.unknown.contains(&old_identifier.id), || {
147
Diagnostic::invariant(
@@ -151,14 +152,14 @@ impl<'e, 'f> Builder<'e, 'f> {
152
153
if self.context.contains(&old_identifier.id) {
154
let new_identifier = self.get_id_at(self.current, old_identifier);
154
- lvalue.identifier.identifier = new_identifier;
155
+ lvalue.identifier = new_identifier;
156
return Ok(());
157
}
158
159
let new_identifier = self.make_identifier(old_identifier);
160
let state = self.states.get_mut(&self.current).unwrap();
161
state.defs.insert(old_identifier.id, new_identifier.clone());
161
- lvalue.identifier.identifier = new_identifier;
162
+ lvalue.identifier = new_identifier;
163
Ok(())
164
}
165