Support spread elements in ArrayExpression

Similar to the previous, but for array expression: `const x = [...y]`
This commit is contained in:
Joe Savona
2023-03-06 15:32:43 -08:00
parent 93cca54aba
commit e381aa042f
7 changed files with 88 additions and 12 deletions
+17 -5
View File
@@ -858,9 +858,24 @@ function lowerExpression(
}
case "ArrayExpression": {
const expr = exprPath as NodePath<t.ArrayExpression>;
let elements: Place[] = [];
let elements: Array<Place | SpreadPattern> = [];
for (const element of expr.get("elements")) {
if (element.node == null || !element.isExpression()) {
if (element.node == null) {
builder.errors.push({
reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`,
severity: ErrorSeverity.Todo,
nodePath: element,
});
continue;
} else if (element.isExpression()) {
elements.push(lowerExpressionToTemporary(builder, element));
} else if (element.isSpreadElement()) {
const place = lowerExpressionToTemporary(
builder,
element.get("argument")
);
elements.push({ kind: "Spread", place });
} else {
builder.errors.push({
reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`,
severity: ErrorSeverity.Todo,
@@ -868,9 +883,6 @@ function lowerExpression(
});
continue;
}
elements.push(
lowerExpressionToTemporary(builder, element as NodePath<t.Expression>)
);
}
return {
kind: "ArrayExpression",
+5 -1
View File
@@ -521,7 +521,11 @@ export type InstructionValue =
properties: Array<ObjectProperty | SpreadPattern>;
loc: SourceLocation;
}
| { kind: "ArrayExpression"; elements: Array<Place>; loc: SourceLocation }
| {
kind: "ArrayExpression";
elements: Array<Place | SpreadPattern>;
loc: SourceLocation;
}
| { kind: "JsxFragment"; children: Array<Place>; loc: SourceLocation }
// store `object.property = value`
+7 -1
View File
@@ -222,7 +222,13 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
switch (instrValue.kind) {
case "ArrayExpression": {
value = `Array [${instrValue.elements
.map((element) => printPlace(element))
.map((element) => {
if (element.kind === "Identifier") {
return printPlace(element);
} else {
return `...${printPlace(element.place)}`;
}
})
.join(", ")}]`;
break;
}
+15 -2
View File
@@ -136,7 +136,13 @@ export function* eachInstructionValueOperand(
break;
}
case "ArrayExpression": {
yield* instrValue.elements;
for (const element of instrValue.elements) {
if (element.kind === "Identifier") {
yield element;
} else {
yield element.place;
}
}
break;
}
case "FunctionExpression": {
@@ -331,7 +337,14 @@ export function mapInstructionOperands(
break;
}
case "ArrayExpression": {
instrValue.elements = instrValue.elements.map((e) => fn(e));
instrValue.elements = instrValue.elements.map((element) => {
if (element.kind === "Identifier") {
return fn(element);
} else {
element.place = fn(element.place);
return element;
}
});
break;
}
case "JsxFragment": {
@@ -525,9 +525,13 @@ function codegenInstructionValue(
let value: t.Expression;
switch (instrValue.kind) {
case "ArrayExpression": {
const elements = instrValue.elements.map((element) =>
codegenPlace(cx, element)
);
const elements = instrValue.elements.map((element) => {
if (element.kind === "Identifier") {
return codegenPlace(cx, element);
} else {
return t.spreadElement(codegenPlace(cx, element.place));
}
});
value = t.arrayExpression(elements);
break;
}
@@ -0,0 +1,33 @@
## Input
```javascript
function Component(props) {
const x = [0, ...props.foo, null, ...props.bar, "z"];
return x;
}
```
## Code
```javascript
function Component(props) {
const $ = React.unstable_useMemoCache(3);
const c_0 = $[0] !== props.foo;
const c_1 = $[1] !== props.bar;
let t0;
if (c_0 || c_1) {
t0 = [0, ...props.foo, null, ...props.bar, "z"];
$[0] = props.foo;
$[1] = props.bar;
$[2] = t0;
} else {
t0 = $[2];
}
const x = t0;
return x;
}
```
@@ -0,0 +1,4 @@
function Component(props) {
const x = [0, ...props.foo, null, ...props.bar, "z"];
return x;
}