Support rest params

Adds support for lowering rest element parameters to spreads. We eagerly create 
a temporary, similar to the approach for destructuring. In theory we could do 
something more optimal if you have a `...foo` (rest element where the argument 
is an Identifier) but it doesn't seem worth optimizing yet.
This commit is contained in:
Joe Savona
2023-09-27 14:04:02 -04:00
parent be7f98d584
commit b61cfc01a5
8 changed files with 172 additions and 5 deletions
@@ -89,7 +89,7 @@ export function lower(
id = idNode.node.name;
}
}
const params: Array<Place> = [];
const params: Array<Place | SpreadPattern> = [];
func.get("params").forEach((param) => {
if (param.isIdentifier()) {
const identifier = builder.resolveIdentifier(param);
@@ -128,6 +128,24 @@ export function lower(
param,
place
);
} else if (param.isRestElement()) {
const place: Place = {
kind: "Identifier",
identifier: builder.makeTemporary(),
effect: Effect.Unknown,
loc: param.node.loc ?? GeneratedSource,
};
params.push({
kind: "Spread",
place,
});
lowerAssignment(
builder,
param.node.loc ?? GeneratedSource,
InstructionKind.Let,
param.get("argument"),
place
);
} else {
builder.errors.push({
reason: `(BuildHIR::lower) Handle ${param.node.type} params`,
@@ -79,16 +79,12 @@ let moduleLocal = false;
## Error
```
[ReactForget] Todo: (BuildHIR::lower) Handle RestElement params (1:1)
[ReactForget] Todo: (BuildHIR::lowerStatement) Handle var kinds in VariableDeclaration (3:3)
[ReactForget] Todo: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10)
[ReactForget] Todo: (BuildHIR::lowerExpression) Handle ObjectMethod properties in ObjectExpression (12:12)
[ReactForget] Todo: (BuildHIR::lower) Handle RestElement params (18:18)
[ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)
[ReactForget] Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (23:25)
@@ -0,0 +1,43 @@
## Input
```javascript
function Component(foo, ...[bar]) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", ["bar", "baz"]],
};
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(foo, ...t9) {
const $ = useMemoCache(3);
const [bar] = t9;
const c_0 = $[0] !== foo;
const c_1 = $[1] !== bar;
let t0;
if (c_0 || c_1) {
t0 = [foo, bar];
$[0] = foo;
$[1] = bar;
$[2] = t0;
} else {
t0 = $[2];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", ["bar", "baz"]],
};
```
@@ -0,0 +1,8 @@
function Component(foo, ...[bar]) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", ["bar", "baz"]],
};
@@ -0,0 +1,43 @@
## Input
```javascript
function Component(foo, ...bar) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", "bar", "baz"],
};
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(foo, ...t9) {
const $ = useMemoCache(3);
const bar = t9;
const c_0 = $[0] !== foo;
const c_1 = $[1] !== bar;
let t0;
if (c_0 || c_1) {
t0 = [foo, bar];
$[0] = foo;
$[1] = bar;
$[2] = t0;
} else {
t0 = $[2];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", "bar", "baz"],
};
```
@@ -0,0 +1,8 @@
function Component(foo, ...bar) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", "bar", "baz"],
};
@@ -0,0 +1,43 @@
## Input
```javascript
function Component(foo, ...{ bar }) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", { bar: "bar" }],
};
```
## Code
```javascript
import { unstable_useMemoCache as useMemoCache } from "react";
function Component(foo, ...t9) {
const $ = useMemoCache(3);
const { bar } = t9;
const c_0 = $[0] !== foo;
const c_1 = $[1] !== bar;
let t0;
if (c_0 || c_1) {
t0 = [foo, bar];
$[0] = foo;
$[1] = bar;
$[2] = t0;
} else {
t0 = $[2];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", { bar: "bar" }],
};
```
@@ -0,0 +1,8 @@
function Component(foo, ...{ bar }) {
return [foo, bar];
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: ["foo", { bar: "bar" }],
};