mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir] Add support for holey arrays
This PR adds a Hole kind that can be present in both ArrayExpression and ArrayPatterns. This Hole type is not interesting for our inference passes and is skipped over for all of the pipeline.
This commit is contained in:
@@ -17,6 +17,7 @@ import { Err, Ok, Result } from "../Utils/Result";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
import { Environment } from "./Environment";
|
||||
import {
|
||||
ArrayExpression,
|
||||
ArrayPattern,
|
||||
BlockId,
|
||||
BranchTerminal,
|
||||
@@ -1064,14 +1065,11 @@ function lowerExpression(
|
||||
}
|
||||
case "ArrayExpression": {
|
||||
const expr = exprPath as NodePath<t.ArrayExpression>;
|
||||
let elements: Array<Place | SpreadPattern> = [];
|
||||
let elements: ArrayExpression["elements"] = [];
|
||||
for (const element of expr.get("elements")) {
|
||||
if (element.node == null) {
|
||||
builder.errors.push({
|
||||
reason: `(BuildHIR::lowerExpression) Handle ${element.type} elements in ArrayExpression`,
|
||||
severity: ErrorSeverity.Todo,
|
||||
loc: null,
|
||||
suggestions: null,
|
||||
elements.push({
|
||||
kind: "Hole",
|
||||
});
|
||||
continue;
|
||||
} else if (element.isExpression()) {
|
||||
@@ -2696,6 +2694,9 @@ function lowerAssignment(
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const element = elements[i];
|
||||
if (element.node == null) {
|
||||
items.push({
|
||||
kind: "Hole",
|
||||
});
|
||||
continue;
|
||||
}
|
||||
if (element.isRestElement()) {
|
||||
|
||||
@@ -472,8 +472,18 @@ export type LValuePattern = {
|
||||
kind: InstructionKind;
|
||||
};
|
||||
|
||||
export type ArrayExpression = {
|
||||
kind: "ArrayExpression";
|
||||
elements: Array<Place | SpreadPattern | Hole>;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type Pattern = ArrayPattern | ObjectPattern;
|
||||
|
||||
export type Hole = {
|
||||
kind: "Hole";
|
||||
};
|
||||
|
||||
export type SpreadPattern = {
|
||||
kind: "Spread";
|
||||
place: Place;
|
||||
@@ -481,7 +491,7 @@ export type SpreadPattern = {
|
||||
|
||||
export type ArrayPattern = {
|
||||
kind: "ArrayPattern";
|
||||
items: Array<Place | SpreadPattern>;
|
||||
items: Array<Place | SpreadPattern | Hole>;
|
||||
};
|
||||
|
||||
export type ObjectPattern = {
|
||||
@@ -648,11 +658,7 @@ export type InstructionValue =
|
||||
properties: Array<ObjectProperty | SpreadPattern>;
|
||||
loc: SourceLocation;
|
||||
}
|
||||
| {
|
||||
kind: "ArrayExpression";
|
||||
elements: Array<Place | SpreadPattern>;
|
||||
loc: SourceLocation;
|
||||
}
|
||||
| ArrayExpression
|
||||
| { kind: "JsxFragment"; children: Array<Place>; loc: SourceLocation }
|
||||
| {
|
||||
kind: "RegExpLiteral";
|
||||
|
||||
@@ -239,6 +239,10 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
|
||||
return value;
|
||||
}
|
||||
|
||||
function printHole(): string {
|
||||
return "<hole>";
|
||||
}
|
||||
|
||||
export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
let value = "";
|
||||
switch (instrValue.kind) {
|
||||
@@ -247,6 +251,8 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
.map((element) => {
|
||||
if (element.kind === "Identifier") {
|
||||
return printPlace(element);
|
||||
} else if (element.kind === "Hole") {
|
||||
return printHole();
|
||||
} else {
|
||||
return `...${printPlace(element.place)}`;
|
||||
}
|
||||
@@ -554,7 +560,16 @@ export function printPattern(pattern: Pattern | Place | SpreadPattern): string {
|
||||
switch (pattern.kind) {
|
||||
case "ArrayPattern": {
|
||||
return (
|
||||
"[ " + pattern.items.map((item) => printPattern(item)).join(", ") + " ]"
|
||||
"[ " +
|
||||
pattern.items
|
||||
.map((item) => {
|
||||
if (item.kind === "Hole") {
|
||||
return "<hole>";
|
||||
}
|
||||
return printPattern(item);
|
||||
})
|
||||
.join(", ") +
|
||||
" ]"
|
||||
);
|
||||
}
|
||||
case "ObjectPattern": {
|
||||
|
||||
@@ -158,7 +158,7 @@ export function* eachInstructionValueOperand(
|
||||
for (const element of instrValue.elements) {
|
||||
if (element.kind === "Identifier") {
|
||||
yield element;
|
||||
} else {
|
||||
} else if (element.kind === "Spread") {
|
||||
yield element.place;
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,8 @@ export function* eachPatternOperand(pattern: Pattern): Iterable<Place> {
|
||||
yield item;
|
||||
} else if (item.kind === "Spread") {
|
||||
yield item.place;
|
||||
} else if (item.kind === "Hole") {
|
||||
continue;
|
||||
} else {
|
||||
assertExhaustive(
|
||||
item,
|
||||
@@ -424,9 +426,11 @@ export function mapInstructionOperands(
|
||||
instrValue.elements = instrValue.elements.map((element) => {
|
||||
if (element.kind === "Identifier") {
|
||||
return fn(element);
|
||||
} else {
|
||||
} else if (element.kind === "Spread") {
|
||||
element.place = fn(element.place);
|
||||
return element;
|
||||
} else {
|
||||
return element;
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -496,9 +500,11 @@ export function mapPatternOperands(
|
||||
pattern.items = pattern.items.map((item) => {
|
||||
if (item.kind === "Identifier") {
|
||||
return fn(item);
|
||||
} else {
|
||||
} else if (item.kind === "Spread") {
|
||||
item.place = fn(item.place);
|
||||
return item;
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
+1
-1
@@ -114,7 +114,7 @@ function visitInstruction(instr: Instruction, state: State): void {
|
||||
nextItems = originalItems.slice(0, i + 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
} else if (item.kind === "Spread") {
|
||||
if (state.used(item.place.identifier)) {
|
||||
nextItems = originalItems.slice(0, i + 1);
|
||||
break;
|
||||
|
||||
+11
-2
@@ -716,8 +716,10 @@ function codegenInstructionValue(
|
||||
const elements = instrValue.elements.map((element) => {
|
||||
if (element.kind === "Identifier") {
|
||||
return codegenPlace(cx, element);
|
||||
} else {
|
||||
} else if (element.kind === "Spread") {
|
||||
return t.spreadElement(codegenPlace(cx, element.place));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
value = t.arrayExpression(elements);
|
||||
@@ -1245,7 +1247,14 @@ function codegenLValue(
|
||||
): t.ArrayPattern | t.ObjectPattern | t.RestElement | t.Identifier {
|
||||
switch (pattern.kind) {
|
||||
case "ArrayPattern": {
|
||||
return t.arrayPattern(pattern.items.map((item) => codegenLValue(item)));
|
||||
return t.arrayPattern(
|
||||
pattern.items.map((item) => {
|
||||
if (item.kind === "Hole") {
|
||||
return null;
|
||||
}
|
||||
return codegenLValue(item);
|
||||
})
|
||||
);
|
||||
}
|
||||
case "ObjectPattern": {
|
||||
return t.objectPattern(
|
||||
|
||||
+1
-1
@@ -628,7 +628,7 @@ function computePatternLValues(pattern: Pattern): Array<LValueMemoization> {
|
||||
for (const item of pattern.items) {
|
||||
if (item.kind === "Identifier") {
|
||||
lvalues.push({ place: item, level: MemoizationLevel.Conditional });
|
||||
} else {
|
||||
} else if (item.kind === "Spread") {
|
||||
lvalues.push({ place: item.place, level: MemoizationLevel.Memoized });
|
||||
}
|
||||
}
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
let x = [, foo, props];
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
function t(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const c_0 = $[0] !== props;
|
||||
let t0;
|
||||
if (c_0) {
|
||||
t0 = [, foo, props];
|
||||
$[0] = props;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const x = t0;
|
||||
return x;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function t(props) {
|
||||
let x = [, foo, props];
|
||||
return x;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
let [foo, bar, ,] = props;
|
||||
return foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
const [foo] = props;
|
||||
return foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function t(props) {
|
||||
let [foo, bar, ,] = props;
|
||||
return foo;
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
let [, foo, bar] = props;
|
||||
return foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
const [, foo] = props;
|
||||
return foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
function t(props) {
|
||||
let [, foo, bar] = props;
|
||||
return foo;
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
let [, setstate] = useState();
|
||||
setstate(1);
|
||||
return props.foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function t(props) {
|
||||
const [, setstate] = useState();
|
||||
setstate(1);
|
||||
return props.foo;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
function t(props) {
|
||||
let [, setstate] = useState();
|
||||
setstate(1);
|
||||
return props.foo;
|
||||
}
|
||||
Reference in New Issue
Block a user