Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[compiler] Implement support for non-declaration for initializers #31712

Open
wants to merge 2 commits into
base: gh/mvitousek/40/base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions compiler/packages/babel-plugin-react-compiler/src/HIR/BuildHIR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,27 +519,23 @@ function lowerStatement(

const initBlock = builder.enter('loop', _blockId => {
const init = stmt.get('init');
if (!init.isVariableDeclaration()) {
builder.errors.push({
reason:
'(BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement',
severity: ErrorSeverity.Todo,
loc: stmt.node.loc ?? null,
suggestions: null,
if (init.isVariableDeclaration()) {
lowerStatement(builder, init);
} else if (init.isExpression()) {
lowerExpressionToTemporary(builder, init);
} else {
lowerValueToTemporary(builder, {
kind: 'Primitive',
loc: stmt.node.loc ?? GeneratedSource,
value: undefined,
});
return {
kind: 'unsupported',
id: makeInstructionId(0),
loc: init.node?.loc ?? GeneratedSource,
};
}
lowerStatement(builder, init);
return {
kind: 'goto',
block: testBlock.id,
variant: GotoVariant.Break,
id: makeInstructionId(0),
loc: init.node.loc ?? GeneratedSource,
loc: init.node?.loc ?? GeneratedSource,
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from '../HIR';
import {
HIRFunction,
InstructionKind,
ReactiveBreakTerminal,
ReactiveContinueTerminal,
ReactiveFunction,
Expand Down Expand Up @@ -364,26 +365,25 @@ class Driver {
const init = this.visitValueBlock(terminal.init, terminal.loc);
const initBlock = this.cx.ir.blocks.get(init.block)!;
let initValue = init.value;
if (initValue.kind === 'SequenceExpression') {
const initBlockHasDeclarations = initBlock.instructions.some(
instr =>
instr.value.kind === 'DeclareContext' ||
instr.value.kind === 'DeclareLocal' ||
((instr.value.kind === 'StoreContext' ||
instr.value.kind === 'StoreLocal') &&
instr.value.lvalue.kind !== InstructionKind.Reassign),
);
if (
initValue.kind === 'SequenceExpression' &&
initBlockHasDeclarations
) {
const last = initBlock.instructions.at(-1)!;
initValue.instructions.push(last);
initValue.value = {
kind: 'Primitive',
value: undefined,
loc: terminal.loc,
};
} else {
initValue = {
kind: 'SequenceExpression',
instructions: [initBlock.instructions.at(-1)!],
id: terminal.id,
loc: terminal.loc,
value: {
kind: 'Primitive',
value: undefined,
loc: terminal.loc,
},
};
}

const testValue = this.visitValueBlock(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1354,6 +1354,8 @@ function codegenForInit(
init: ReactiveValue,
): t.Expression | t.VariableDeclaration | null {
if (init.kind === 'SequenceExpression') {
// We may end up emitti
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: looks cut off

const temp = cx.temp;
const body = codegenBlock(
cx,
init.instructions.map(instruction => ({
Expand All @@ -1363,7 +1365,7 @@ function codegenForInit(
).body;
const declarators: Array<t.VariableDeclarator> = [];
let kind: 'let' | 'const' = 'const';
body.forEach(instr => {
for (const instr of body) {
let top: undefined | t.VariableDeclarator = undefined;
if (
instr.type === 'ExpressionStatement' &&
Expand All @@ -1375,30 +1377,29 @@ function codegenForInit(
top?.init == null
) {
top.init = instr.expression.right;
} else {
CompilerError.invariant(
instr.type === 'VariableDeclaration' &&
(instr.kind === 'let' || instr.kind === 'const'),
{
reason: 'Expected a variable declaration',
loc: init.loc,
description: `Got ${instr.type}`,
suggestions: null,
},
);
} else if (
instr.type === 'VariableDeclaration' &&
(instr.kind === 'let' || instr.kind === 'const')
) {
if (instr.kind === 'let') {
kind = 'let';
}
declarators.push(...instr.declarations);
} else {
/*
* We found instructions in the initializer that don't correspond to a variable declarator:
* emit as an expression instead
*/
cx.temp = temp;
return codegenInstructionValueToExpression(cx, init);
Copy link
Contributor

@josephsavona josephsavona Dec 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this skip over remaining instructions? since it's exiting the loop and function

}
});
CompilerError.invariant(declarators.length > 0, {
reason: 'Expected a variable declaration',
loc: init.loc,
description: null,
suggestions: null,
});
return t.variableDeclaration(kind, declarators);
}
if (declarators.length > 0) {
return t.variableDeclaration(kind, declarators);
} else {
cx.temp = temp;
return codegenInstructionValueToExpression(cx, init);
}
} else {
return codegenInstructionValueToExpression(cx, init);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ let moduleLocal = false;

Todo: (BuildHIR::lowerStatement) Handle ClassDeclaration statements (5:10)

Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (20:22)

Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (23:25)

Todo: (BuildHIR::lowerStatement) Handle non-variable initialization in ForStatement (26:28)

Todo: (BuildHIR::lowerStatement) Handle empty test in ForStatement (26:28)

Todo: (BuildHIR::lowerExpression) Handle tagged template with interpolations (30:32)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@

## Input

```javascript
function Foo() {
let i = 0;
for (42; i < 1; i += 1) {}
for (bar(); i < 1; i += 1) {}
for (; i < 1; i += 1) {}
for (i = 0; i < 1; i += 1) {}
}

function bar() {}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};

```

## Code

```javascript
function Foo() {
let i = 0;
for (42; i < 1; i = i + 1, i) {}
for (bar(); i < 1; i = i + 1, i) {}
for (undefined; i < 1; i = i + 1, i) {}
for (i = 0; i < 1; i = i + 1, i) {}
}

function bar() {}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};

```

### Eval output
(kind: ok)
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function Foo() {
let i = 0;
for (42; i < 1; i += 1) {}
for (bar(); i < 1; i += 1) {}
for (; i < 1; i += 1) {}
for (i = 0; i < 1; i += 1) {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's test a more complex initializer value, like a logical expression, ternary, sequence expression, or optional.

}

function bar() {}

export const FIXTURE_ENTRYPOINT = {
fn: Foo,
params: [],
};
Loading