-
Notifications
You must be signed in to change notification settings - Fork 46.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[compiler] HIR-based FlattenReactiveLoops
Pre the title, this implements an HIR-based version of FlattenReactiveLoops. Another step on the way to HIR-everywhere. ghstack-source-id: e1d166352df6b0725e4c4915a19445437916251f Pull Request resolved: #29838
- Loading branch information
1 parent
f7b871a
commit 43c17d1
Showing
2 changed files
with
87 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
71 changes: 71 additions & 0 deletions
71
compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/FlattenReactiveLoopsHIR.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
/** | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import { BlockId, HIRFunction, PrunedScopeTerminal } from "../HIR"; | ||
import { assertExhaustive, retainWhere } from "../Utils/utils"; | ||
|
||
/** | ||
* Prunes any reactive scopes that are within a loop (for, while, etc). We don't yet | ||
* support memoization within loops because this would require an extra layer of reconciliation | ||
* (plus a way to identify values across runs, similar to how we use `key` in JSX for lists). | ||
* Eventually we may integrate more deeply into the runtime so that we can do a single level | ||
* of reconciliation, but for now we've found it's sufficient to memoize *around* the loop. | ||
*/ | ||
export function flattenReactiveLoopsHIR(fn: HIRFunction): void { | ||
const activeLoops = Array<BlockId>(); | ||
for (const [, block] of fn.body.blocks) { | ||
retainWhere(activeLoops, (id) => id !== block.id); | ||
const { terminal } = block; | ||
switch (terminal.kind) { | ||
case "do-while": | ||
case "for": | ||
case "for-in": | ||
case "for-of": | ||
case "while": { | ||
activeLoops.push(terminal.fallthrough); | ||
break; | ||
} | ||
case "scope": { | ||
if (activeLoops.length !== 0) { | ||
block.terminal = { | ||
kind: "pruned-scope", | ||
block: terminal.block, | ||
fallthrough: terminal.fallthrough, | ||
id: terminal.id, | ||
loc: terminal.loc, | ||
scope: terminal.scope, | ||
} as PrunedScopeTerminal; | ||
} | ||
break; | ||
} | ||
case "branch": | ||
case "goto": | ||
case "if": | ||
case "label": | ||
case "logical": | ||
case "maybe-throw": | ||
case "optional": | ||
case "pruned-scope": | ||
case "return": | ||
case "sequence": | ||
case "switch": | ||
case "ternary": | ||
case "throw": | ||
case "try": | ||
case "unreachable": | ||
case "unsupported": { | ||
break; | ||
} | ||
default: { | ||
assertExhaustive( | ||
terminal, | ||
`Unexpected terminal kind \`${(terminal as any).kind}\`` | ||
); | ||
} | ||
} | ||
} | ||
} |