mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[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.
This commit is contained in:
@@ -2,14 +2,15 @@ use std::collections::HashSet;
|
||||
|
||||
use forget_diagnostics::Diagnostic;
|
||||
use forget_estree::{
|
||||
AssignmentTarget, BlockStatement, Expression, ExpressionOrSpread, ExpressionOrSuper, ForInit,
|
||||
Function, IntoFunction, JsValue, Pattern, Statement, VariableDeclaration,
|
||||
VariableDeclarationKind,
|
||||
AssignmentPropertyOrRestElement, AssignmentTarget, BlockStatement, Expression,
|
||||
ExpressionOrSpread, ExpressionOrSuper, ForInit, Function, IntoFunction, JsValue, Pattern,
|
||||
Statement, VariableDeclaration, VariableDeclarationKind,
|
||||
};
|
||||
use forget_hir::{
|
||||
BlockKind, BranchTerminal, Environment, ForTerminal, GotoKind, IdentifierOperand,
|
||||
InstructionKind, InstructionValue, JSXAttribute, JSXElement, LValue, LoadGlobal, LoadLocal,
|
||||
PlaceOrSpread, TerminalValue,
|
||||
ArrayDestructureItem, BlockKind, BranchTerminal, Destructure, DestructurePattern, Environment,
|
||||
ForTerminal, GotoKind, Identifier, IdentifierOperand, InstructionKind, InstructionValue,
|
||||
JSXAttribute, JSXElement, LValue, LoadGlobal, LoadLocal, ObjectDestructureItem,
|
||||
ObjectDestructureProperty, PlaceOrSpread, TerminalValue,
|
||||
};
|
||||
|
||||
use crate::builder::{Builder, LoopScope};
|
||||
@@ -303,8 +304,8 @@ fn lower_variable_declaration(
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(Diagnostic::todo(
|
||||
"Handle non-identifier variable declarations",
|
||||
return Err(Diagnostic::invalid_syntax(
|
||||
"Expected an identifier for variable declaration without an intializer. Destructuring requires an initial value",
|
||||
declaration.range,
|
||||
));
|
||||
}
|
||||
@@ -543,6 +544,7 @@ fn lower_assignment(
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: change the success type to void, no caller uses it
|
||||
fn lower_assignment_pattern(
|
||||
env: &Environment,
|
||||
builder: &mut Builder,
|
||||
@@ -558,6 +560,147 @@ fn lower_assignment_pattern(
|
||||
value,
|
||||
}))
|
||||
}
|
||||
Pattern::ArrayPattern(lvalue) => {
|
||||
let mut items = Vec::with_capacity(lvalue.elements.len());
|
||||
let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
|
||||
for element in &lvalue.elements {
|
||||
match element {
|
||||
None => items.push(ArrayDestructureItem::Hole),
|
||||
Some(Pattern::Identifier(element)) => {
|
||||
let identifier =
|
||||
lower_identifier_for_assignment(env, builder, kind, &element)?;
|
||||
items.push(ArrayDestructureItem::Value(identifier));
|
||||
}
|
||||
Some(Pattern::RestElement(element)) => {
|
||||
if let Pattern::Identifier(element) = &element.argument {
|
||||
let identifier = lower_identifier_for_assignment(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
element.as_ref(),
|
||||
)?;
|
||||
items.push(ArrayDestructureItem::Spread(identifier));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
items.push(ArrayDestructureItem::Spread(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, &element.argument));
|
||||
}
|
||||
}
|
||||
Some(element) => {
|
||||
let temporary = env.new_temporary();
|
||||
items.push(ArrayDestructureItem::Value(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, element));
|
||||
}
|
||||
}
|
||||
}
|
||||
let temporary = builder.push(InstructionValue::Destructure(Destructure {
|
||||
kind,
|
||||
pattern: DestructurePattern::Array(items),
|
||||
value,
|
||||
}));
|
||||
for (temporary, pattern) in followups {
|
||||
lower_assignment_pattern(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
pattern,
|
||||
IdentifierOperand {
|
||||
identifier: temporary,
|
||||
effect: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
temporary
|
||||
}
|
||||
Pattern::ObjectPattern(lvalue) => {
|
||||
let mut properties = Vec::with_capacity(lvalue.properties.len());
|
||||
let mut followups: Vec<(Identifier, &Pattern)> = Vec::new();
|
||||
|
||||
for property in &lvalue.properties {
|
||||
match property {
|
||||
AssignmentPropertyOrRestElement::RestElement(property) => {
|
||||
if let Pattern::Identifier(element) = &property.argument {
|
||||
let identifier = lower_identifier_for_assignment(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
element.as_ref(),
|
||||
)?;
|
||||
properties.push(ObjectDestructureItem::Spread(identifier));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
properties.push(ObjectDestructureItem::Spread(IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
}));
|
||||
followups.push((temporary, &property.argument));
|
||||
}
|
||||
}
|
||||
AssignmentPropertyOrRestElement::AssignmentProperty(property) => {
|
||||
if property.is_computed {
|
||||
return Err(Diagnostic::todo(
|
||||
"Handle computed properties in ObjectPattern",
|
||||
property.range,
|
||||
));
|
||||
}
|
||||
let key = if let Expression::Identifier(key) = &property.key {
|
||||
key.name.as_str()
|
||||
} else {
|
||||
return Err(Diagnostic::todo(
|
||||
"Support non-identifier object keys in non-computed ObjectPattern",
|
||||
property.range,
|
||||
));
|
||||
};
|
||||
if let Pattern::Identifier(value) = &property.value {
|
||||
let value = lower_identifier_for_assignment(env, builder, kind, value)?;
|
||||
properties.push(ObjectDestructureItem::Property(
|
||||
ObjectDestructureProperty {
|
||||
name: key.to_string(),
|
||||
value,
|
||||
},
|
||||
));
|
||||
} else {
|
||||
let temporary = env.new_temporary();
|
||||
properties.push(ObjectDestructureItem::Property(
|
||||
ObjectDestructureProperty {
|
||||
name: key.to_string(),
|
||||
value: IdentifierOperand {
|
||||
identifier: temporary.clone(),
|
||||
effect: None,
|
||||
},
|
||||
},
|
||||
));
|
||||
followups.push((temporary, &property.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let temporary = builder.push(InstructionValue::Destructure(Destructure {
|
||||
kind,
|
||||
pattern: DestructurePattern::Object(properties),
|
||||
value,
|
||||
}));
|
||||
for (temporary, pattern) in followups {
|
||||
lower_assignment_pattern(
|
||||
env,
|
||||
builder,
|
||||
kind,
|
||||
pattern,
|
||||
IdentifierOperand {
|
||||
identifier: temporary,
|
||||
effect: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
temporary
|
||||
}
|
||||
_ => todo!("lower assignment pattern for {:#?}", lvalue),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
function Component(a, b) {
|
||||
const [c, , ...d] = a;
|
||||
const [[[e]], ...[f]] = b;
|
||||
return [c, d, e, f];
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
function Component(a, b) {
|
||||
const {
|
||||
c,
|
||||
d,
|
||||
e: { e },
|
||||
f: { _f: f },
|
||||
g: {
|
||||
g: {
|
||||
g: { g, ...h },
|
||||
},
|
||||
},
|
||||
...i
|
||||
} = a;
|
||||
return [c, d, e, f, g, h, i];
|
||||
}
|
||||
@@ -38,6 +38,7 @@ fn fixtures() {
|
||||
match build(&environment, &fun.function) {
|
||||
Ok(mut fun) => {
|
||||
println!("ok build");
|
||||
fun.debug();
|
||||
enter_ssa(&environment, &mut fun).unwrap();
|
||||
println!("ok enter_ssa");
|
||||
eliminate_redundant_phis(&environment, &mut fun);
|
||||
|
||||
+70
-26
@@ -45,29 +45,73 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $0 = 1
|
||||
[1] unknown $2 = StoreLocal Let unknown a$39 = unknown $0
|
||||
[2] unknown $4 = DeclareLocal Let unknown b$40
|
||||
[3] unknown $9 = 1
|
||||
[4] unknown $10 = 1
|
||||
[5] unknown $11 = true
|
||||
[6] unknown $5 = true
|
||||
[7] unknown $6 = StoreLocal Reassign unknown b$41 = unknown $5
|
||||
[8] unknown $13 = DeclareLocal Let unknown c$43
|
||||
[9] unknown $18 = true
|
||||
[10] unknown $14 = "hello"
|
||||
[11] unknown $15 = StoreLocal Reassign unknown c$45 = unknown $14
|
||||
[12] unknown $20 = DeclareLocal Let unknown d$47
|
||||
[13] unknown $25 = "hello"
|
||||
[14] unknown $26 = "hello"
|
||||
[15] unknown $27 = true
|
||||
[16] unknown $21 = 42
|
||||
[17] unknown $22 = StoreLocal Reassign unknown d$49 = unknown $21
|
||||
[18] unknown $29 = DeclareLocal Let unknown e$51
|
||||
[19] unknown $34 = 42
|
||||
[20] unknown $35 = 42
|
||||
[21] unknown $36 = true
|
||||
[22] unknown $30 = "ok"
|
||||
[23] unknown $31 = StoreLocal Reassign unknown e$53 = unknown $30
|
||||
[24] unknown $37 = "ok"
|
||||
[25] Return unknown $37
|
||||
[0] unknown $39 = 1
|
||||
[1] unknown $40 = StoreLocal Let unknown a$41 = unknown $39
|
||||
[2] unknown $42 = DeclareLocal Let unknown b$43
|
||||
[3] unknown $44 = LoadLocal unknown a$1
|
||||
[4] unknown $45 = 1
|
||||
[5] unknown $46 = Binary unknown $44 === unknown $45
|
||||
[6] If unknown $11 consequent=bb2 alternate=bb3 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[7] unknown $47 = true
|
||||
[8] unknown $48 = StoreLocal Reassign unknown b$49 = unknown $47
|
||||
[9] Goto bb1
|
||||
bb3 (block)
|
||||
predecessors: bb0
|
||||
[10] unknown $50 = false
|
||||
[11] unknown $51 = StoreLocal Reassign unknown b$52 = unknown $50
|
||||
[12] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb2, bb3
|
||||
[13] unknown $53 = DeclareLocal Let unknown c$54
|
||||
[14] unknown $55 = LoadLocal unknown b$3
|
||||
[15] If unknown $18 consequent=bb5 alternate=bb6 fallthrough=bb4
|
||||
bb5 (block)
|
||||
predecessors: bb1
|
||||
[16] unknown $56 = "hello"
|
||||
[17] unknown $57 = StoreLocal Reassign unknown c$58 = unknown $56
|
||||
[18] Goto bb4
|
||||
bb6 (block)
|
||||
predecessors: bb1
|
||||
[19] unknown $59 = null
|
||||
[20] unknown $60 = StoreLocal Reassign unknown c$61 = unknown $59
|
||||
[21] Goto bb4
|
||||
bb4 (block)
|
||||
predecessors: bb5, bb6
|
||||
[22] unknown $62 = DeclareLocal Let unknown d$63
|
||||
[23] unknown $64 = LoadLocal unknown c$12
|
||||
[24] unknown $65 = "hello"
|
||||
[25] unknown $66 = Binary unknown $64 === unknown $65
|
||||
[26] If unknown $27 consequent=bb8 alternate=bb9 fallthrough=bb7
|
||||
bb8 (block)
|
||||
predecessors: bb4
|
||||
[27] unknown $67 = 42
|
||||
[28] unknown $68 = StoreLocal Reassign unknown d$69 = unknown $67
|
||||
[29] Goto bb7
|
||||
bb9 (block)
|
||||
predecessors: bb4
|
||||
[30] unknown $70 = 42.001
|
||||
[31] unknown $71 = StoreLocal Reassign unknown d$72 = unknown $70
|
||||
[32] Goto bb7
|
||||
bb7 (block)
|
||||
predecessors: bb8, bb9
|
||||
[33] unknown $73 = DeclareLocal Let unknown e$74
|
||||
[34] unknown $75 = LoadLocal unknown d$19
|
||||
[35] unknown $76 = 42
|
||||
[36] unknown $77 = Binary unknown $75 === unknown $76
|
||||
[37] If unknown $36 consequent=bb11 alternate=bb12 fallthrough=bb10
|
||||
bb11 (block)
|
||||
predecessors: bb7
|
||||
[38] unknown $78 = "ok"
|
||||
[39] unknown $79 = StoreLocal Reassign unknown e$80 = unknown $78
|
||||
[40] Goto bb10
|
||||
bb12 (block)
|
||||
predecessors: bb7
|
||||
[41] unknown $81 = "nope"
|
||||
[42] unknown $82 = StoreLocal Reassign unknown e$83 = unknown $81
|
||||
[43] Goto bb10
|
||||
bb10 (block)
|
||||
predecessors: bb11, bb12
|
||||
[44] unknown $84 = LoadLocal unknown e$28
|
||||
[45] Return unknown $37
|
||||
|
||||
+103
-105
@@ -72,127 +72,125 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $2 = DeclareLocal Let unknown a$109
|
||||
[1] unknown $3 = LoadGlobal Math
|
||||
[2] unknown $4 = StoreLocal Reassign unknown a$110 = unknown $3
|
||||
[3] unknown $5 = LoadGlobal Math
|
||||
[4] unknown $7 = DeclareLocal Let unknown b$111
|
||||
[5] unknown $12 = LoadLocal unknown props$108
|
||||
[0] unknown $109 = DeclareLocal Let unknown a$110
|
||||
[1] unknown $111 = LoadGlobal Math
|
||||
[2] unknown $112 = StoreLocal Reassign unknown a$113 = unknown $111
|
||||
[3] unknown $114 = LoadLocal unknown a$1
|
||||
[4] unknown $115 = DeclareLocal Let unknown b$116
|
||||
[5] unknown $117 = LoadLocal unknown props$0
|
||||
[6] If unknown $12 consequent=bb2 alternate=bb3 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[7] unknown $8 = true
|
||||
[8] unknown $9 = StoreLocal Reassign unknown b$112 = unknown $8
|
||||
[7] unknown $118 = true
|
||||
[8] unknown $119 = StoreLocal Reassign unknown b$120 = unknown $118
|
||||
[9] Goto bb1
|
||||
bb3 (block)
|
||||
predecessors: bb0
|
||||
[10] unknown $10 = true
|
||||
[11] unknown $11 = StoreLocal Reassign unknown b$113 = unknown $10
|
||||
[10] unknown $121 = true
|
||||
[11] unknown $122 = StoreLocal Reassign unknown b$123 = unknown $121
|
||||
[12] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb2, bb3
|
||||
b$114: phi(bb2: b$112, bb3: b$113)
|
||||
[13] unknown $13 = true
|
||||
[14] unknown $15 = DeclareLocal Let unknown c$115
|
||||
[15] unknown $20 = LoadLocal unknown props$108
|
||||
[13] unknown $124 = LoadLocal unknown b$6
|
||||
[14] unknown $125 = DeclareLocal Let unknown c$126
|
||||
[15] unknown $127 = LoadLocal unknown props$0
|
||||
[16] If unknown $20 consequent=bb5 alternate=bb6 fallthrough=bb4
|
||||
bb5 (block)
|
||||
predecessors: bb1
|
||||
[17] unknown $16 = true
|
||||
[18] unknown $17 = StoreLocal Reassign unknown c$117 = unknown $16
|
||||
[17] unknown $128 = true
|
||||
[18] unknown $129 = StoreLocal Reassign unknown c$130 = unknown $128
|
||||
[19] Goto bb4
|
||||
bb6 (block)
|
||||
predecessors: bb1
|
||||
[20] unknown $18 = 42
|
||||
[21] unknown $19 = StoreLocal Reassign unknown c$118 = unknown $18
|
||||
[20] unknown $131 = 42
|
||||
[21] unknown $132 = StoreLocal Reassign unknown c$133 = unknown $131
|
||||
[22] Goto bb4
|
||||
bb4 (block)
|
||||
predecessors: bb5, bb6
|
||||
c$119: phi(bb5: c$117, bb6: c$118)
|
||||
[23] unknown $21 = LoadLocal unknown c$119
|
||||
[24] unknown $22 = 42
|
||||
[25] unknown $23 = 1
|
||||
[26] unknown $24 = 43
|
||||
[27] unknown $25 = 42
|
||||
[28] unknown $26 = 1
|
||||
[29] unknown $27 = 41
|
||||
[30] unknown $28 = 42
|
||||
[31] unknown $29 = 2
|
||||
[32] unknown $30 = 84
|
||||
[33] unknown $31 = 42
|
||||
[34] unknown $32 = 2
|
||||
[35] unknown $33 = 21
|
||||
[36] unknown $34 = 0
|
||||
[37] unknown $35 = 1
|
||||
[38] unknown $36 = false
|
||||
[39] unknown $37 = 0
|
||||
[40] unknown $38 = 1
|
||||
[41] unknown $39 = true
|
||||
[42] unknown $40 = 0
|
||||
[43] unknown $41 = 1
|
||||
[44] unknown $42 = false
|
||||
[45] unknown $43 = 0
|
||||
[46] unknown $44 = 1
|
||||
[47] unknown $45 = true
|
||||
[48] unknown $46 = 0
|
||||
[49] unknown $47 = 0
|
||||
[50] unknown $48 = true
|
||||
[51] unknown $49 = LoadGlobal NaN
|
||||
[52] unknown $50 = LoadGlobal NaN
|
||||
[53] unknown $51 = Binary unknown $49 == unknown $50
|
||||
[54] unknown $52 = LoadGlobal NaN
|
||||
[55] unknown $53 = LoadGlobal NaN
|
||||
[56] unknown $54 = Binary unknown $52 != unknown $53
|
||||
[57] unknown $55 = LoadGlobal NaN
|
||||
[58] unknown $56 = LoadGlobal NaN
|
||||
[59] unknown $57 = Binary unknown $55 !== unknown $56
|
||||
[60] unknown $58 = LoadGlobal NaN
|
||||
[61] unknown $59 = LoadGlobal NaN
|
||||
[62] unknown $60 = Binary unknown $58 !== unknown $59
|
||||
[63] unknown $61 = "hello"
|
||||
[64] unknown $62 = "hello"
|
||||
[65] unknown $63 = true
|
||||
[66] unknown $64 = "hello"
|
||||
[67] unknown $65 = "hello"
|
||||
[68] unknown $66 = false
|
||||
[69] unknown $67 = "hello"
|
||||
[70] unknown $68 = "hello"
|
||||
[71] unknown $69 = true
|
||||
[72] unknown $70 = "hello"
|
||||
[73] unknown $71 = "hello"
|
||||
[74] unknown $72 = false
|
||||
[75] unknown $73 = "hello"
|
||||
[76] unknown $74 = "world"
|
||||
[77] unknown $75 = false
|
||||
[78] unknown $76 = "hello"
|
||||
[79] unknown $77 = "world"
|
||||
[80] unknown $78 = true
|
||||
[81] unknown $79 = "hello"
|
||||
[82] unknown $80 = "world"
|
||||
[83] unknown $81 = false
|
||||
[84] unknown $82 = "hello"
|
||||
[85] unknown $83 = "world"
|
||||
[86] unknown $84 = true
|
||||
[87] unknown $85 = true
|
||||
[88] unknown $86 = true
|
||||
[89] unknown $87 = true
|
||||
[90] unknown $88 = true
|
||||
[91] unknown $89 = true
|
||||
[92] unknown $90 = false
|
||||
[93] unknown $91 = true
|
||||
[94] unknown $92 = true
|
||||
[95] unknown $93 = true
|
||||
[96] unknown $94 = true
|
||||
[97] unknown $95 = true
|
||||
[98] unknown $96 = false
|
||||
[99] unknown $97 = 5
|
||||
[100] unknown $98 = 60
|
||||
[101] unknown $99 = 300
|
||||
[102] unknown $100 = 60
|
||||
[103] unknown $101 = 18000
|
||||
[104] unknown $102 = 1000
|
||||
[105] unknown $103 = 18000000
|
||||
[106] unknown $105 = StoreLocal Let unknown x$120 = unknown $103
|
||||
[107] unknown $106 = 18000000
|
||||
[108] unknown $107 = <undefined>
|
||||
[23] unknown $134 = LoadLocal unknown c$14
|
||||
[24] unknown $135 = 42
|
||||
[25] unknown $136 = 1
|
||||
[26] unknown $137 = 43
|
||||
[27] unknown $138 = 42
|
||||
[28] unknown $139 = 1
|
||||
[29] unknown $140 = 41
|
||||
[30] unknown $141 = 42
|
||||
[31] unknown $142 = 2
|
||||
[32] unknown $143 = 84
|
||||
[33] unknown $144 = 42
|
||||
[34] unknown $145 = 2
|
||||
[35] unknown $146 = 21
|
||||
[36] unknown $147 = 0
|
||||
[37] unknown $148 = 1
|
||||
[38] unknown $149 = false
|
||||
[39] unknown $150 = 0
|
||||
[40] unknown $151 = 1
|
||||
[41] unknown $152 = true
|
||||
[42] unknown $153 = 0
|
||||
[43] unknown $154 = 1
|
||||
[44] unknown $155 = false
|
||||
[45] unknown $156 = 0
|
||||
[46] unknown $157 = 1
|
||||
[47] unknown $158 = true
|
||||
[48] unknown $159 = 0
|
||||
[49] unknown $160 = 0
|
||||
[50] unknown $161 = true
|
||||
[51] unknown $162 = LoadGlobal NaN
|
||||
[52] unknown $163 = LoadGlobal NaN
|
||||
[53] unknown $164 = Binary unknown $162 == unknown $163
|
||||
[54] unknown $165 = LoadGlobal NaN
|
||||
[55] unknown $166 = LoadGlobal NaN
|
||||
[56] unknown $167 = Binary unknown $165 != unknown $166
|
||||
[57] unknown $168 = LoadGlobal NaN
|
||||
[58] unknown $169 = LoadGlobal NaN
|
||||
[59] unknown $170 = Binary unknown $168 !== unknown $169
|
||||
[60] unknown $171 = LoadGlobal NaN
|
||||
[61] unknown $172 = LoadGlobal NaN
|
||||
[62] unknown $173 = Binary unknown $171 !== unknown $172
|
||||
[63] unknown $174 = "hello"
|
||||
[64] unknown $175 = "hello"
|
||||
[65] unknown $176 = true
|
||||
[66] unknown $177 = "hello"
|
||||
[67] unknown $178 = "hello"
|
||||
[68] unknown $179 = false
|
||||
[69] unknown $180 = "hello"
|
||||
[70] unknown $181 = "hello"
|
||||
[71] unknown $182 = true
|
||||
[72] unknown $183 = "hello"
|
||||
[73] unknown $184 = "hello"
|
||||
[74] unknown $185 = false
|
||||
[75] unknown $186 = "hello"
|
||||
[76] unknown $187 = "world"
|
||||
[77] unknown $188 = false
|
||||
[78] unknown $189 = "hello"
|
||||
[79] unknown $190 = "world"
|
||||
[80] unknown $191 = true
|
||||
[81] unknown $192 = "hello"
|
||||
[82] unknown $193 = "world"
|
||||
[83] unknown $194 = false
|
||||
[84] unknown $195 = "hello"
|
||||
[85] unknown $196 = "world"
|
||||
[86] unknown $197 = true
|
||||
[87] unknown $198 = true
|
||||
[88] unknown $199 = true
|
||||
[89] unknown $200 = true
|
||||
[90] unknown $201 = true
|
||||
[91] unknown $202 = true
|
||||
[92] unknown $203 = false
|
||||
[93] unknown $204 = true
|
||||
[94] unknown $205 = true
|
||||
[95] unknown $206 = true
|
||||
[96] unknown $207 = true
|
||||
[97] unknown $208 = true
|
||||
[98] unknown $209 = false
|
||||
[99] unknown $210 = 5
|
||||
[100] unknown $211 = 60
|
||||
[101] unknown $212 = 300
|
||||
[102] unknown $213 = 60
|
||||
[103] unknown $214 = 18000
|
||||
[104] unknown $215 = 1000
|
||||
[105] unknown $216 = 18000000
|
||||
[106] unknown $217 = StoreLocal Let unknown x$218 = unknown $216
|
||||
[107] unknown $219 = LoadLocal unknown x$104
|
||||
[108] unknown $220 = <undefined>
|
||||
[109] Return unknown $107
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
---
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/forget_fixtures/tests/fixtures/destructure-array.js
|
||||
---
|
||||
Input:
|
||||
function Component(a, b) {
|
||||
const [c, , ...d] = a;
|
||||
const [[[e]], ...[f]] = b;
|
||||
return [c, d, e, f];
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown a$22,
|
||||
unknown b$23,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $24 = LoadLocal unknown a$0
|
||||
[1] unknown $25 = Destructure [ unknown c$26, <hole>, ...unknown d$27 ] = unknown $24
|
||||
[2] unknown $28 = LoadLocal unknown b$1
|
||||
[3] unknown $29 = Destructure [ unknown $30, ...unknown $31 ] = unknown $28
|
||||
[4] unknown $32 = Destructure [ unknown $33 ] = unknown $30
|
||||
[5] unknown $34 = Destructure [ unknown e$35 ] = unknown $33
|
||||
[6] unknown $36 = Destructure [ unknown f$37 ] = unknown $31
|
||||
[7] unknown $38 = LoadLocal unknown c$3
|
||||
[8] unknown $39 = LoadLocal unknown d$4
|
||||
[9] unknown $40 = LoadLocal unknown e$12
|
||||
[10] unknown $41 = LoadLocal unknown f$14
|
||||
[11] unknown $42 = Array [unknown $38, unknown $39, unknown $40, unknown $41]
|
||||
[12] Return unknown $20
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
---
|
||||
source: crates/forget_fixtures/tests/fixtures_test.rs
|
||||
expression: "format!(\"Input:\\n{input}\\n\\nOutput:\\n{output}\")"
|
||||
input_file: crates/forget_fixtures/tests/fixtures/destructure-object.js
|
||||
---
|
||||
Input:
|
||||
function Component(a, b) {
|
||||
const {
|
||||
c,
|
||||
d,
|
||||
e: { e },
|
||||
f: { _f: f },
|
||||
g: {
|
||||
g: {
|
||||
g: { g, ...h },
|
||||
},
|
||||
},
|
||||
...i
|
||||
} = a;
|
||||
return [c, d, e, f, g, h, i];
|
||||
}
|
||||
|
||||
|
||||
Output:
|
||||
function Component(
|
||||
unknown a$30,
|
||||
unknown b$31,
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $32 = LoadLocal unknown a$0
|
||||
[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
|
||||
[2] unknown $40 = Destructure { e: unknown e$41 } = unknown $36
|
||||
[3] unknown $42 = Destructure { _f: unknown f$43 } = unknown $37
|
||||
[4] unknown $44 = Destructure { g: unknown $45 } = unknown $38
|
||||
[5] unknown $46 = Destructure { g: unknown $47 } = unknown $45
|
||||
[6] unknown $48 = Destructure { g: unknown g$49, ...unknown h$50 } = unknown $47
|
||||
[7] unknown $51 = LoadLocal unknown c$3
|
||||
[8] unknown $52 = LoadLocal unknown d$4
|
||||
[9] unknown $53 = LoadLocal unknown e$10
|
||||
[10] unknown $54 = LoadLocal unknown f$12
|
||||
[11] unknown $55 = LoadLocal unknown g$18
|
||||
[12] unknown $56 = LoadLocal unknown h$19
|
||||
[13] unknown $57 = LoadLocal unknown i$8
|
||||
[14] unknown $58 = Array [unknown $51, unknown $52, unknown $53, unknown $54, unknown $55, unknown $56, unknown $57]
|
||||
[15] Return unknown $28
|
||||
+16
-18
@@ -18,37 +18,35 @@ function foo(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $0 = 0
|
||||
[1] unknown $2 = StoreLocal Let unknown x$19 = unknown $0
|
||||
[0] unknown $19 = 0
|
||||
[1] unknown $20 = StoreLocal Let unknown x$21 = unknown $19
|
||||
[2] For init=bb3 test=bb1 update=bb4 body=bb5 fallthrough=bb2
|
||||
bb3 (loop)
|
||||
predecessors: bb0
|
||||
[3] unknown $3 = 0
|
||||
[4] unknown $5 = StoreLocal Let unknown i$20 = unknown $3
|
||||
[3] unknown $22 = 0
|
||||
[4] unknown $23 = StoreLocal Let unknown i$24 = unknown $22
|
||||
[5] Goto bb1
|
||||
bb1 (loop)
|
||||
predecessors: bb3, bb4
|
||||
i$21: phi(bb3: i$20, bb4: i$24)
|
||||
x$22: phi(bb3: x$19, bb4: x$23)
|
||||
[6] unknown $14 = LoadLocal unknown i$21
|
||||
[7] unknown $15 = 10
|
||||
[8] unknown $16 = Binary unknown $14 < unknown $15
|
||||
[6] unknown $25 = LoadLocal unknown i$4
|
||||
[7] unknown $26 = 10
|
||||
[8] unknown $27 = Binary unknown $25 < unknown $26
|
||||
[9] Branch unknown $16 consequent=bb5 alternate=bb2
|
||||
bb5 (block)
|
||||
predecessors: bb1
|
||||
[10] unknown $10 = LoadLocal unknown x$22
|
||||
[11] unknown $11 = LoadLocal unknown i$21
|
||||
[12] unknown $12 = Binary unknown $10 + unknown $11
|
||||
[13] unknown $13 = StoreLocal Reassign unknown x$23 = unknown $12
|
||||
[10] unknown $28 = LoadLocal unknown x$1
|
||||
[11] unknown $29 = LoadLocal unknown i$4
|
||||
[12] unknown $30 = Binary unknown $28 + unknown $29
|
||||
[13] unknown $31 = StoreLocal Reassign unknown x$32 = unknown $30
|
||||
[14] Goto bb4
|
||||
bb4 (loop)
|
||||
predecessors: bb5
|
||||
[15] unknown $6 = LoadLocal unknown i$21
|
||||
[16] unknown $7 = 1
|
||||
[17] unknown $8 = Binary unknown $6 + unknown $7
|
||||
[18] unknown $9 = StoreLocal Reassign unknown i$24 = unknown $8
|
||||
[15] unknown $33 = LoadLocal unknown i$4
|
||||
[16] unknown $34 = 1
|
||||
[17] unknown $35 = Binary unknown $33 + unknown $34
|
||||
[18] unknown $36 = StoreLocal Reassign unknown i$37 = unknown $35
|
||||
[19] Goto bb1
|
||||
bb2 (block)
|
||||
predecessors: bb1
|
||||
[20] unknown $17 = LoadLocal unknown x$22
|
||||
[20] unknown $38 = LoadLocal unknown x$1
|
||||
[21] Return unknown $17
|
||||
|
||||
+61
-49
@@ -33,62 +33,74 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $1 = 2
|
||||
[1] unknown $3 = StoreLocal Const unknown x$59 = unknown $1
|
||||
[2] unknown $54 = Function @deps[] @context[unknown x$59]:
|
||||
[0] unknown $59 = 2
|
||||
[1] unknown $60 = StoreLocal Const unknown x$61 = unknown $59
|
||||
[2] unknown $62 = Function @deps[] @context[unknown x$61]:
|
||||
function foo(
|
||||
unknown y$60,
|
||||
unknown y$63,
|
||||
)
|
||||
entry bb1
|
||||
bb1 (block)
|
||||
[0] unknown $5 = 1
|
||||
[1] unknown $7 = StoreLocal Let unknown a$61 = unknown $5
|
||||
[2] unknown $9 = DeclareLocal Let unknown b$62
|
||||
[3] unknown $16 = 1
|
||||
[4] unknown $17 = 1
|
||||
[5] unknown $18 = true
|
||||
[6] unknown $10 = 5
|
||||
[7] unknown $11 = 3
|
||||
[8] unknown $12 = 8
|
||||
[9] unknown $13 = StoreLocal Reassign unknown b$63 = unknown $12
|
||||
[10] unknown $19 = 2
|
||||
[11] unknown $20 = LoadLocal unknown y$60
|
||||
[12] unknown $21 = Binary unknown $19 + unknown $20
|
||||
[13] unknown $22 = 1
|
||||
[14] unknown $23 = Binary unknown $21 + unknown $22
|
||||
[15] unknown $24 = 8
|
||||
[16] unknown $25 = Binary unknown $23 + unknown $24
|
||||
[17] unknown $48 = Function @deps[] @context[unknown x$59, unknown y$60, unknown a$61, unknown b$63]:
|
||||
[0] unknown $64 = 1
|
||||
[1] unknown $65 = StoreLocal Let unknown a$66 = unknown $64
|
||||
[2] unknown $67 = DeclareLocal Let unknown b$68
|
||||
[3] unknown $69 = LoadLocal unknown a$6
|
||||
[4] unknown $70 = 1
|
||||
[5] unknown $71 = Binary unknown $69 === unknown $70
|
||||
[6] If unknown $18 consequent=bb3 alternate=bb4 fallthrough=bb2
|
||||
bb3 (block)
|
||||
predecessors: bb1
|
||||
[7] unknown $72 = 5
|
||||
[8] unknown $73 = 3
|
||||
[9] unknown $74 = 8
|
||||
[10] unknown $75 = StoreLocal Reassign unknown b$76 = unknown $74
|
||||
[11] Goto bb2
|
||||
bb4 (block)
|
||||
predecessors: bb1
|
||||
[12] unknown $77 = false
|
||||
[13] unknown $78 = StoreLocal Reassign unknown b$79 = unknown $77
|
||||
[14] Goto bb2
|
||||
bb2 (block)
|
||||
predecessors: bb3, bb4
|
||||
b$91: phi(bb3: b$76, bb4: b$79)
|
||||
[15] unknown $80 = LoadLocal unknown x$2
|
||||
[16] unknown $81 = LoadLocal unknown y$4
|
||||
[17] unknown $82 = Binary unknown $80 + unknown $81
|
||||
[18] unknown $83 = LoadLocal unknown a$6
|
||||
[19] unknown $84 = Binary unknown $82 + unknown $83
|
||||
[20] unknown $85 = LoadLocal unknown b$8
|
||||
[21] unknown $86 = Binary unknown $84 + unknown $85
|
||||
[22] unknown $87 = Function @deps[] @context[unknown x$61, unknown y$63, unknown a$66, unknown b$91]:
|
||||
function bar(
|
||||
unknown z$69,
|
||||
unknown z$92,
|
||||
)
|
||||
entry bb5
|
||||
bb5 (block)
|
||||
[0] unknown $27 = 2
|
||||
[1] unknown $29 = StoreLocal Let unknown c$70 = unknown $27
|
||||
[2] unknown $31 = DeclareLocal Let unknown d$71
|
||||
[3] unknown $32 = 3
|
||||
[4] unknown $33 = StoreLocal Reassign unknown d$72 = unknown $32
|
||||
[5] unknown $34 = LoadLocal unknown x$65
|
||||
[6] unknown $35 = LoadLocal unknown y$66
|
||||
[7] unknown $36 = Binary unknown $34 + unknown $35
|
||||
[8] unknown $37 = LoadLocal unknown a$67
|
||||
[9] unknown $38 = Binary unknown $36 + unknown $37
|
||||
[10] unknown $39 = LoadLocal unknown b$68
|
||||
[11] unknown $40 = Binary unknown $38 + unknown $39
|
||||
[12] unknown $41 = LoadLocal unknown z$69
|
||||
[13] unknown $42 = Binary unknown $40 + unknown $41
|
||||
[14] unknown $43 = 2
|
||||
[15] unknown $44 = Binary unknown $42 + unknown $43
|
||||
[16] unknown $45 = 3
|
||||
[17] unknown $46 = Binary unknown $44 + unknown $45
|
||||
[18] unknown $47 = <undefined>
|
||||
[0] unknown $93 = 2
|
||||
[1] unknown $94 = StoreLocal Let unknown c$95 = unknown $93
|
||||
[2] unknown $96 = DeclareLocal Let unknown d$97
|
||||
[3] unknown $98 = 3
|
||||
[4] unknown $99 = StoreLocal Reassign unknown d$100 = unknown $98
|
||||
[5] unknown $101 = LoadLocal unknown x$2
|
||||
[6] unknown $102 = LoadLocal unknown y$4
|
||||
[7] unknown $103 = Binary unknown $101 + unknown $102
|
||||
[8] unknown $104 = LoadLocal unknown a$6
|
||||
[9] unknown $105 = Binary unknown $103 + unknown $104
|
||||
[10] unknown $106 = LoadLocal unknown b$8
|
||||
[11] unknown $107 = Binary unknown $105 + unknown $106
|
||||
[12] unknown $108 = LoadLocal unknown z$26
|
||||
[13] unknown $109 = Binary unknown $107 + unknown $108
|
||||
[14] unknown $110 = LoadLocal unknown c$28
|
||||
[15] unknown $111 = Binary unknown $109 + unknown $110
|
||||
[16] unknown $112 = LoadLocal unknown d$30
|
||||
[17] unknown $113 = Binary unknown $111 + unknown $112
|
||||
[18] unknown $114 = <undefined>
|
||||
[19] Return unknown $47
|
||||
[18] unknown $50 = StoreLocal Const unknown bar$73 = unknown $48
|
||||
[19] unknown $51 = LoadLocal unknown bar$73
|
||||
[20] unknown $52 = LoadGlobal foo
|
||||
[21] unknown $53 = <undefined>
|
||||
[22] Return unknown $53
|
||||
[3] unknown $56 = StoreLocal Const unknown foo$74 = unknown $54
|
||||
[4] unknown $57 = <undefined>
|
||||
[23] unknown $115 = StoreLocal Const unknown bar$116 = unknown $87
|
||||
[24] unknown $117 = LoadLocal unknown bar$49
|
||||
[25] unknown $118 = LoadGlobal foo
|
||||
[26] unknown $119 = <undefined>
|
||||
[27] Return unknown $53
|
||||
[3] unknown $120 = StoreLocal Const unknown foo$121 = unknown $62
|
||||
[4] unknown $122 = <undefined>
|
||||
[5] Return unknown $57
|
||||
|
||||
+10
-10
@@ -28,14 +28,14 @@ function id(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $1 = LoadGlobal Math
|
||||
[1] unknown $2 = LoadGlobal id
|
||||
[2] unknown $3 = true
|
||||
[3] unknown $5 = StoreLocal Let unknown y$15 = unknown $3
|
||||
[4] unknown $6 = false
|
||||
[5] unknown $7 = StoreLocal Reassign unknown y$16 = unknown $6
|
||||
[6] unknown $8 = false
|
||||
[7] unknown $10 = DeclareLocal Let unknown z$17
|
||||
[8] unknown $11 = LoadLocal unknown z$17
|
||||
[9] unknown $12 = LoadLocal unknown x$14
|
||||
[0] unknown $15 = LoadGlobal Math
|
||||
[1] unknown $16 = LoadGlobal id
|
||||
[2] unknown $17 = true
|
||||
[3] unknown $18 = StoreLocal Let unknown y$19 = unknown $17
|
||||
[4] unknown $20 = false
|
||||
[5] unknown $21 = StoreLocal Reassign unknown y$22 = unknown $20
|
||||
[6] unknown $23 = LoadLocal unknown y$4
|
||||
[7] unknown $24 = DeclareLocal Let unknown z$25
|
||||
[8] unknown $26 = LoadLocal unknown z$9
|
||||
[9] unknown $27 = LoadLocal unknown x$0
|
||||
[10] Return unknown $12
|
||||
|
||||
+5
-5
@@ -23,18 +23,18 @@ function foo(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $6 = LoadLocal unknown a$9
|
||||
[0] unknown $13 = LoadLocal unknown a$0
|
||||
[1] If unknown $6 consequent=bb2 alternate=bb4 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[2] unknown $4 = LoadLocal unknown b$10
|
||||
[2] unknown $14 = LoadLocal unknown b$1
|
||||
[3] Return unknown $4
|
||||
bb4 (block)
|
||||
predecessors: bb0
|
||||
[4] unknown $5 = LoadLocal unknown c$11
|
||||
[4] unknown $15 = LoadLocal unknown c$2
|
||||
[5] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb4
|
||||
[6] unknown $7 = LoadLocal unknown d$12
|
||||
[7] unknown $8 = <undefined>
|
||||
[6] unknown $16 = LoadLocal unknown d$3
|
||||
[7] unknown $17 = <undefined>
|
||||
[8] Return unknown $8
|
||||
|
||||
+17
-17
@@ -21,26 +21,26 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $1 = LoadGlobal Math
|
||||
[1] unknown $2 = 0
|
||||
[2] unknown $4 = StoreLocal Let unknown b$24 = unknown $2
|
||||
[3] unknown $17 = Function @deps[] @context[unknown a$23, unknown b$24]:
|
||||
[0] unknown $24 = LoadGlobal Math
|
||||
[1] unknown $25 = 0
|
||||
[2] unknown $26 = StoreLocal Let unknown b$27 = unknown $25
|
||||
[3] unknown $28 = Function @deps[] @context[unknown a$23, unknown b$27]:
|
||||
function foo_(
|
||||
unknown c$25,
|
||||
unknown c$29,
|
||||
)
|
||||
entry bb1
|
||||
bb1 (block)
|
||||
[0] unknown $6 = 1
|
||||
[1] unknown $8 = StoreLocal Let unknown d$26 = unknown $6
|
||||
[2] unknown $9 = LoadLocal unknown a$23
|
||||
[3] unknown $10 = 0
|
||||
[4] unknown $11 = Binary unknown $9 + unknown $10
|
||||
[5] unknown $12 = LoadLocal unknown c$25
|
||||
[6] unknown $13 = Binary unknown $11 + unknown $12
|
||||
[7] unknown $14 = 1
|
||||
[8] unknown $15 = Binary unknown $13 + unknown $14
|
||||
[0] unknown $30 = 1
|
||||
[1] unknown $31 = StoreLocal Let unknown d$32 = unknown $30
|
||||
[2] unknown $33 = LoadLocal unknown a$0
|
||||
[3] unknown $34 = LoadLocal unknown b$3
|
||||
[4] unknown $35 = Binary unknown $33 + unknown $34
|
||||
[5] unknown $36 = LoadLocal unknown c$5
|
||||
[6] unknown $37 = Binary unknown $35 + unknown $36
|
||||
[7] unknown $38 = LoadLocal unknown d$7
|
||||
[8] unknown $39 = Binary unknown $37 + unknown $38
|
||||
[9] Return unknown $15
|
||||
[4] unknown $19 = StoreLocal Const unknown foo$27 = unknown $17
|
||||
[5] unknown $20 = LoadLocal unknown foo$27
|
||||
[6] unknown $21 = Call unknown $20()
|
||||
[4] unknown $40 = StoreLocal Const unknown foo$41 = unknown $28
|
||||
[5] unknown $42 = LoadLocal unknown foo$18
|
||||
[6] unknown $43 = Call unknown $42()
|
||||
[7] Return unknown $21
|
||||
|
||||
+9
-9
@@ -15,13 +15,13 @@ function test(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $0 = true
|
||||
[1] unknown $1 = false
|
||||
[2] unknown $2 = null
|
||||
[3] unknown $3 = 1
|
||||
[4] unknown $4 = 3.14
|
||||
[5] unknown $5 = "hello world!"
|
||||
[6] unknown $6 = Array [unknown $5]
|
||||
[7] unknown $7 = Array [unknown $0, unknown $1, unknown $2, unknown $3, unknown $4, ...unknown $6]
|
||||
[8] unknown $8 = 2
|
||||
[0] unknown $10 = true
|
||||
[1] unknown $11 = false
|
||||
[2] unknown $12 = null
|
||||
[3] unknown $13 = 1
|
||||
[4] unknown $14 = 3.14
|
||||
[5] unknown $15 = "hello world!"
|
||||
[6] unknown $16 = Array [unknown $15]
|
||||
[7] unknown $17 = Array [unknown $10, unknown $11, unknown $12, unknown $13, unknown $14, ...unknown $16]
|
||||
[8] unknown $18 = 2
|
||||
[9] Return unknown $8
|
||||
|
||||
+20
-23
@@ -29,45 +29,42 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $3 = DeclareLocal Let unknown x$28
|
||||
[1] unknown $4 = 0
|
||||
[2] unknown $6 = StoreLocal Let unknown y$29 = unknown $4
|
||||
[3] unknown $7 = 10
|
||||
[4] unknown $9 = StoreLocal Let unknown z$30 = unknown $7
|
||||
[5] unknown $19 = LoadLocal unknown a$26
|
||||
[0] unknown $28 = DeclareLocal Let unknown x$29
|
||||
[1] unknown $30 = 0
|
||||
[2] unknown $31 = StoreLocal Let unknown y$32 = unknown $30
|
||||
[3] unknown $33 = 10
|
||||
[4] unknown $34 = StoreLocal Let unknown z$35 = unknown $33
|
||||
[5] unknown $36 = LoadLocal unknown a$0
|
||||
[6] If unknown $19 consequent=bb2 alternate=bb6 fallthrough=bb1
|
||||
bb2 (block)
|
||||
predecessors: bb0
|
||||
[7] unknown $10 = 1
|
||||
[8] unknown $11 = StoreLocal Reassign unknown x$31 = unknown $10
|
||||
[9] unknown $16 = LoadLocal unknown b$27
|
||||
[7] unknown $37 = 1
|
||||
[8] unknown $38 = StoreLocal Reassign unknown x$39 = unknown $37
|
||||
[9] unknown $40 = LoadLocal unknown b$1
|
||||
[10] If unknown $16 consequent=bb4 alternate=bb5 fallthrough=bb3
|
||||
bb4 (block)
|
||||
predecessors: bb2
|
||||
[11] unknown $12 = 20
|
||||
[12] unknown $13 = StoreLocal Reassign unknown z$32 = unknown $12
|
||||
[11] unknown $41 = 20
|
||||
[12] unknown $42 = StoreLocal Reassign unknown z$43 = unknown $41
|
||||
[13] Goto bb3
|
||||
bb5 (block)
|
||||
predecessors: bb2
|
||||
[14] unknown $14 = 30
|
||||
[15] unknown $15 = StoreLocal Reassign unknown z$33 = unknown $14
|
||||
[14] unknown $44 = 30
|
||||
[15] unknown $45 = StoreLocal Reassign unknown z$46 = unknown $44
|
||||
[16] Goto bb3
|
||||
bb3 (block)
|
||||
predecessors: bb4, bb5
|
||||
z$40: phi(bb4: z$32, bb5: z$33)
|
||||
[17] Goto bb1
|
||||
bb6 (block)
|
||||
predecessors: bb0
|
||||
[18] unknown $17 = 2
|
||||
[19] unknown $18 = StoreLocal Reassign unknown x$34 = unknown $17
|
||||
[18] unknown $47 = 2
|
||||
[19] unknown $48 = StoreLocal Reassign unknown x$49 = unknown $47
|
||||
[20] Goto bb1
|
||||
bb1 (block)
|
||||
predecessors: bb3, bb6
|
||||
x$35: phi(bb3: x$31, bb6: x$34)
|
||||
z$39: phi(bb3: z$40, bb6: z$30)
|
||||
[21] unknown $20 = LoadLocal unknown x$35
|
||||
[22] unknown $21 = 0
|
||||
[23] unknown $22 = Binary unknown $20 + unknown $21
|
||||
[24] unknown $23 = LoadLocal unknown z$39
|
||||
[25] unknown $24 = Binary unknown $22 + unknown $23
|
||||
[21] unknown $50 = LoadLocal unknown x$2
|
||||
[22] unknown $51 = LoadLocal unknown y$5
|
||||
[23] unknown $52 = Binary unknown $50 + unknown $51
|
||||
[24] unknown $53 = LoadLocal unknown z$8
|
||||
[25] unknown $54 = Binary unknown $52 + unknown $53
|
||||
[26] Return unknown $24
|
||||
|
||||
+7
-7
@@ -18,17 +18,17 @@ function Component(
|
||||
)
|
||||
entry bb0
|
||||
bb0 (block)
|
||||
[0] unknown $1 = LoadGlobal useMemo
|
||||
[1] unknown $14 = DeclareLocal Let unknown t$12
|
||||
[0] unknown $11 = LoadGlobal useMemo
|
||||
[1] unknown $20 = DeclareLocal Let unknown t$18
|
||||
[2] Label block=bb1 fallthrough=bb6
|
||||
bb1 (block)
|
||||
predecessors: bb0
|
||||
[3] unknown $2 = LoadGlobal y
|
||||
[4] unknown $13 = StoreLocal Reassign unknown t$12 = unknown $2
|
||||
[3] unknown $13 = LoadGlobal y
|
||||
[4] unknown $19 = StoreLocal Reassign unknown t$18 = unknown $2
|
||||
[5] Goto bb6
|
||||
bb6 (block)
|
||||
predecessors: bb1
|
||||
[6] unknown $5 = LoadLocal unknown t$12
|
||||
[7] unknown $7 = StoreLocal Const unknown x$11 = unknown $5
|
||||
[8] unknown $8 = LoadLocal unknown x$11
|
||||
[6] unknown $14 = LoadLocal unknown t$18
|
||||
[7] unknown $15 = StoreLocal Const unknown x$16 = unknown $14
|
||||
[8] unknown $17 = LoadLocal unknown x$6
|
||||
[9] Return unknown $8
|
||||
|
||||
@@ -16,17 +16,20 @@ pub struct Instruction {
|
||||
impl Instruction {
|
||||
pub fn each_identifier_store<F>(&mut self, mut f: F) -> ()
|
||||
where
|
||||
F: FnMut(&mut LValue) -> (),
|
||||
F: FnMut(&mut IdentifierOperand) -> (),
|
||||
{
|
||||
match &mut self.value {
|
||||
InstructionValue::DeclareContext(instr) => {
|
||||
f(&mut instr.lvalue);
|
||||
f(&mut instr.lvalue.identifier);
|
||||
}
|
||||
InstructionValue::DeclareLocal(instr) => {
|
||||
f(&mut instr.lvalue);
|
||||
f(&mut instr.lvalue.identifier);
|
||||
}
|
||||
InstructionValue::StoreLocal(instr) => {
|
||||
f(&mut instr.lvalue);
|
||||
f(&mut instr.lvalue.identifier);
|
||||
}
|
||||
InstructionValue::Destructure(instr) => {
|
||||
instr.pattern.each_operand(f);
|
||||
}
|
||||
InstructionValue::Array(_)
|
||||
| InstructionValue::Binary(_)
|
||||
@@ -43,18 +46,19 @@ impl Instruction {
|
||||
|
||||
pub fn try_each_identifier_store<F, E>(&mut self, mut f: F) -> Result<(), E>
|
||||
where
|
||||
F: FnMut(&mut LValue) -> Result<(), E>,
|
||||
F: FnMut(&mut IdentifierOperand) -> Result<(), E>,
|
||||
{
|
||||
match &mut self.value {
|
||||
InstructionValue::DeclareContext(instr) => {
|
||||
f(&mut instr.lvalue)?;
|
||||
f(&mut instr.lvalue.identifier)?;
|
||||
}
|
||||
InstructionValue::DeclareLocal(instr) => {
|
||||
f(&mut instr.lvalue)?;
|
||||
f(&mut instr.lvalue.identifier)?;
|
||||
}
|
||||
InstructionValue::StoreLocal(instr) => {
|
||||
f(&mut instr.lvalue)?;
|
||||
f(&mut instr.lvalue.identifier)?;
|
||||
}
|
||||
InstructionValue::Destructure(instr) => instr.pattern.try_each_operand(f)?,
|
||||
InstructionValue::Array(_)
|
||||
| InstructionValue::Binary(_)
|
||||
| InstructionValue::Call(_)
|
||||
@@ -73,21 +77,23 @@ impl Instruction {
|
||||
where
|
||||
F: FnMut(&mut IdentifierOperand) -> (),
|
||||
{
|
||||
match &mut self.value {
|
||||
InstructionValue::LoadLocal(instr) => f(&mut instr.place),
|
||||
InstructionValue::Array(_)
|
||||
| InstructionValue::Binary(_)
|
||||
| InstructionValue::Call(_)
|
||||
| InstructionValue::DeclareContext(_)
|
||||
| InstructionValue::DeclareLocal(_)
|
||||
| InstructionValue::LoadContext(_)
|
||||
| InstructionValue::LoadGlobal(_)
|
||||
| InstructionValue::Primitive(_)
|
||||
| InstructionValue::StoreLocal(_)
|
||||
| InstructionValue::Function(_)
|
||||
| InstructionValue::JSXElement(_)
|
||||
| InstructionValue::Tombstone => {}
|
||||
}
|
||||
// match &mut self.value {
|
||||
// InstructionValue::LoadLocal(instr) => f(&mut instr.place),
|
||||
// InstructionValue::Array(_)
|
||||
// | InstructionValue::Binary(_)
|
||||
// | InstructionValue::Call(_)
|
||||
// | InstructionValue::DeclareContext(_)
|
||||
// | InstructionValue::DeclareLocal(_)
|
||||
// | InstructionValue::Destructure(_)
|
||||
// | InstructionValue::LoadContext(_)
|
||||
// | InstructionValue::LoadGlobal(_)
|
||||
// | InstructionValue::Primitive(_)
|
||||
// | InstructionValue::StoreLocal(_)
|
||||
// | InstructionValue::Function(_)
|
||||
// | InstructionValue::JSXElement(_)
|
||||
// | InstructionValue::Tombstone => {}
|
||||
// }
|
||||
self.each_operand(f);
|
||||
}
|
||||
|
||||
pub fn each_operand<F>(&mut self, mut f: F) -> ()
|
||||
@@ -139,6 +145,9 @@ impl Instruction {
|
||||
}
|
||||
}
|
||||
}
|
||||
InstructionValue::Destructure(value) => {
|
||||
f(&mut value.value);
|
||||
}
|
||||
InstructionValue::DeclareContext(_)
|
||||
| InstructionValue::LoadContext(_)
|
||||
| InstructionValue::LoadGlobal(_)
|
||||
@@ -162,7 +171,7 @@ pub enum InstructionValue {
|
||||
// Debugger(Debugger),
|
||||
DeclareContext(DeclareContext),
|
||||
DeclareLocal(DeclareLocal),
|
||||
// Destructure(Destructure),
|
||||
Destructure(Destructure),
|
||||
Function(FunctionExpression),
|
||||
JSXElement(JSXElement),
|
||||
// JsxFragment(JsxFragment),
|
||||
@@ -272,6 +281,94 @@ pub enum JSXAttribute {
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Destructure {
|
||||
pub kind: InstructionKind,
|
||||
pub pattern: DestructurePattern,
|
||||
pub value: IdentifierOperand,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DestructurePattern {
|
||||
Array(Vec<ArrayDestructureItem>),
|
||||
Object(Vec<ObjectDestructureItem>),
|
||||
}
|
||||
|
||||
impl DestructurePattern {
|
||||
pub fn try_each_operand<E, F>(&mut self, mut f: F) -> Result<(), E>
|
||||
where
|
||||
F: FnMut(&mut IdentifierOperand) -> Result<(), E>,
|
||||
{
|
||||
match self {
|
||||
Self::Array(elements) => {
|
||||
for item in elements {
|
||||
match item {
|
||||
ArrayDestructureItem::Hole => { /* no-op */ }
|
||||
ArrayDestructureItem::Value(item) => f(item)?,
|
||||
ArrayDestructureItem::Spread(item) => f(item)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Object(properties) => {
|
||||
for property in properties {
|
||||
match property {
|
||||
ObjectDestructureItem::Property(property) => {
|
||||
f(&mut property.value)?;
|
||||
}
|
||||
ObjectDestructureItem::Spread(property) => f(property)?,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn each_operand<F>(&mut self, mut f: F) -> ()
|
||||
where
|
||||
F: FnMut(&mut IdentifierOperand) -> (),
|
||||
{
|
||||
match self {
|
||||
Self::Array(elements) => {
|
||||
for item in elements {
|
||||
match item {
|
||||
ArrayDestructureItem::Hole => { /* no-op */ }
|
||||
ArrayDestructureItem::Value(item) => f(item),
|
||||
ArrayDestructureItem::Spread(item) => f(item),
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Object(properties) => {
|
||||
for property in properties {
|
||||
match property {
|
||||
ObjectDestructureItem::Property(property) => {
|
||||
f(&mut property.value);
|
||||
}
|
||||
ObjectDestructureItem::Spread(property) => f(property),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ArrayDestructureItem {
|
||||
Hole,
|
||||
Value(IdentifierOperand),
|
||||
Spread(IdentifierOperand),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ObjectDestructureItem {
|
||||
Property(ObjectDestructureProperty),
|
||||
Spread(IdentifierOperand),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ObjectDestructureProperty {
|
||||
pub name: String,
|
||||
pub value: IdentifierOperand,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IdentifierOperand {
|
||||
pub identifier: Identifier,
|
||||
|
||||
@@ -4,8 +4,9 @@ use forget_estree::JsValue;
|
||||
use forget_utils::ensure_sufficient_stack;
|
||||
|
||||
use crate::{
|
||||
BasicBlock, Function, Identifier, IdentifierOperand, Instruction, InstructionValue, LValue,
|
||||
Phi, PlaceOrSpread, Terminal, TerminalValue, HIR,
|
||||
ArrayDestructureItem, BasicBlock, DestructurePattern, Function, Identifier, IdentifierOperand,
|
||||
Instruction, InstructionValue, LValue, ObjectDestructureItem, Phi, PlaceOrSpread, Terminal,
|
||||
TerminalValue, HIR,
|
||||
};
|
||||
|
||||
/// Trait for HIR types to describe how they print themselves.
|
||||
@@ -205,6 +206,12 @@ impl Print for InstructionValue {
|
||||
.collect();
|
||||
write!(out, "{}", lines.join("\n"))?;
|
||||
}
|
||||
InstructionValue::Destructure(value) => {
|
||||
write!(out, "Destructure ")?;
|
||||
value.pattern.print(hir, out)?;
|
||||
write!(out, " = ")?;
|
||||
value.value.print(hir, out)?;
|
||||
}
|
||||
InstructionValue::Tombstone => {
|
||||
write!(out, "Tombstone!")?;
|
||||
}
|
||||
@@ -262,6 +269,54 @@ impl Print for Identifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl Print for DestructurePattern {
|
||||
fn print(&self, hir: &HIR, out: &mut impl Write) -> Result {
|
||||
match self {
|
||||
DestructurePattern::Array(items) => {
|
||||
write!(out, "[ ")?;
|
||||
for (index, item) in items.iter().enumerate() {
|
||||
if index != 0 {
|
||||
write!(out, ", ")?;
|
||||
}
|
||||
match item {
|
||||
ArrayDestructureItem::Hole => {
|
||||
write!(out, "<hole>")?;
|
||||
}
|
||||
ArrayDestructureItem::Value(item) => {
|
||||
item.print(hir, out)?;
|
||||
}
|
||||
ArrayDestructureItem::Spread(item) => {
|
||||
write!(out, "...")?;
|
||||
item.print(hir, out)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
write!(out, " ]")?;
|
||||
}
|
||||
DestructurePattern::Object(properties) => {
|
||||
write!(out, "{{ ")?;
|
||||
for (index, property) in properties.iter().enumerate() {
|
||||
if index != 0 {
|
||||
write!(out, ", ")?;
|
||||
}
|
||||
match property {
|
||||
ObjectDestructureItem::Property(property) => {
|
||||
write!(out, "{}: ", &property.name)?;
|
||||
property.value.print(hir, out)?;
|
||||
}
|
||||
ObjectDestructureItem::Spread(property) => {
|
||||
write!(out, "...")?;
|
||||
property.print(hir, out)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
write!(out, " }}")?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Print for Terminal {
|
||||
fn print(&self, hir: &HIR, out: &mut impl Write) -> Result {
|
||||
write!(out, " {} ", self.id)?;
|
||||
|
||||
@@ -6,7 +6,8 @@ use forget_estree::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
AstNode, DeclarationKind, LabelId, LabelKind, ReferenceKind, ScopeId, ScopeKind, ScopeManager,
|
||||
AstNode, DeclarationKind, Label, LabelId, LabelKind, ReferenceKind, ScopeId, ScopeKind,
|
||||
ScopeManager,
|
||||
};
|
||||
|
||||
pub fn analyze(ast: &Program) -> ScopeManager {
|
||||
@@ -43,18 +44,18 @@ impl Analyzer {
|
||||
assert_eq!(last, id);
|
||||
}
|
||||
|
||||
fn lookup_break(&self, name: Option<&str>) -> Option<LabelId> {
|
||||
fn lookup_break(&self, name: Option<&str>) -> Option<&Label> {
|
||||
for id in self.labels.iter().rev() {
|
||||
let label = self.manager.label(*id);
|
||||
match (name, &label.name) {
|
||||
// If this is a labeled break, only return if an exact match
|
||||
// is in scope
|
||||
(Some(name), Some(label_name)) if name == label_name => {
|
||||
return Some(label.id);
|
||||
return Some(label);
|
||||
}
|
||||
// If this is an unlabeld break, return the innermost label id
|
||||
(None, _) => {
|
||||
return Some(label.id);
|
||||
return Some(label);
|
||||
}
|
||||
_ => { /* no-op */ }
|
||||
}
|
||||
@@ -62,22 +63,18 @@ impl Analyzer {
|
||||
None
|
||||
}
|
||||
|
||||
fn lookup_continue(&self, name: Option<&str>) -> Option<LabelId> {
|
||||
fn lookup_continue(&self, name: Option<&str>) -> Option<&Label> {
|
||||
for id in self.labels.iter().rev() {
|
||||
let label = self.manager.label(*id);
|
||||
// Skip labels that are not for loops, can only continue to a loop
|
||||
if label.kind != LabelKind::Loop {
|
||||
continue;
|
||||
}
|
||||
match (name, &label.name) {
|
||||
// If this is a labeled break, only return if an exact match
|
||||
// is in scope
|
||||
(Some(name), Some(label_name)) if &name == label_name => {
|
||||
return Some(label.id);
|
||||
return Some(label);
|
||||
}
|
||||
// If this is an unlabeld break, return the innermost label id
|
||||
(None, _) => {
|
||||
return Some(label.id);
|
||||
return Some(label);
|
||||
}
|
||||
_ => { /* no-op */ }
|
||||
}
|
||||
@@ -425,16 +422,14 @@ impl Visitor for Analyzer {
|
||||
}
|
||||
|
||||
fn visit_break_statement(&mut self, ast: &forget_estree::BreakStatement) {
|
||||
if let Some(label_id) =
|
||||
self.lookup_break(ast.label.as_ref().map(|ident| ident.name.as_str()))
|
||||
if let Some(label) = self.lookup_break(ast.label.as_ref().map(|ident| ident.name.as_str()))
|
||||
{
|
||||
self.manager
|
||||
.node_labels
|
||||
.insert(AstNode::from(ast), label_id);
|
||||
let id = label.id;
|
||||
self.manager.node_labels.insert(AstNode::from(ast), id);
|
||||
if let Some(label_node) = &ast.label {
|
||||
self.manager
|
||||
.node_labels
|
||||
.insert(AstNode::from(label_node), label_id);
|
||||
.insert(AstNode::from(label_node), id);
|
||||
}
|
||||
} else {
|
||||
self.manager.diagnostics.push(Diagnostic::invalid_syntax(
|
||||
@@ -462,21 +457,31 @@ impl Visitor for Analyzer {
|
||||
}
|
||||
|
||||
fn visit_continue_statement(&mut self, ast: &forget_estree::ContinueStatement) {
|
||||
if let Some(label_id) =
|
||||
let range = ast
|
||||
.label
|
||||
.as_ref()
|
||||
.map(|label| label.range)
|
||||
.unwrap_or(ast.range);
|
||||
if let Some(label) =
|
||||
self.lookup_continue(ast.label.as_ref().map(|ident| ident.name.as_str()))
|
||||
{
|
||||
self.manager
|
||||
.node_labels
|
||||
.insert(AstNode::from(ast), label_id);
|
||||
let id = label.id;
|
||||
if label.kind != LabelKind::Loop {
|
||||
self.manager.diagnostics.push(Diagnostic::invalid_syntax(
|
||||
"Invalid continue statement, the named label must be for a loop",
|
||||
range,
|
||||
));
|
||||
}
|
||||
self.manager.node_labels.insert(AstNode::from(ast), id);
|
||||
if let Some(label_node) = &ast.label {
|
||||
self.manager
|
||||
.node_labels
|
||||
.insert(AstNode::from(label_node), label_id);
|
||||
.insert(AstNode::from(label_node), id);
|
||||
}
|
||||
} else {
|
||||
self.manager.diagnostics.push(Diagnostic::invalid_syntax(
|
||||
"Non-syntactic continue, could not resolve continue target",
|
||||
ast.range,
|
||||
range,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +70,7 @@ pub fn eliminate_redundant_phis(env: &Environment, fun: &mut Function) {
|
||||
|
||||
for instr_ix in block.instructions.iter() {
|
||||
let instr = &mut hir.instructions[usize::from(*instr_ix)];
|
||||
instr.each_identifier_store(|store| {
|
||||
rewrite(&rewrites, &mut store.identifier.identifier)
|
||||
});
|
||||
instr.each_identifier_store(|store| rewrite(&rewrites, &mut store.identifier));
|
||||
instr.each_identifier_load(|load| rewrite(&rewrites, &mut load.identifier));
|
||||
|
||||
if let InstructionValue::Function(fun) = &mut instr.value {
|
||||
|
||||
@@ -47,6 +47,7 @@ fn visit_instructions<'e, 'f>(
|
||||
builder.each_block(|block, builder| {
|
||||
for instr_ix in &block.instructions {
|
||||
let instr = &mut instructions[usize::from(*instr_ix)];
|
||||
builder.visit_store(&mut instr.lvalue)?;
|
||||
instr.try_each_identifier_store(|store| builder.visit_store(store))?;
|
||||
instr.each_identifier_load(|load| builder.visit_load(load));
|
||||
|
||||
@@ -139,8 +140,8 @@ impl<'e, 'f> Builder<'e, 'f> {
|
||||
self.env.next_identifier_id()
|
||||
}
|
||||
|
||||
fn visit_store(&mut self, lvalue: &mut LValue) -> Result<(), Diagnostic> {
|
||||
let old_identifier = &lvalue.identifier.identifier;
|
||||
fn visit_store(&mut self, lvalue: &mut IdentifierOperand) -> Result<(), Diagnostic> {
|
||||
let old_identifier = &lvalue.identifier;
|
||||
// TODO: use Result (?)
|
||||
invariant(!self.unknown.contains(&old_identifier.id), || {
|
||||
Diagnostic::invariant(
|
||||
@@ -151,14 +152,14 @@ impl<'e, 'f> Builder<'e, 'f> {
|
||||
|
||||
if self.context.contains(&old_identifier.id) {
|
||||
let new_identifier = self.get_id_at(self.current, old_identifier);
|
||||
lvalue.identifier.identifier = new_identifier;
|
||||
lvalue.identifier = new_identifier;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let new_identifier = self.make_identifier(old_identifier);
|
||||
let state = self.states.get_mut(&self.current).unwrap();
|
||||
state.defs.insert(old_identifier.id, new_identifier.clone());
|
||||
lvalue.identifier.identifier = new_identifier;
|
||||
lvalue.identifier = new_identifier;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user