[hir] Make lambdas dependencies be a list of Places
This lets HIR understand and rename dependencies correctly.
Sathya Gunasekaran committed
Jan 10, 2023 at 16:06 UTC
6f9c9cf9ea037829b4da4bc419a877e3fc8b7d4a
6 files changed
+87
-9
compiler/forget/src/HIR/BuildHIR.ts
+15
-5
@@ -1152,7 +1152,11 @@ function lowerExpression(
1152
const expr = exprPath as NodePath<t.FunctionExpression>;
1153
const name: string | null = expr.get("id")?.node?.name ?? null;
1154
const componentScope: Scope = expr.scope.parent.getFunctionParent()!;
1155
- const dependencies = gatherCapturedDeps(expr, componentScope);
1155
+ const dependencies: Array<Place> = gatherCapturedDeps(
1156
+ builder,
1157
+ expr,
1158
+ componentScope
1159
+ );
1160
const body = expr.get("body").node;
1161
const params: Array<string> = expr.get("params").map((p) => {
1162
todoInvariant(p.isIdentifier(), "handle non identifier params");
@@ -1562,10 +1566,11 @@ function capturePureScopes(
1566
}
1567
1568
function gatherCapturedDeps(
1569
+ builder: HIRBuilder,
1570
fn: NodePath<t.FunctionExpression>,
1571
componentScope: Scope
1567
-): Set<t.Identifier> {
1568
- const captured: Set<t.Identifier> = new Set();
1572
+): Array<Place> {
1573
+ const captured: Set<Place> = new Set();
1574
1575
// Capture all the scopes from the parent of this function up to and including
1576
// the component scope.
@@ -1587,9 +1592,14 @@ function gatherCapturedDeps(
1592
return;
1593
}
1594
1590
- captured.add(binding.identifier);
1595
+ captured.add({
1596
+ kind: "Identifier",
1597
+ identifier: builder.resolveIdentifier(binding.identifier),
1598
+ effect: Effect.Unknown,
1599
+ loc: id.node.loc!,
1600
+ });
1601
},
1602
});
1603
1594
- return captured;
1604
+ return [...captured];
1605
}
compiler/forget/src/HIR/HIR.ts
+1
-1
@@ -313,7 +313,7 @@ export type InstructionData =
313
kind: "FunctionExpression";
314
name: string | null;
315
params: Array<string>;
316
- dependencies: Set<t.Identifier>;
316
+ dependencies: Array<Place>;
317
body: t.BlockStatement;
318
}
319
compiler/forget/src/HIR/PrintHIR.ts
+3
-1
@@ -293,7 +293,9 @@ export function printInstructionValue(instrValue: InstructionValue): string {
293
case "FunctionExpression": {
294
const params = instrValue.params.join(",");
295
const body = generate(instrValue.body).code;
296
- const deps = [...instrValue.dependencies].map((i) => i.name).join(",");
296
+ const deps = instrValue.dependencies
297
+ .map((i) => printIdentifier(i.identifier))
298
+ .join(",");
299
value = `Function ${instrValue.name ?? ""} @deps[${deps}] (${
300
params ?? ""
301
}){${body}}`;
compiler/forget/src/HIR/visitors.ts
+8
-2
@@ -87,9 +87,12 @@ export function* eachInstructionValueOperand(
87
yield* instrValue.elements;
88
break;
89
}
90
+ case "FunctionExpression": {
91
+ yield* instrValue.dependencies;
92
+ break;
93
+ }
94
case "OtherStatement":
95
case "Primitive":
92
- case "FunctionExpression":
96
case "JSXText": {
97
break;
98
}
@@ -174,9 +177,12 @@ export function mapInstructionOperands(
177
instrValue.children = instrValue.children.map((e) => fn(e));
178
break;
179
}
180
+ case "FunctionExpression": {
181
+ instrValue.dependencies = instrValue.dependencies.map((d) => fn(d));
182
+ break;
183
+ }
184
case "OtherStatement":
185
case "Primitive":
179
- case "FunctionExpression":
186
case "JSXText": {
187
break;
188
}
compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.expect.md
new
+53
@@ -0,0 +1,53 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function component(a, b) {
6
+ let z = { a, b };
7
+ let x = function () {
8
+ z;
9
+ };
10
+ return x;
11
+}
12
+
13
+```
14
+
15
+## Code
16
+
17
+```javascript
18
+function component(a, b) {
19
+ const $ = React.useMemoCache();
20
+ const c_0 = $[0] !== a;
21
+ const c_1 = $[1] !== b;
22
+ let z;
23
+ if (c_0 || c_1) {
24
+ z = {
25
+ a: a,
26
+ b: b,
27
+ };
28
+ $[0] = a;
29
+ $[1] = b;
30
+ $[2] = z;
31
+ } else {
32
+ z = $[2];
33
+ }
34
+
35
+ const c_3 = $[3] !== z;
36
+ let x;
37
+
38
+ if (c_3) {
39
+ x = function () {
40
+ z;
41
+ };
42
+
43
+ $[3] = z;
44
+ $[4] = x;
45
+ } else {
46
+ x = $[4];
47
+ }
48
+
49
+ return x;
50
+}
51
+
52
+```
53
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/prop-capturing-function-1.js
new
+7
@@ -0,0 +1,7 @@
1
+function component(a, b) {
2
+ let z = { a, b };
3
+ let x = function () {
4
+ z;
5
+ };
6
+ return x;
7
+}