[hir] Make lambdas dependencies be a list of Places

This lets HIR understand and rename dependencies correctly.
This commit is contained in:
Sathya Gunasekaran
2023-01-10 16:06:55 +00:00
parent 346ecb27fe
commit 6f9c9cf9ea
6 changed files with 87 additions and 9 deletions
+15 -5
View File
@@ -1152,7 +1152,11 @@ function lowerExpression(
const expr = exprPath as NodePath<t.FunctionExpression>;
const name: string | null = expr.get("id")?.node?.name ?? null;
const componentScope: Scope = expr.scope.parent.getFunctionParent()!;
const dependencies = gatherCapturedDeps(expr, componentScope);
const dependencies: Array<Place> = gatherCapturedDeps(
builder,
expr,
componentScope
);
const body = expr.get("body").node;
const params: Array<string> = expr.get("params").map((p) => {
todoInvariant(p.isIdentifier(), "handle non identifier params");
@@ -1562,10 +1566,11 @@ function capturePureScopes(
}
function gatherCapturedDeps(
builder: HIRBuilder,
fn: NodePath<t.FunctionExpression>,
componentScope: Scope
): Set<t.Identifier> {
const captured: Set<t.Identifier> = new Set();
): Array<Place> {
const captured: Set<Place> = new Set();
// Capture all the scopes from the parent of this function up to and including
// the component scope.
@@ -1587,9 +1592,14 @@ function gatherCapturedDeps(
return;
}
captured.add(binding.identifier);
captured.add({
kind: "Identifier",
identifier: builder.resolveIdentifier(binding.identifier),
effect: Effect.Unknown,
loc: id.node.loc!,
});
},
});
return captured;
return [...captured];
}
+1 -1
View File
@@ -313,7 +313,7 @@ export type InstructionData =
kind: "FunctionExpression";
name: string | null;
params: Array<string>;
dependencies: Set<t.Identifier>;
dependencies: Array<Place>;
body: t.BlockStatement;
}
+3 -1
View File
@@ -293,7 +293,9 @@ export function printInstructionValue(instrValue: InstructionValue): string {
case "FunctionExpression": {
const params = instrValue.params.join(",");
const body = generate(instrValue.body).code;
const deps = [...instrValue.dependencies].map((i) => i.name).join(",");
const deps = instrValue.dependencies
.map((i) => printIdentifier(i.identifier))
.join(",");
value = `Function ${instrValue.name ?? ""} @deps[${deps}] (${
params ?? ""
}){${body}}`;
+8 -2
View File
@@ -87,9 +87,12 @@ export function* eachInstructionValueOperand(
yield* instrValue.elements;
break;
}
case "FunctionExpression": {
yield* instrValue.dependencies;
break;
}
case "OtherStatement":
case "Primitive":
case "FunctionExpression":
case "JSXText": {
break;
}
@@ -174,9 +177,12 @@ export function mapInstructionOperands(
instrValue.children = instrValue.children.map((e) => fn(e));
break;
}
case "FunctionExpression": {
instrValue.dependencies = instrValue.dependencies.map((d) => fn(d));
break;
}
case "OtherStatement":
case "Primitive":
case "FunctionExpression":
case "JSXText": {
break;
}
@@ -0,0 +1,53 @@
## Input
```javascript
function component(a, b) {
let z = { a, b };
let x = function () {
z;
};
return x;
}
```
## Code
```javascript
function component(a, b) {
const $ = React.useMemoCache();
const c_0 = $[0] !== a;
const c_1 = $[1] !== b;
let z;
if (c_0 || c_1) {
z = {
a: a,
b: b,
};
$[0] = a;
$[1] = b;
$[2] = z;
} else {
z = $[2];
}
const c_3 = $[3] !== z;
let x;
if (c_3) {
x = function () {
z;
};
$[3] = z;
$[4] = x;
} else {
x = $[4];
}
return x;
}
```
@@ -0,0 +1,7 @@
function component(a, b) {
let z = { a, b };
let x = function () {
z;
};
return x;
}