@samitouri / QOS-React-2 / commits / 6e52cc3f38

Construct nested reactive scopes

There are a bunch of ways we can go about converting from the input HIR into a final form that has the preamble inserted and memoized blocks of code wrapped with change detection and caching. This is just one way, it might not be the ideal way. In any case, this pass converts HIRFunction -> ReactiveFunction. The latter is a recursive (tree-shaped) data structure that attempts to represent blocks each of composed of scopes or instructions, where scopes are themselves composed of blocks etc. The idea is a) this makes it easy to visualize the structure and check that the scopes and their dependencies are correct and b) this is a really nice form for adding the memoization code. We can convert from a ReactiveFunction back to an HIRFunction, wrapping each scope in the appropriate if checks and caching. ## Example Consider the following example, which has 2 main scopes: an outer one for `x` and an inner one in the consequent for `y`: ```javascript function foo(a, b, c) { const x = []; if (a) { const y = []; y.push(b); x.push(<div>{y}</div>); } else { x.push(c); } return x; } ``` ## Output The new builder constructs a ReactiveFunction for this example along the lines of the following (note that inputs are always empty bc we don't collect those yet): ``` { scope @0 [1:11] inputs=[] { [1] Const mutate x$11_@0[1:11] = Array [] [2] if (read a$8) { scope @1 [3:5] inputs=[] { [3] Const mutate y$12_@1[3:5] = Array [] [4] Call mutate y$12_@1.push(read b$9) } scope @2 [5:6] inputs=[] { [5] Const mutate $13_@2 = "div" } scope @3 [6:7] inputs=[] { [6] Const mutate $14_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2> } [7] Call mutate x$11_@0.push(read $14_@3) } else { [9] Call mutate x$11_@0.push(read c$10) } } [10] return x$11; } ``` This shows the hierarchy: there's an outer scope, `@0` to compute `x` (the first scope), then within the if consequent there's another scope, `@1`, to compute `y`. We have some technically extraneous scopes to compute the JSX element; that can be cleaned up with a bit more refinement. With this structure — and the inputs and outputs of each scope filled in — we can convert to code in a straightforward manner. Each scope turns into a block along the lines of the following: (note here we use strings to index the cache, in reality these would be ints) ```javascript // one change variable pet input: let c_a = a !== $['a']; ... // one variable for each output: let x; ... // if (changed) { recompute } else { use-cache } if (c_a || ... ) { x = ...; // one assignment per output $['x'] = x; // update cache per input $['a'] = a; ... } else { // one assignment per output x = $['x']; ... } ```

Joseph Savona committed Dec 13, 2022 at 11:53 UTC 6e52cc3f3800c885fac12541fa0372b43e85829a
101 files changed +4229 -493
compiler/forget/packages/playground/components/Editor/Output.tsx
+12
@@ -20,6 +20,8 @@ import type { Store } from "../../lib/stores";
20 import TabbedWindow, { TabTypes } from "../TabbedWindow";
21 import { monacoOptions } from "./monacoOptions";
22 const {
23 + buildReactiveFunction,
24 + printReactiveFunction,
25 parseFunctions,
26 Environment,
27 enterSSA,
@@ -54,6 +56,7 @@ type CompilerOutput = {
56 inferReactiveScopeVariablesOutput: string;
57 inferReactiveScopesOutput: string;
58 inferReactiveScopeDependenciesOutput: string;
59 + reactiveFunctionOutput: string;
60 leaveSSAOutput: string;
61 codegenOutput: string;
62 sourceMapUrl: string | null;
@@ -99,6 +102,9 @@ function compile(source: string): CompilerOutput | CompilerError {
102 inferReactiveScopeDependencies(ir);
103 const inferReactiveScopeDependenciesOutput = printHIR(ir.body);
104
105 + const reactiveFunction = buildReactiveFunction(ir);
106 + const reactiveFunctionOutput = printReactiveFunction(reactiveFunction);
107 +
108 codegen(ir);
109 const ast = codegen(ir);
110 const generated = generate(
@@ -128,6 +134,7 @@ function compile(source: string): CompilerOutput | CompilerError {
134 inferReactiveScopeDependenciesOutput,
135 inferReactiveScopeVariablesOutput,
136 inferReactiveScopesOutput,
137 + reactiveFunctionOutput,
138 leaveSSAOutput,
139 codegenOutput,
140 sourceMapUrl,
@@ -203,6 +210,11 @@ function Output({ store, setTabsOpen, tabsOpen }: Props) {
210 output={compilerOutput.inferReactiveScopeDependenciesOutput}
211 ></TextTabContent>
212 ),
213 + ReactiveFunctions: (
214 + <TextTabContent
215 + output={compilerOutput.reactiveFunctionOutput}
216 + ></TextTabContent>
217 + ),
218 JS: <TextTabContent output={compilerOutput.codegenOutput} />,
219 SourceMap: (
220 <>
compiler/forget/packages/playground/components/TabbedWindow.tsx
+1
@@ -16,6 +16,7 @@ export type TabTypes =
16 | "InferReactiveScopeVariables"
17 | "InferReactiveScopes"
18 | "InferReactiveScopeDependencies"
19 + | "ReactiveFunctions"
20 | "LeaveSSA"
21 | "JS"
22 | "SourceMap"
compiler/forget/src/HIR/BuildReactiveFunction.ts new
+394
@@ -0,0 +1,394 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import invariant from "invariant";
9 +import { assertExhaustive } from "../Common/utils";
10 +import {
11 + BlockId,
12 + HIRFunction,
13 + Instruction,
14 + InstructionId,
15 + InstructionValue,
16 + Place,
17 + ReactiveBasicBlock,
18 + ReactiveBlock,
19 + ReactiveFunction,
20 + ReactiveInstruction,
21 + ReactiveScope,
22 + ReactiveTerminal,
23 + ReactiveValueBlock,
24 + ScopeId,
25 +} from "./HIR";
26 +import { BlockTerminal, Visitor, visitTree } from "./HIRTreeVisitor";
27 +import { eachInstructionOperand } from "./visitors";
28 +
29 +export function buildReactiveFunction(fn: HIRFunction): ReactiveFunction {
30 + const builder = new ReactiveFunctionBuilder();
31 + const body = visitTree(fn, builder);
32 + invariant(body != null, "Expected a root block");
33 + return {
34 + loc: fn.loc,
35 + id: fn.id,
36 + params: fn.params,
37 + generator: fn.generator,
38 + async: fn.async,
39 + body,
40 + };
41 +}
42 +
43 +type BlockKind =
44 + | { kind: "block"; block: ReactiveBasicBlock }
45 + | { kind: "scope"; block: ReactiveBasicBlock; scope: ReactiveScope };
46 +
47 +class Builder {
48 + #instructions: ReactiveBasicBlock;
49 + #stack: Array<
50 + | { kind: "scope"; block: ReactiveBlock }
51 + | { kind: "block"; block: ReactiveBasicBlock }
52 + >;
53 +
54 + constructor() {
55 + const block: ReactiveBasicBlock = [];
56 + this.#instructions = block;
57 + this.#stack = [{ kind: "block", block }];
58 + }
59 +
60 + append(item: ReactiveInstruction, label: BlockId | undefined): void {
61 + if (label !== undefined) {
62 + invariant(item.kind === "terminal", "Only terminals may have a label");
63 + item.label = label;
64 + }
65 + this.#instructions.push(item);
66 + }
67 +
68 + startScope(scope: ReactiveScope): void {
69 + const block: ReactiveBlock = {
70 + kind: "block",
71 + id: scope.id,
72 + range: scope.range,
73 + dependencies: scope.dependencies,
74 + instructions: [],
75 + };
76 + this.append(block, undefined);
77 + this.#instructions = block.instructions;
78 + this.#stack.push({ kind: "scope", block });
79 + }
80 +
81 + visitId(id: InstructionId): void {
82 + for (let i = 0; i < this.#stack.length; i++) {
83 + const scope = this.#stack[i]!;
84 + if (scope.kind === "scope" && id >= scope.block.range.end) {
85 + this.#stack.length = i;
86 + break;
87 + }
88 + }
89 + const last = this.#stack[this.#stack.length - 1]!;
90 + if (last.kind === "block") {
91 + this.#instructions = last.block;
92 + } else {
93 + this.#instructions = last.block.instructions;
94 + }
95 + }
96 +
97 + complete(): ReactiveBasicBlock {
98 + // TODO @josephsavona: debug two failures of this
99 + // invariant(
100 + // this.#stack.length === 1,
101 + // "Expected all scopes to be closed when exiting a block"
102 + // );
103 + const first = this.#stack[0]!;
104 + invariant(
105 + first.kind === "block",
106 + "Expected first stack item to be a basic block"
107 + );
108 + return first.block;
109 + }
110 +}
111 +
112 +class ReactiveFunctionBuilder
113 + implements
114 + Visitor<
115 + Builder,
116 + ReactiveBasicBlock,
117 + ReactiveValueBlock,
118 + ReactiveValueBlock,
119 + InstructionValue | ReactiveValueBlock,
120 + ReactiveInstruction,
121 + { test: InstructionValue | null; block: ReactiveBasicBlock }
122 + >
123 +{
124 + #builders: Array<Builder> = [];
125 + #scopes: Set<ScopeId> = new Set();
126 +
127 + visitId(id: InstructionId): void {
128 + const builder = this.#builders[this.#builders.length - 1]!;
129 + builder.visitId(id);
130 + }
131 +
132 + enterBlock(): Builder {
133 + const builder = new Builder();
134 + this.#builders.push(builder);
135 + return builder;
136 + }
137 + appendBlock(
138 + block: Builder,
139 + item: ReactiveInstruction,
140 + label?: BlockId | undefined
141 + ): void {
142 + block.append(item, label);
143 + }
144 + leaveBlock(block: Builder): ReactiveBasicBlock {
145 + const builder = this.#builders.pop();
146 + invariant(
147 + builder === block,
148 + "Expected enterBlock/leaveBlock to be called 1:1"
149 + );
150 + return block.complete();
151 + }
152 +
153 + enterValueBlock(block: Builder): ReactiveValueBlock {
154 + return {
155 + kind: "value-block",
156 + instructions: [],
157 + value: null,
158 + };
159 + }
160 + appendValueBlock(block: ReactiveValueBlock, item: ReactiveInstruction): void {
161 + block.instructions.push(item);
162 + }
163 + leaveValueBlock(
164 + block: ReactiveValueBlock,
165 + value: InstructionValue | ReactiveValueBlock | null
166 + ): InstructionValue | ReactiveValueBlock {
167 + if (value !== null) {
168 + invariant(
169 + value.kind !== "value-block",
170 + "Expected value block to end in a value"
171 + );
172 + block.value = value;
173 + }
174 + return block;
175 + }
176 +
177 + enterInitBlock(block: Builder): ReactiveValueBlock {
178 + return this.enterValueBlock(block);
179 + }
180 + appendInitBlock(block: ReactiveValueBlock, item: ReactiveInstruction): void {
181 + this.appendValueBlock(block, item);
182 + }
183 + leaveInitBlock(block: ReactiveValueBlock): ReactiveValueBlock {
184 + return block;
185 + }
186 +
187 + visitValue(
188 + value: InstructionValue,
189 + id: InstructionId
190 + ): InstructionValue | ReactiveValueBlock {
191 + return value;
192 + }
193 + visitInstruction(
194 + instruction: Instruction,
195 + value: InstructionValue | ReactiveValueBlock
196 + ): ReactiveInstruction {
197 + this.visitId(instruction.id);
198 + const scope = getInstructionScope(instruction);
199 + if (scope !== null && !this.#scopes.has(scope.id)) {
200 + this.#scopes.add(scope.id);
201 + const builder = this.#builders[this.#builders.length - 1]!;
202 + builder.startScope(scope);
203 + }
204 + return { kind: "instruction", instruction };
205 + }
206 + visitTerminalId(id: InstructionId): void {
207 + this.visitId(id);
208 + }
209 + visitImplicitTerminal(): ReactiveInstruction | null {
210 + return null;
211 + }
212 + visitTerminal(
213 + terminal: BlockTerminal<
214 + ReactiveValueBlock,
215 + InstructionValue | ReactiveValueBlock,
216 + ReactiveBasicBlock,
217 + { test: InstructionValue | null; block: ReactiveBasicBlock }
218 + >
219 + ): ReactiveInstruction {
220 + let result: ReactiveTerminal;
221 + switch (terminal.kind) {
222 + case "break": {
223 + result = { kind: "break", label: terminal.label };
224 + break;
225 + }
226 + case "continue": {
227 + result = { kind: "continue", label: terminal.label };
228 + break;
229 + }
230 + case "for": {
231 + const { test, update } = terminal;
232 + result = {
233 + kind: "for",
234 + init: terminal.init,
235 + test: terminal.test as ReactiveValueBlock,
236 + update: terminal.update as ReactiveValueBlock,
237 + loop: terminal.loop,
238 + };
239 + break;
240 + }
241 + case "if": {
242 + result = {
243 + kind: "if",
244 + test: terminal.test as Place,
245 + consequent: terminal.consequent,
246 + alternate: terminal.alternate,
247 + };
248 + break;
249 + }
250 + case "return": {
251 + const value = terminal.value;
252 + if (value !== null && value.kind !== "Identifier") {
253 + invariant(false, "Expected return to be a Place");
254 + }
255 + result = { kind: "return", value };
256 + break;
257 + }
258 + case "switch": {
259 + result = {
260 + kind: "switch",
261 + test: terminal.test as Place,
262 + cases: terminal.cases as Array<{
263 + test: Place | null;
264 + block: ReactiveBasicBlock | void;
265 + }>,
266 + };
267 + break;
268 + }
269 + case "throw": {
270 + result = { kind: "throw", value: terminal.value as Place };
271 + break;
272 + }
273 + case "while": {
274 + result = {
275 + kind: "while",
276 + test: terminal.test as ReactiveValueBlock,
277 + loop: terminal.loop,
278 + };
279 + break;
280 + }
281 + default: {
282 + assertExhaustive(
283 + terminal,
284 + `Unexpected terminal kind '${(terminal as any).kind}'`
285 + );
286 + }
287 + }
288 + return {
289 + kind: "terminal",
290 + terminal: result,
291 + label: null,
292 + };
293 + }
294 + visitCase(
295 + test: InstructionValue | ReactiveValueBlock | null,
296 + block: ReactiveBasicBlock
297 + ): { test: InstructionValue | null; block: ReactiveBasicBlock } {
298 + if (test !== null && test.kind !== "Identifier") {
299 + invariant(false, "Expected a Place");
300 + }
301 + return { test, block };
302 + }
303 +}
304 +
305 +function getInstructionScope(instr: Instruction): ReactiveScope | null {
306 + let scope: ReactiveScope | null = null;
307 + if (
308 + instr.lvalue !== null &&
309 + instr.lvalue.place.identifier.scope !== null &&
310 + isScopeActive(instr.lvalue.place.identifier.scope, instr.id)
311 + ) {
312 + scope = instr.lvalue.place.identifier.scope;
313 + } else {
314 + for (const operand of eachInstructionOperand(instr)) {
315 + if (
316 + operand.identifier.scope !== null &&
317 + isScopeActive(operand.identifier.scope, instr.id)
318 + ) {
319 + scope = operand.identifier.scope;
320 + break;
321 + }
322 + }
323 + }
324 + if (
325 + scope !== null &&
326 + (scope.range.end > scope.range.start + 1 || mayAllocate(instr.value))
327 + ) {
328 + return scope;
329 + }
330 + return null;
331 +}
332 +
333 +function mayAllocate(value: InstructionValue): boolean {
334 + switch (value.kind) {
335 + case "BinaryExpression":
336 + case "Identifier":
337 + case "JSXText":
338 + case "Primitive": {
339 + return false;
340 + }
341 + case "ArrayExpression":
342 + case "CallExpression":
343 + case "JsxExpression":
344 + case "JsxFragment":
345 + case "NewExpression":
346 + case "ObjectExpression":
347 + case "OtherStatement":
348 + case "UnaryExpression": {
349 + return true;
350 + }
351 + default: {
352 + assertExhaustive(value, `Unexpected value kind '${(value as any).kind}'`);
353 + }
354 + }
355 +}
356 +
357 +function isScopeActive(scope: ReactiveScope, id: InstructionId): boolean {
358 + return id >= scope.range.start && id < scope.range.end;
359 +}
360 +
361 +class ArraySet<T> {
362 + items: Array<T> = [];
363 + set: Set<T> = new Set();
364 +
365 + add(item: T) {
366 + if (!this.set.has(item)) {
367 + this.set.add(item);
368 + this.items.push(item);
369 + }
370 + }
371 +
372 + delete(item: T) {
373 + if (this.set.has(item)) {
374 + this.set.delete(item);
375 + this.items.splice(
376 + this.items.findIndex((x) => x === item),
377 + 1
378 + );
379 + }
380 + }
381 +
382 + has(item: T): boolean {
383 + return this.set.has(item);
384 + }
385 +
386 + last(): T {
387 + invariant(this.items.length > 0, "Called ArraySet::last on empty set");
388 + return this.items[this.items.length - 1];
389 + }
390 +
391 + *[Symbol.iterator]() {
392 + yield* this.items;
393 + }
394 +}
compiler/forget/src/HIR/HIR.ts
+68 -22
@@ -14,47 +14,93 @@ import { invariant } from "../CompilerError";
14 // *******************************************************************************************
15 // *******************************************************************************************
16
17 -// option 1: control dependencies using CFG (done in Joe's PR)
18 -// option 2: reachability (did execution reach this point last time, if not calculate)
19 -// option 3: push change variable calculation to point of use (more allocations)
20 -// option 4: compute intermediates
21 -
22 -// AST -> (lowering) -> HIR -> (dep analysis) -> Reactive Scopes -> (scheduling?) -> HIR -> (codegen) -> AST
17 +// AST -> (lowering) -> HIR -> (analysis) -> Reactive Scopes -> (scheduling?) -> HIR -> (codegen) -> AST
18
19 /**
20 * A location in a source file, intended to be used for providing diagnostic information and
21 * transforming code while preserving source information (ie to emit source maps).
22 *
23 * `GeneratedSource` indicates that there is no single source location from which the code derives.
29 - *
24 */
25 export const GeneratedSource = Symbol();
26 export type SourceLocation = t.SourceLocation | typeof GeneratedSource;
27
28 /**
35 - * A React function defines a computation that takes some set of reactive
36 - * inputs (eg props, hook arguments) and returns a result (JSX, hook return
37 - * value). It is composed of one or more Reactive Scopes, where each
38 - * Reactive Scope takes a set of reactive inputs and produces one *or more*
39 - * result values. The idea is that each Reactive Scope is responsible for
40 - * producing its result values whenever its inputs change: scopes contain
41 - * instructions to produce the result values, deriving from the inputs
42 - * as well as from the results of other scopes.
29 + * A React function defines a computation that takes some set of reactive inputs
30 + * (props, hook arguments) and return a result (JSX, hook return value). Unlike
31 + * HIR, the data model is tree-shaped:
32 + *
33 + * ReactFunction
34 + * ReactiveBlock
35 + * ReactiveBlockScope*
36 + * Place* (dependencies)
37 + * (ReactiveInstruction | ReactiveTerminal)*
38 *
44 - * A React function comprises a Reactive Scope responsible for producing the
45 - * return value of the function, plus additional scopes that the return scopes
46 - * may depend upon (transitively).
39 + * Where ReactiveTerminal may recursively contain zero or more ReactiveBlocks.
40 + *
41 + * Each ReactiveBlockScope describes a set of dependencies as well as the instructions (and terminals)
42 + * within that scope.
43 */
48 -export type ReactFunction = {
44 +export type ReactiveFunction = {
45 loc: SourceLocation;
46 id: Identifier | null;
47 params: Array<Place>;
52 - returnScope: ScopeId;
53 - scopes: Map<ScopeId, ReactiveScope>;
48 + generator: boolean;
49 + async: boolean;
50 + body: ReactiveBasicBlock;
51 +};
52 +
53 +export type ReactiveBlock = {
54 + kind: "block";
55 + id: ScopeId;
56 + range: MutableRange;
57 + dependencies: Set<Place>;
58 + instructions: ReactiveBasicBlock;
59 };
60
61 +export type ReactiveBasicBlock = Array<ReactiveInstruction>;
62 +
63 +export type ReactiveValueBlock = {
64 + kind: "value-block";
65 + instructions: ReactiveBasicBlock;
66 + value: InstructionValue | null;
67 +};
68 +
69 +export type ReactiveInstruction =
70 + | { kind: "instruction"; instruction: Instruction }
71 + | { kind: "terminal"; terminal: ReactiveTerminal; label: BlockId | null }
72 + | ReactiveBlock;
73 +
74 +export type ReactiveTerminal =
75 + | { kind: "break"; label: BlockId | null }
76 + | { kind: "continue"; label: BlockId | null }
77 + | { kind: "return"; value: Place | null }
78 + | { kind: "throw"; value: Place }
79 + | {
80 + kind: "switch";
81 + test: Place;
82 + cases: Array<{
83 + test: Place | null;
84 + block: ReactiveBasicBlock | void;
85 + }>;
86 + }
87 + | { kind: "while"; test: ReactiveValueBlock; loop: ReactiveBasicBlock }
88 + | {
89 + kind: "for";
90 + init: ReactiveValueBlock;
91 + test: ReactiveValueBlock;
92 + update: ReactiveValueBlock;
93 + loop: ReactiveBasicBlock;
94 + }
95 + | {
96 + kind: "if";
97 + test: Place;
98 + consequent: ReactiveBasicBlock;
99 + alternate: ReactiveBasicBlock | null;
100 + };
101 +
102 /**
57 - * A function declaration including its path
103 + * A function lowered to HIR form, ie where its body is lowered to an HIR control-flow graph
104 */
105 export type HIRFunction = {
106 loc: SourceLocation;
compiler/forget/src/HIR/InferReactiveScopeVariables.ts
+6 -6
@@ -77,15 +77,15 @@ export function inferReactiveScopeVariables(fn: HIRFunction) {
77 for (const instr of block.instructions) {
78 const operands: Array<Identifier> = [];
79 if (instr.lvalue !== null) {
80 - // invariant(
81 - // isMutable(instr, instr.lvalue!.place),
82 - // "Assignment always means the value is mutable:\n" +
83 - // printMixedHIR(instr)
84 - // );
80 operands.push(instr.lvalue!.place.identifier);
81 }
82 for (const operand of eachInstructionOperand(instr)) {
88 - if (isMutable(instr, operand)) {
83 + if (
84 + isMutable(instr, operand) &&
85 + // exclude global variables from being added to scopes, we can't recreate them!
86 + // TODO: improve handling of module-scoped variables and globals
87 + operand.identifier.mutableRange.start > 0
88 + ) {
89 operands.push(operand.identifier);
90 }
91 }
compiler/forget/src/HIR/PrintReactiveFunction.ts new
+204
@@ -0,0 +1,204 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + */
7 +
8 +import invariant from "invariant";
9 +import { assertExhaustive } from "../Common/utils";
10 +import {
11 + ReactiveBlock,
12 + ReactiveFunction,
13 + ReactiveInstruction,
14 + ReactiveTerminal,
15 + ReactiveValueBlock,
16 +} from "./HIR";
17 +import {
18 + printInstruction,
19 + printInstructionValue,
20 + printPlace,
21 +} from "./PrintHIR";
22 +
23 +export function printReactiveFunction(fn: ReactiveFunction): string {
24 + const writer = new Writer();
25 + writer.writeLine(`function ${fn.id?.name ?? "<unknown>"}(`);
26 + writer.indented(() => {
27 + for (const param of fn.params) {
28 + writer.writeLine(`${param.identifier.name ?? "<param>"},`);
29 + }
30 + });
31 + writer.writeLine(") {");
32 + printReactiveInstructions(writer, fn.body);
33 + writer.writeLine("}");
34 + return writer.complete();
35 +}
36 +
37 +export function printReactiveBlock(writer: Writer, block: ReactiveBlock): void {
38 + writer.writeLine(
39 + `scope @${block.id} [${block.range.start}:${
40 + block.range.end
41 + }] deps=[${Array.from(block.dependencies)
42 + .map((dep) => printPlace(dep))
43 + .join(", ")}] {`
44 + );
45 + printReactiveInstructions(writer, block.instructions);
46 + writer.writeLine("}");
47 +}
48 +
49 +export function printReactiveInstructions(
50 + writer: Writer,
51 + instructions: Array<ReactiveInstruction>
52 +): void {
53 + writer.indented(() => {
54 + for (const instr of instructions) {
55 + printReactiveInstruction(writer, instr);
56 + }
57 + });
58 +}
59 +
60 +function printReactiveInstruction(
61 + writer: Writer,
62 + instr: ReactiveInstruction
63 +): void {
64 + switch (instr.kind) {
65 + case "instruction": {
66 + writer.writeLine(printInstruction(instr.instruction));
67 + break;
68 + }
69 + case "block": {
70 + printReactiveBlock(writer, instr);
71 + break;
72 + }
73 + case "terminal": {
74 + printTerminal(writer, instr.terminal);
75 + break;
76 + }
77 + default: {
78 + assertExhaustive(
79 + instr,
80 + `Unexpected terminal kind '${(instr as any).kind}'`
81 + );
82 + }
83 + }
84 +}
85 +
86 +function printValueBlock(writer: Writer, block: ReactiveValueBlock): void {
87 + writer.indented(() => {
88 + for (const instr of block.instructions) {
89 + printReactiveInstruction(writer, instr);
90 + }
91 + if (block.value !== null) {
92 + writer.writeLine(printInstructionValue(block.value));
93 + }
94 + });
95 +}
96 +
97 +function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
98 + switch (terminal.kind) {
99 + case "break": {
100 + if (terminal.label !== null) {
101 + writer.writeLine(`break bb${terminal.label}`);
102 + } else {
103 + writer.writeLine(`break`);
104 + }
105 + break;
106 + }
107 + case "continue": {
108 + if (terminal.label !== null) {
109 + writer.writeLine(`continue bb${terminal.label}`);
110 + } else {
111 + writer.writeLine(`continue`);
112 + }
113 + break;
114 + }
115 + case "while": {
116 + writer.writeLine(`while (`);
117 + printValueBlock(writer, terminal.test);
118 + writer.writeLine(") {");
119 + printReactiveInstructions(writer, terminal.loop);
120 + writer.writeLine("}");
121 + break;
122 + }
123 + case "if": {
124 + const { test, consequent, alternate } = terminal;
125 + writer.writeLine(`if (${printPlace(test)}) {`);
126 + printReactiveInstructions(writer, consequent);
127 + if (alternate !== null) {
128 + writer.writeLine("} else {");
129 + printReactiveInstructions(writer, alternate);
130 + }
131 + writer.writeLine("}");
132 + break;
133 + }
134 + case "switch": {
135 + writer.writeLine(`switch (${printPlace(terminal.test)}) {`);
136 + writer.indented(() => {
137 + for (const case_ of terminal.cases) {
138 + let prefix =
139 + case_.test !== null ? `case ${printPlace(case_.test)}` : "default";
140 + writer.writeLine(`${prefix}: {`);
141 + writer.indented(() => {
142 + const block = case_.block;
143 + invariant(block != null, "Expected case to have a block");
144 + printReactiveInstructions(writer, block);
145 + });
146 + writer.writeLine("}");
147 + }
148 + });
149 + writer.writeLine("}");
150 + break;
151 + }
152 + case "for": {
153 + writer.writeLine("for (");
154 + printValueBlock(writer, terminal.init);
155 + writer.writeLine(";");
156 + printValueBlock(writer, terminal.test);
157 + writer.writeLine(";");
158 + printValueBlock(writer, terminal.update);
159 + writer.writeLine(") {");
160 + printReactiveInstructions(writer, terminal.loop);
161 + writer.writeLine("}");
162 + break;
163 + }
164 + case "throw": {
165 + writer.writeLine(`throw ${printPlace(terminal.value)}`);
166 + break;
167 + }
168 + case "return": {
169 + if (terminal.value !== null) {
170 + writer.writeLine(`return ${printPlace(terminal.value)}`);
171 + } else {
172 + writer.writeLine("return");
173 + }
174 + break;
175 + }
176 + }
177 +}
178 +
179 +export class Writer {
180 + #out: Array<string> = [];
181 + #depth: number;
182 +
183 + constructor({ depth }: { depth: number } = { depth: 0 }) {
184 + this.#depth = depth;
185 + }
186 +
187 + complete(): string {
188 + return this.#out.join("");
189 + }
190 +
191 + write(s: string): void {
192 + this.#out.push(" ".repeat(this.#depth) + s);
193 + }
194 +
195 + writeLine(s: string): void {
196 + this.#out.push(" ".repeat(this.#depth) + s + "\n");
197 + }
198 +
199 + indented(f: () => void): void {
200 + this.#depth++;
201 + f();
202 + this.#depth--;
203 + }
204 +}
compiler/forget/src/__tests__/fixtures/hir/_bug_conditional-break-labeled.expect.md new
+110
@@ -0,0 +1,110 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +/**
6 + * props.b *does* influence `a`
7 + */
8 +function Component(props) {
9 + const a = [];
10 + a.push(props.a);
11 + label: {
12 + if (props.b) {
13 + break label;
14 + }
15 + a.push(props.c);
16 + }
17 + a.push(props.d);
18 + return a;
19 +}
20 +
21 +```
22 +
23 +## HIR
24 +
25 +```
26 +bb0:
27 + [1] Const mutate a$4_@0[1:7] = Array []
28 + [2] Call mutate a$4_@0.push(read props$3.a)
29 + [3] If (read props$3.b) then:bb1 else:bb2 fallthrough=bb2
30 +bb2:
31 + predecessor blocks: bb0
32 + [4] Call mutate a$4_@0.push(read props$3.c)
33 + [5] Goto bb1
34 +bb1:
35 + predecessor blocks: bb0 bb2
36 + [6] Call mutate a$4_@0.push(read props$3.d)
37 + [7] Return freeze a$4_@0
38 +scope0 [1:7]:
39 + - dependency: read props$3.a
40 + - dependency: read props$3.d
41 + - dependency: read props$3.c
42 +```
43 +
44 +## Reactive Scopes
45 +
46 +```
47 +function Component(
48 + props,
49 +) {
50 + scope @0 [1:7] deps=[read props$3.a, read props$3.d, read props$3.c] {
51 + [1] Const mutate a$4_@0[1:7] = Array []
52 + [2] Call mutate a$4_@0.push(read props$3.a)
53 + if (read props$3.b) {
54 + [6] Call mutate a$4_@0.push(read props$3.d)
55 + return freeze a$4_@0
56 + }
57 + [4] Call mutate a$4_@0.push(read props$3.c)
58 + }
59 +}
60 +
61 +```
62 +
63 +### CFG
64 +
65 +```mermaid
66 +flowchart TB
67 + %% Basic Blocks
68 + subgraph bb0
69 + bb0_instrs["
70 + [1] Const mutate a$4_@0[1:7] = Array []
71 + [2] Call mutate a$4_@0.push(read props$3.a)
72 + "]
73 + bb0_instrs --> bb0_terminal(["If (read props$3.b)"])
74 + end
75 + subgraph bb2
76 + bb2_instrs["
77 + [4] Call mutate a$4_@0.push(read props$3.c)
78 + "]
79 + bb2_instrs --> bb2_terminal(["Goto"])
80 + end
81 + subgraph bb1
82 + bb1_instrs["
83 + [6] Call mutate a$4_@0.push(read props$3.d)
84 + "]
85 + bb1_instrs --> bb1_terminal(["Return freeze a$4_@0"])
86 + end
87 +
88 + %% Jumps
89 + bb0_terminal -- "then" --> bb1
90 + bb0_terminal -- "else" --> bb2
91 + bb2_terminal --> bb1
92 +
93 +```
94 +
95 +## Code
96 +
97 +```javascript
98 +function Component$0(props$3) {
99 + const a$4 = [];
100 + a$4.push(props$3.a);
101 + bb2: if (props$3.b) {
102 + a$4.push(props$3.d);
103 + return a$4;
104 + }
105 +
106 + a$4.push(props$3.c);
107 +}
108 +
109 +```
110 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/_bug_conditional-break-labeled.js new
+15
@@ -0,0 +1,15 @@
1 +/**
2 + * props.b *does* influence `a`
3 + */
4 +function Component(props) {
5 + const a = [];
6 + a.push(props.a);
7 + label: {
8 + if (props.b) {
9 + break label;
10 + }
11 + a.push(props.c);
12 + }
13 + a.push(props.d);
14 + return a;
15 +}
compiler/forget/src/__tests__/fixtures/hir/_bug_expression-with-assignment.expect.md
+14
@@ -28,6 +28,20 @@ scope3 [4:5]:
28 - dependency: read x$5_@1
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function f(
35 +) {
36 + [1] Const mutate x$4_@0 = 1
37 + [2] Const mutate x$5_@1 = 2
38 + [3] Const mutate $6_@2 = Binary read x$5_@1 + read x$5_@1
39 + [4] Const mutate $7_@3 = Binary read $6_@2 + read x$5_@1
40 + return read $7_@3
41 +}
42 +
43 +```
44 +
45 ### CFG
46
47 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/_bug_inverted-if-else.expect.md
+17
@@ -39,6 +39,23 @@ scope2 [5:6]:
39 - dependency: read c$7
40 ```
41
42 +## Reactive Scopes
43 +
44 +```
45 +function foo(
46 + a,
47 + b,
48 + c,
49 +) {
50 + [1] Const mutate x$8_@0 = null
51 + if (read a$5) {
52 + [3] Const mutate x$9_@1 = read b$6
53 + }
54 + [5] Const mutate x$10_@2 = read c$7
55 +}
56 +
57 +```
58 +
59 ### CFG
60
61 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path-mutate.expect.md
+30 -12
@@ -17,16 +17,34 @@ function component() {
17
18 ```
19 bb0:
20 - [1] Const mutate z$5_@0[0:7] = Array []
21 - [2] Const mutate y$6_@0[0:7] = Object { }
22 - [3] Reassign mutate y$6_@0.z[0:7] = read z$5_@0
23 - [4] Const mutate x$7_@0[0:7] = Object { }
24 - [5] Reassign mutate x$7_@0.y[0:7] = read y$6_@0
25 - [6] Call mutate mutate$4_@0(mutate x$7_@0.y.z)
20 + [1] Const mutate z$5_@0[1:7] = Array []
21 + [2] Const mutate y$6_@0[1:7] = Object { }
22 + [3] Reassign mutate y$6_@0.z[1:7] = read z$5_@0
23 + [4] Const mutate x$7_@0[1:7] = Object { }
24 + [5] Reassign mutate x$7_@0.y[1:7] = read y$6_@0
25 + [6] Call mutate mutate$4(mutate x$7_@0.y.z)
26 [7] Return
27
28 ```
29
30 +## Reactive Scopes
31 +
32 +```
33 +function component(
34 +) {
35 + scope @0 [1:7] deps=[] {
36 + [1] Const mutate z$5_@0[1:7] = Array []
37 + [2] Const mutate y$6_@0[1:7] = Object { }
38 + [3] Reassign mutate y$6_@0.z[1:7] = read z$5_@0
39 + [4] Const mutate x$7_@0[1:7] = Object { }
40 + [5] Reassign mutate x$7_@0.y[1:7] = read y$6_@0
41 + [6] Call mutate mutate$4(mutate x$7_@0.y.z)
42 + }
43 + return
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
@@ -34,12 +52,12 @@ flowchart TB
52 %% Basic Blocks
53 subgraph bb0
54 bb0_instrs["
37 - [1] Const mutate z$5_@0[0:7] = Array []
38 - [2] Const mutate y$6_@0[0:7] = Object { }
39 - [3] Reassign mutate y$6_@0.z[0:7] = read z$5_@0
40 - [4] Const mutate x$7_@0[0:7] = Object { }
41 - [5] Reassign mutate x$7_@0.y[0:7] = read y$6_@0
42 - [6] Call mutate mutate$4_@0(mutate x$7_@0.y.z)
55 + [1] Const mutate z$5_@0[1:7] = Array []
56 + [2] Const mutate y$6_@0[1:7] = Object { }
57 + [3] Reassign mutate y$6_@0.z[1:7] = read z$5_@0
58 + [4] Const mutate x$7_@0[1:7] = Object { }
59 + [5] Reassign mutate x$7_@0.y[1:7] = read y$6_@0
60 + [6] Call mutate mutate$4(mutate x$7_@0.y.z)
61 "]
62 bb0_instrs --> bb0_terminal(["Return"])
63 end
compiler/forget/src/__tests__/fixtures/hir/alias-nested-member-path.expect.md
+21
@@ -29,6 +29,27 @@ scope2 [4:6]:
29 - dependency: read y$5_@1
30 ```
31
32 +## Reactive Scopes
33 +
34 +```
35 +function component(
36 +) {
37 + scope @0 [1:2] deps=[] {
38 + [1] Const mutate z$4_@0 = Array []
39 + }
40 + scope @1 [2:4] deps=[read z$4_@0] {
41 + [2] Const mutate y$5_@1[2:4] = Object { }
42 + [3] Reassign mutate y$5_@1.z[2:4] = read z$4_@0
43 + }
44 + scope @2 [4:6] deps=[read y$5_@1] {
45 + [4] Const mutate x$6_@2[4:6] = Object { }
46 + [5] Reassign mutate x$6_@2.y[4:6] = read y$5_@1
47 + }
48 + return freeze x$6_@2
49 +}
50 +
51 +```
52 +
53 ### CFG
54
55 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/alias-while.expect.md
+57 -16
@@ -27,20 +27,20 @@ function mutate(x, y) {}
27
28 ```
29 bb0:
30 - [1] Let mutate a$8_@0[0:12] = Object { }
31 - [2] Let mutate b$9_@0[0:12] = Object { }
32 - [3] Let mutate c$10_@0[0:12] = Object { }
30 + [1] Let mutate a$8_@0[1:12] = Object { }
31 + [2] Let mutate b$9_@0[1:12] = Object { }
32 + [3] Let mutate c$10_@0[1:12] = Object { }
33 [4] While test=bb1 loop=bb3 fallthrough=bb2
34 bb1:
35 predecessor blocks: bb0 bb3
36 [5] If (read cond$7) then:bb3 else:bb2 fallthrough=bb2
37 bb3:
38 predecessor blocks: bb1
39 - [6] Const mutate z$13_@0[0:12] = read a$8_@0
40 - [7] Reassign mutate a$8_@0[0:12] = read b$9_@0
41 - [8] Reassign mutate b$9_@0[0:12] = read c$10_@0
42 - [9] Reassign mutate c$10_@0[0:12] = read z$13_@0
43 - [10] Call mutate mutate$6_@0(mutate a$8_@0, mutate b$9_@0)
39 + [6] Const mutate z$13_@0[1:12] = read a$8_@0
40 + [7] Reassign mutate a$8_@0[1:12] = read b$9_@0
41 + [8] Reassign mutate b$9_@0[1:12] = read c$10_@0
42 + [9] Reassign mutate c$10_@0[1:12] = read z$13_@0
43 + [10] Call mutate mutate$6(mutate a$8_@0, mutate b$9_@0)
44 [11] Goto(Continue) bb1
45 bb2:
46 predecessor blocks: bb1
@@ -48,6 +48,35 @@ bb2:
48 [13] read b$9_@0
49 [14] read c$10_@0
50 [15] Return freeze a$8_@0
51 +scope0 [1:12]:
52 + - dependency: read cond$7
53 +```
54 +
55 +## Reactive Scopes
56 +
57 +```
58 +function foo(
59 + cond,
60 +) {
61 + scope @0 [1:12] deps=[read cond$7] {
62 + [1] Let mutate a$8_@0[1:12] = Object { }
63 + [2] Let mutate b$9_@0[1:12] = Object { }
64 + [3] Let mutate c$10_@0[1:12] = Object { }
65 + while (
66 + read cond$7
67 + ) {
68 + [6] Const mutate z$13_@0[1:12] = read a$8_@0
69 + [7] Reassign mutate a$8_@0[1:12] = read b$9_@0
70 + [8] Reassign mutate b$9_@0[1:12] = read c$10_@0
71 + [9] Reassign mutate c$10_@0[1:12] = read z$13_@0
72 + [10] Call mutate mutate$6(mutate a$8_@0, mutate b$9_@0)
73 + }
74 + }
75 + [12] read a$8_@0
76 + [13] read b$9_@0
77 + [14] read c$10_@0
78 + return freeze a$8_@0
79 +}
80
81 ```
82
@@ -58,9 +87,9 @@ flowchart TB
87 %% Basic Blocks
88 subgraph bb0
89 bb0_instrs["
61 - [1] Let mutate a$8_@0[0:12] = Object { }
62 - [2] Let mutate b$9_@0[0:12] = Object { }
63 - [3] Let mutate c$10_@0[0:12] = Object { }
90 + [1] Let mutate a$8_@0[1:12] = Object { }
91 + [2] Let mutate b$9_@0[1:12] = Object { }
92 + [3] Let mutate c$10_@0[1:12] = Object { }
93 "]
94 bb0_instrs --> bb0_terminal(["While"])
95 end
@@ -69,11 +98,11 @@ flowchart TB
98 end
99 subgraph bb3
100 bb3_instrs["
72 - [6] Const mutate z$13_@0[0:12] = read a$8_@0
73 - [7] Reassign mutate a$8_@0[0:12] = read b$9_@0
74 - [8] Reassign mutate b$9_@0[0:12] = read c$10_@0
75 - [9] Reassign mutate c$10_@0[0:12] = read z$13_@0
76 - [10] Call mutate mutate$6_@0(mutate a$8_@0, mutate b$9_@0)
101 + [6] Const mutate z$13_@0[1:12] = read a$8_@0
102 + [7] Reassign mutate a$8_@0[1:12] = read b$9_@0
103 + [8] Reassign mutate b$9_@0[1:12] = read c$10_@0
104 + [9] Reassign mutate c$10_@0[1:12] = read z$13_@0
105 + [10] Call mutate mutate$6(mutate a$8_@0, mutate b$9_@0)
106 "]
107 bb3_instrs --> bb3_terminal(["Goto"])
108 end
@@ -126,6 +155,18 @@ bb0:
155
156 ```
157
158 +## Reactive Scopes
159 +
160 +```
161 +function mutate(
162 + x,
163 + y,
164 +) {
165 + return
166 +}
167 +
168 +```
169 +
170 ### CFG
171
172 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/assignment-variations.expect.md
+34
@@ -39,6 +39,23 @@ scope6 [7:8]:
39 - dependency: read $10_@5
40 ```
41
42 +## Reactive Scopes
43 +
44 +```
45 +function f(
46 +) {
47 + [1] Const mutate x$5_@0 = 1
48 + [2] Const mutate $6_@1 = 1
49 + [3] Const mutate x$7_@2 = Binary read x$5_@0 + read $6_@1
50 + [4] Const mutate $8_@3 = 1
51 + [5] Const mutate x$9_@4 = Binary read x$7_@2 + read $8_@3
52 + [6] Const mutate $10_@5 = 1
53 + [7] Const mutate x$11_@6 = Binary read x$9_@4 >>> read $10_@5
54 + return
55 +}
56 +
57 +```
58 +
59 ### CFG
60
61 ```mermaid
@@ -85,6 +102,23 @@ scope2 [3:4]:
102 - dependency: mutate a$4_@1.b.c
103 ```
104
105 +## Reactive Scopes
106 +
107 +```
108 +function g(
109 + a,
110 +) {
111 + [1] Const mutate $5_@0 = 1
112 + scope @1 [0:5] deps=[] {
113 + [2] Reassign mutate a$4_@1.b.c[0:5] = Binary read a$4_@1.b.c + read $5_@0
114 + [3] Const mutate $6_@2 = 2
115 + [4] Reassign mutate a$4_@1.b.c[0:5] = Binary read a$4_@1.b.c * read $6_@2
116 + }
117 + return
118 +}
119 +
120 +```
121 +
122 ### CFG
123
124 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/call.expect.md
+43 -8
@@ -23,6 +23,16 @@ bb0:
23
24 ```
25
26 +## Reactive Scopes
27 +
28 +```
29 +function foo(
30 +) {
31 + return
32 +}
33 +
34 +```
35 +
36 ### CFG
37
38 ```mermaid
@@ -46,12 +56,12 @@ function foo$0() {}
56
57 ```
58 bb0:
49 - [1] Const mutate a$10_@0[0:7] = Array []
50 - [2] Const mutate b$11_@0[0:7] = Object { }
51 - [3] Call mutate foo$4_@0(mutate a$10_@0, mutate b$11_@0)
59 + [1] Const mutate a$10_@0[1:7] = Array []
60 + [2] Const mutate b$11_@0[1:7] = Object { }
61 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
62 [4] Const mutate $12_@1 = "div"
63 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
54 - [6] Call mutate foo$4_@0(mutate b$11_@0)
64 + [6] Call mutate foo$4(mutate b$11_@0)
65 [7] Const mutate $14_@3 = "div"
66 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
67 [9] Return read $15_@4
@@ -63,6 +73,31 @@ scope4 [8:9]:
73 - dependency: freeze b$11_@0
74 ```
75
76 +## Reactive Scopes
77 +
78 +```
79 +function Component(
80 + props,
81 +) {
82 + scope @0 [1:7] deps=[] {
83 + [1] Const mutate a$10_@0[1:7] = Array []
84 + [2] Const mutate b$11_@0[1:7] = Object { }
85 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
86 + [4] Const mutate $12_@1 = "div"
87 + scope @2 [5:6] deps=[read $12_@1] {
88 + [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
89 + }
90 + [6] Call mutate foo$4(mutate b$11_@0)
91 + }
92 + [7] Const mutate $14_@3 = "div"
93 + scope @4 [8:9] deps=[read $14_@3, read a$10_@0, freeze b$11_@0] {
94 + [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
95 + }
96 + return read $15_@4
97 +}
98 +
99 +```
100 +
101 ### CFG
102
103 ```mermaid
@@ -70,12 +105,12 @@ flowchart TB
105 %% Basic Blocks
106 subgraph bb0
107 bb0_instrs["
73 - [1] Const mutate a$10_@0[0:7] = Array []
74 - [2] Const mutate b$11_@0[0:7] = Object { }
75 - [3] Call mutate foo$4_@0(mutate a$10_@0, mutate b$11_@0)
108 + [1] Const mutate a$10_@0[1:7] = Array []
109 + [2] Const mutate b$11_@0[1:7] = Object { }
110 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
111 [4] Const mutate $12_@1 = 'div'
112 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
78 - [6] Call mutate foo$4_@0(mutate b$11_@0)
113 + [6] Call mutate foo$4(mutate b$11_@0)
114 [7] Const mutate $14_@3 = 'div'
115 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
116 "]
compiler/forget/src/__tests__/fixtures/hir/complex-while.expect.md
+22
@@ -37,6 +37,28 @@ bb1:
37
38 ```
39
40 +## Reactive Scopes
41 +
42 +```
43 +function foo(
44 + a,
45 + b,
46 + c,
47 +) {
48 + if (read a$4) {
49 + while (
50 + read b$5
51 + ) {
52 + if (read c$6) {
53 + break
54 + }
55 + }
56 + }
57 + return
58 +}
59 +
60 +```
61 +
62 ### CFG
63
64 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+263 -114
@@ -2,7 +2,6 @@
2 ## Input
3
4 ```javascript
5 -// @Out DefUseGraph
5 function Component(props) {
6 const items = props.items;
7 const maxItems = props.maxItems;
@@ -10,7 +9,8 @@ function Component(props) {
9 const renderedItems = [];
10 const seen = new Set();
11 const max = Math.max(0, maxItems);
13 - for (const item of items) {
12 + for (let i = 0; i < items.length; i += 1) {
13 + const item = items.at(i);
14 if (item == null || seen.has(item)) {
15 continue;
16 }
@@ -35,63 +35,162 @@ function Component(props) {
35
36 ```
37 bb0:
38 - [1] Const mutate items$27_@0 = read props$26.items
39 - [2] Const mutate maxItems$28_@1 = read props$26.maxItems
40 - [3] Const mutate renderedItems$29_@2[3:22] = Array []
41 - [4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
42 - [5] Const mutate $31_@4 = 0
43 - [6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
44 - [7] Goto bb1
45 -bb1:
46 - predecessor blocks: bb0 bb5 bb10
47 - [8] If (read items$27_@0) then:bb3 else:bb2 fallthrough=bb2
38 + [1] Const mutate items$30_@0 = read props$29.items
39 + [2] Const mutate maxItems$31_@1 = read props$29.maxItems
40 + [3] Const mutate renderedItems$32_@2[3:33] = Array []
41 + [4] Const mutate seen$33_@2[3:33] = New mutate Set$6()
42 + [5] Const mutate $34_@4 = 0
43 + [6] Const mutate max$35_@5 = Call mutate Math$8.max(read $34_@4, read maxItems$31_@1)
44 + [7] For init=bb3 test=bb1 loop=bb5 update=bb4 fallthrough=bb2
45 bb3:
46 + predecessor blocks: bb0
47 + [8] Let mutate i$36_@2[3:33] = 0
48 + [9] Goto bb1
49 +bb1:
50 + predecessor blocks: bb3 bb4
51 + [10] Const mutate $39_@2[3:33] = Binary read i$36_@2 < read items$30_@0.length
52 + [11] If (read $39_@2) then:bb5 else:bb2 fallthrough=bb2
53 +bb5:
54 predecessor blocks: bb1
50 - [9] Const mutate $34_@6 = null
51 - [10] Const mutate $36_@3[0:19] = Binary read item$10_@3 == read $34_@6
52 - [11] Let mutate $37_@3[0:19] = undefined
53 - [11] If (read $36_@3) then:bb8 else:bb9 fallthrough=bb7
54 -bb8:
55 - predecessor blocks: bb3
56 - [12] Const mutate $37_@3[0:19] = read $36_@3
57 - [13] Goto bb7
55 + [12] Const mutate item$40_@2[3:33] = Call read items$30_@0.at(read i$36_@2)
56 + [13] Const mutate $41_@6 = null
57 + [14] Const mutate $42_@2[3:33] = Binary read item$40_@2 == read $41_@6
58 + [15] Let mutate $43_@2[3:33] = undefined
59 + [15] If (read $42_@2) then:bb10 else:bb11 fallthrough=bb9
60 +bb10:
61 + predecessor blocks: bb5
62 + [16] Const mutate $43_@2[3:33] = read $42_@2
63 + [17] Goto bb9
64 +bb11:
65 + predecessor blocks: bb5
66 + [18] Const mutate $43_@2[3:33] = Call mutate seen$33_@2.has(mutate item$40_@2)
67 + [19] Goto bb9
68 bb9:
59 - predecessor blocks: bb3
60 - [14] Const mutate $37_@3[0:19] = Call mutate seen$30_@3.has(mutate item$10_@3)
61 - [15] Goto bb7
69 + predecessor blocks: bb10 bb11
70 + [20] If (read $43_@2) then:bb7 else:bb6 fallthrough=bb6
71 bb7:
63 - predecessor blocks: bb8 bb9
64 - [16] If (read $37_@3) then:bb5 else:bb4 fallthrough=bb4
65 -bb5:
66 - predecessor blocks: bb7
67 - [17] Goto(Continue) bb1
72 + predecessor blocks: bb9
73 + [21] Goto(Continue) bb4
74 +bb6:
75 + predecessor blocks: bb9
76 + [22] Call mutate seen$33_@2.add(mutate item$40_@2)
77 + [23] Const mutate $49_@7 = "div"
78 + [24] Const mutate $50_@8 = JSX <read $49_@7>{freeze item$40_@2}</read $49_@7>
79 + [25] Call mutate renderedItems$32_@2.push(read $50_@8)
80 + [26] Const mutate $55_@9 = Binary read renderedItems$32_@2.length >= read max$35_@5
81 + [27] If (read $55_@9) then:bb2 else:bb12 fallthrough=bb12
82 +bb12:
83 + predecessor blocks: bb6
84 + [28] Goto(Continue) bb4
85 bb4:
69 - predecessor blocks: bb7
70 - [18] Call mutate seen$30_@3.add(mutate item$10_@3)
71 - [19] Const mutate $43_@7 = "div"
72 - [20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
73 - [21] Call mutate renderedItems$29_@2.push(read $44_@8)
74 - [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
75 - [23] If (read $49_@9) then:bb2 else:bb10 fallthrough=bb10
76 -bb10:
77 - predecessor blocks: bb4
78 - [24] Goto(Continue) bb1
86 + predecessor blocks: bb7 bb12
87 + [29] Const mutate $56_@2[3:33] = 1
88 + [30] Reassign mutate i$36_@2[3:33] = Binary read i$36_@2 + read $56_@2
89 + [31] read i$36_@2
90 + [32] Goto bb1
91 bb2:
80 - predecessor blocks: bb4 bb1
81 - [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
82 - [26] Const mutate $53_@11 = "div"
83 - [27] Const mutate $54_@12 = "\n "
84 - [28] Const mutate $55_@13 = "h1"
85 - [29] Const mutate $56_@14 = " Items"
86 - [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
87 - [31] Const mutate $58_@16 = "\n "
88 - [32] Const mutate $59_@17 = "\n "
89 - [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
90 - [34] Return read $60_@18
92 + predecessor blocks: bb6 bb1
93 + [33] Const mutate count$66_@11 = read renderedItems$32_@2.length
94 + [34] Const mutate $67_@12 = "div"
95 + [35] Const mutate $68_@13 = "\n "
96 + [36] Const mutate $69_@14 = "h1"
97 + [37] Const mutate $70_@15 = " Items"
98 + [38] Const mutate $71_@16 = JSX <read $69_@14>{freeze count$66_@11}{read $70_@15}</read $69_@14>
99 + [39] Const mutate $72_@17 = "\n "
100 + [40] Const mutate $73_@18 = "\n "
101 + [41] Const mutate $74_@19 = JSX <read $67_@12>{read $68_@13}{read $71_@16}{read $72_@17}{freeze renderedItems$32_@2}{read $73_@18}</read $67_@12>
102 + [42] Return read $74_@19
103 scope0 [1:2]:
92 - - dependency: read props$26.items
104 + - dependency: read props$29.items
105 scope1 [2:3]:
94 - - dependency: read props$26.maxItems
106 + - dependency: read props$29.maxItems
107 +scope5 [6:7]:
108 + - dependency: read $34_@4
109 + - dependency: read maxItems$31_@1
110 +scope8 [24:25]:
111 + - dependency: read $49_@7
112 +scope9 [26:27]:
113 + - dependency: read max$35_@5
114 +scope11 [33:34]:
115 + - dependency: read renderedItems$32_@2.length
116 +scope16 [38:39]:
117 + - dependency: read $69_@14
118 + - dependency: freeze count$66_@11
119 + - dependency: read $70_@15
120 +scope19 [41:42]:
121 + - dependency: read $67_@12
122 + - dependency: read $68_@13
123 + - dependency: read $71_@16
124 + - dependency: read $72_@17
125 + - dependency: freeze renderedItems$32_@2
126 + - dependency: read $73_@18
127 +```
128 +
129 +## Reactive Scopes
130 +
131 +```
132 +function Component(
133 + props,
134 +) {
135 + [1] Const mutate items$30_@0 = read props$29.items
136 + [2] Const mutate maxItems$31_@1 = read props$29.maxItems
137 + scope @2 [3:33] deps=[] {
138 + [3] Const mutate renderedItems$32_@2[3:33] = Array []
139 + [4] Const mutate seen$33_@2[3:33] = New mutate Set$6()
140 + [5] Const mutate $34_@4 = 0
141 + scope @5 [6:7] deps=[read $34_@4, read maxItems$31_@1] {
142 + [6] Const mutate max$35_@5 = Call mutate Math$8.max(read $34_@4, read maxItems$31_@1)
143 + }
144 + for (
145 + [8] Let mutate i$36_@2[3:33] = 0
146 + ;
147 + [10] Const mutate $39_@2[3:33] = Binary read i$36_@2 < read items$30_@0.length
148 + read $39_@2
149 + ;
150 + [29] Const mutate $56_@2[3:33] = 1
151 + [30] Reassign mutate i$36_@2[3:33] = Binary read i$36_@2 + read $56_@2
152 + read i$36_@2
153 + ) {
154 + [12] Const mutate item$40_@2[3:33] = Call read items$30_@0.at(read i$36_@2)
155 + [13] Const mutate $41_@6 = null
156 + [14] Const mutate $42_@2[3:33] = Binary read item$40_@2 == read $41_@6
157 + [15] Let mutate $43_@2[3:33] = undefined
158 + if (read $42_@2) {
159 + [16] Const mutate $43_@2[3:33] = read $42_@2
160 + } else {
161 + [18] Const mutate $43_@2[3:33] = Call mutate seen$33_@2.has(mutate item$40_@2)
162 + }
163 + if (read $43_@2) {
164 + continue
165 + }
166 + [22] Call mutate seen$33_@2.add(mutate item$40_@2)
167 + [23] Const mutate $49_@7 = "div"
168 + scope @8 [24:25] deps=[read $49_@7] {
169 + [24] Const mutate $50_@8 = JSX <read $49_@7>{freeze item$40_@2}</read $49_@7>
170 + }
171 + [25] Call mutate renderedItems$32_@2.push(read $50_@8)
172 + [26] Const mutate $55_@9 = Binary read renderedItems$32_@2.length >= read max$35_@5
173 + if (read $55_@9) {
174 + break
175 + }
176 + }
177 + }
178 + [33] Const mutate count$66_@11 = read renderedItems$32_@2.length
179 + [34] Const mutate $67_@12 = "div"
180 + [35] Const mutate $68_@13 = "\n "
181 + [36] Const mutate $69_@14 = "h1"
182 + [37] Const mutate $70_@15 = " Items"
183 + scope @16 [38:39] deps=[read $69_@14, freeze count$66_@11, read $70_@15] {
184 + [38] Const mutate $71_@16 = JSX <read $69_@14>{freeze count$66_@11}{read $70_@15}</read $69_@14>
185 + }
186 + [39] Const mutate $72_@17 = "\n "
187 + [40] Const mutate $73_@18 = "\n "
188 + scope @19 [41:42] deps=[read $67_@12, read $68_@13, read $71_@16, read $72_@17, freeze renderedItems$32_@2, read $73_@18] {
189 + [41] Const mutate $74_@19 = JSX <read $67_@12>{read $68_@13}{read $71_@16}{read $72_@17}{freeze renderedItems$32_@2}{read $73_@18}</read $67_@12>
190 + }
191 + return read $74_@19
192 +}
193 +
194 ```
195
196 ### CFG
@@ -101,99 +200,149 @@ flowchart TB
200 %% Basic Blocks
201 subgraph bb0
202 bb0_instrs["
104 - [1] Const mutate items$27_@0 = read props$26.items
105 - [2] Const mutate maxItems$28_@1 = read props$26.maxItems
106 - [3] Const mutate renderedItems$29_@2[3:22] = Array []
107 - [4] Const mutate seen$30_@3[0:19] = New mutate Set$6_@3()
108 - [5] Const mutate $31_@4 = 0
109 - [6] Const mutate max$32_@5[0:7] = Call mutate Math$8_@5.max(read $31_@4, read maxItems$28_@1)
203 + [1] Const mutate items$30_@0 = read props$29.items
204 + [2] Const mutate maxItems$31_@1 = read props$29.maxItems
205 + [3] Const mutate renderedItems$32_@2[3:33] = Array []
206 + [4] Const mutate seen$33_@2[3:33] = New mutate Set$6()
207 + [5] Const mutate $34_@4 = 0
208 + [6] Const mutate max$35_@5 = Call mutate Math$8.max(read $34_@4, read maxItems$31_@1)
209 "]
111 - bb0_instrs --> bb0_terminal(["Goto"])
112 - end
113 - subgraph bb1
114 - bb1_terminal(["If (read items$27_@0)"])
210 + bb0_instrs --> bb0_terminal(["For"])
211 end
212 subgraph bb3
213 bb3_instrs["
118 - [9] Const mutate $34_@6 = null
119 - [10] Const mutate $36_@3[0:19] = Binary read item$10_@3 == read $34_@6
120 - [11] Let mutate $37_@3[0:19] = undefined
214 + [8] Let mutate i$36_@2[3:33] = 0
215 "]
122 - bb3_instrs --> bb3_terminal(["If (read $36_@3)"])
216 + bb3_instrs --> bb3_terminal(["Goto"])
217 end
124 - subgraph bb8
125 - bb8_instrs["
126 - [12] Const mutate $37_@3[0:19] = read $36_@3
218 + subgraph bb1
219 + bb1_instrs["
220 + [10] Const mutate $39_@2[3:33] = Binary read i$36_@2 < read items$30_@0.length
221 "]
128 - bb8_instrs --> bb8_terminal(["Goto"])
222 + bb1_instrs --> bb1_terminal(["If (read $39_@2)"])
223 end
130 - subgraph bb9
131 - bb9_instrs["
132 - [14] Const mutate $37_@3[0:19] = Call mutate seen$30_@3.has(mutate item$10_@3)
224 + subgraph bb5
225 + bb5_instrs["
226 + [12] Const mutate item$40_@2[3:33] = Call read items$30_@0.at(read i$36_@2)
227 + [13] Const mutate $41_@6 = null
228 + [14] Const mutate $42_@2[3:33] = Binary read item$40_@2 == read $41_@6
229 + [15] Let mutate $43_@2[3:33] = undefined
230 + "]
231 + bb5_instrs --> bb5_terminal(["If (read $42_@2)"])
232 + end
233 + subgraph bb10
234 + bb10_instrs["
235 + [16] Const mutate $43_@2[3:33] = read $42_@2
236 "]
134 - bb9_instrs --> bb9_terminal(["Goto"])
237 + bb10_instrs --> bb10_terminal(["Goto"])
238 + end
239 + subgraph bb11
240 + bb11_instrs["
241 + [18] Const mutate $43_@2[3:33] = Call mutate seen$33_@2.has(mutate item$40_@2)
242 + "]
243 + bb11_instrs --> bb11_terminal(["Goto"])
244 + end
245 + subgraph bb9
246 + bb9_terminal(["If (read $43_@2)"])
247 end
248 subgraph bb7
137 - bb7_terminal(["If (read $37_@3)"])
249 + bb7_terminal(["Goto"])
250 end
139 - subgraph bb5
140 - bb5_terminal(["Goto"])
251 + subgraph bb6
252 + bb6_instrs["
253 + [22] Call mutate seen$33_@2.add(mutate item$40_@2)
254 + [23] Const mutate $49_@7 = 'div'
255 + [24] Const mutate $50_@8 = JSX <read $49_@7>{freeze item$40_@2}</read $49_@7>
256 + [25] Call mutate renderedItems$32_@2.push(read $50_@8)
257 + [26] Const mutate $55_@9 = Binary read renderedItems$32_@2.length >= read max$35_@5
258 + "]
259 + bb6_instrs --> bb6_terminal(["If (read $55_@9)"])
260 + end
261 + subgraph bb12
262 + bb12_terminal(["Goto"])
263 end
264 subgraph bb4
265 bb4_instrs["
144 - [18] Call mutate seen$30_@3.add(mutate item$10_@3)
145 - [19] Const mutate $43_@7 = 'div'
146 - [20] Const mutate $44_@8 = JSX <read $43_@7>{read item$10_@3}</read $43_@7>
147 - [21] Call mutate renderedItems$29_@2.push(read $44_@8)
148 - [22] Const mutate $49_@9 = Binary read renderedItems$29_@2.length >= read max$32_@5
266 + [29] Const mutate $56_@2[3:33] = 1
267 + [30] Reassign mutate i$36_@2[3:33] = Binary read i$36_@2 + read $56_@2
268 + [31] read i$36_@2
269 "]
150 - bb4_instrs --> bb4_terminal(["If (read $49_@9)"])
151 - end
152 - subgraph bb10
153 - bb10_terminal(["Goto"])
270 + bb4_instrs --> bb4_terminal(["Goto"])
271 end
272 subgraph bb2
273 bb2_instrs["
157 - [25] Const mutate count$52_@10 = read renderedItems$29_@2.length
158 - [26] Const mutate $53_@11 = 'div'
159 - [27] Const mutate $54_@12 = '\n '
160 - [28] Const mutate $55_@13 = 'h1'
161 - [29] Const mutate $56_@14 = ' Items'
162 - [30] Const mutate $57_@15 = JSX <read $55_@13>{freeze count$52_@10}{read $56_@14}</read $55_@13>
163 - [31] Const mutate $58_@16 = '\n '
164 - [32] Const mutate $59_@17 = '\n '
165 - [33] Const mutate $60_@18 = JSX <read $53_@11>{read $54_@12}{read $57_@15}{read $58_@16}{freeze renderedItems$29_@2}{read $59_@17}</read $53_@11>
274 + [33] Const mutate count$66_@11 = read renderedItems$32_@2.length
275 + [34] Const mutate $67_@12 = 'div'
276 + [35] Const mutate $68_@13 = '\n '
277 + [36] Const mutate $69_@14 = 'h1'
278 + [37] Const mutate $70_@15 = ' Items'
279 + [38] Const mutate $71_@16 = JSX <read $69_@14>{freeze count$66_@11}{read $70_@15}</read $69_@14>
280 + [39] Const mutate $72_@17 = '\n '
281 + [40] Const mutate $73_@18 = '\n '
282 + [41] Const mutate $74_@19 = JSX <read $67_@12>{read $68_@13}{read $71_@16}{read $72_@17}{freeze renderedItems$32_@2}{read $73_@18}</read $67_@12>
283 "]
167 - bb2_instrs --> bb2_terminal(["Return read $60_@18"])
284 + bb2_instrs --> bb2_terminal(["Return read $74_@19"])
285 end
286
287 %% Jumps
171 - bb0_terminal --> bb1
172 - bb1_terminal -- "then" --> bb3
288 + bb0_terminal -- "init" --> bb3
289 + bb0_terminal -- "test" --> bb1
290 + bb0_terminal -- "update" --> bb4
291 + bb0_terminal -- "loop" --> bb5
292 + bb0_terminal -- "fallthrough" --> bb2
293 + bb3_terminal --> bb1
294 + bb1_terminal -- "then" --> bb5
295 bb1_terminal -- "else" --> bb2
174 - bb3_terminal -- "then" --> bb8
175 - bb3_terminal -- "else" --> bb9
176 - bb3_terminal -- "fallthrough" --> bb7
177 - bb8_terminal --> bb7
178 - bb9_terminal --> bb7
179 - bb7_terminal -- "then" --> bb5
180 - bb7_terminal -- "else" --> bb4
181 - bb5_terminal --> bb1
182 - bb4_terminal -- "then" --> bb2
183 - bb4_terminal -- "else" --> bb10
184 - bb10_terminal --> bb1
296 + bb5_terminal -- "then" --> bb10
297 + bb5_terminal -- "else" --> bb11
298 + bb5_terminal -- "fallthrough" --> bb9
299 + bb10_terminal --> bb9
300 + bb11_terminal --> bb9
301 + bb9_terminal -- "then" --> bb7
302 + bb9_terminal -- "else" --> bb6
303 + bb7_terminal --> bb4
304 + bb6_terminal -- "then" --> bb2
305 + bb6_terminal -- "else" --> bb12
306 + bb12_terminal --> bb4
307 + bb4_terminal --> bb1
308
309 ```
310
311 ## Code
312
313 ```javascript
191 -function Component$0(props$26) {
192 - const items$27 = props$26.items;
193 - const maxItems$28 = props$26.maxItems;
194 - const renderedItems$29 = [];
195 - const seen$30 = new Set$6();
196 - const max$32 = Math$8.max(0, maxItems$28);
314 +function Component$0(props$29) {
315 + const items$30 = props$29.items;
316 + const maxItems$31 = props$29.maxItems;
317 + const renderedItems$32 = [];
318 + const seen$33 = new Set$6();
319 + const max$35 = Math$8.max(0, maxItems$31);
320 + bb2: for (let i$36 = 0; i$36 < items$30.length; i$36 = i$36 + 1, i$36) {
321 + const item$40 = items$30.at(i$36);
322 +
323 + bb9: if (item$40 == null) {
324 + } else {
325 + }
326 +
327 + bb6: if (seen$33.has(item$40)) {
328 + continue;
329 + }
330 +
331 + seen$33.add(item$40);
332 + renderedItems$32.push(<div>{item$40}</div>);
333 +
334 + bb12: if (renderedItems$32.length >= max$35) {
335 + break;
336 + }
337 + }
338 +
339 + const count$66 = renderedItems$32.length;
340 + return (
341 + <div>
342 + {<h1>{count$66} Items</h1>}
343 + {renderedItems$32}
344 + </div>
345 + );
346 }
347
348 ```
compiler/forget/src/__tests__/fixtures/hir/component.js
+2 -2
@@ -1,4 +1,3 @@
1 -// @Out DefUseGraph
1 function Component(props) {
2 const items = props.items;
3 const maxItems = props.maxItems;
@@ -6,7 +5,8 @@ function Component(props) {
5 const renderedItems = [];
6 const seen = new Set();
7 const max = Math.max(0, maxItems);
9 - for (const item of items) {
8 + for (let i = 0; i < items.length; i += 1) {
9 + const item = items.at(i);
10 if (item == null || seen.has(item)) {
11 continue;
12 }
compiler/forget/src/__tests__/fixtures/hir/conditional-break.expect.md
+99
@@ -95,6 +95,26 @@ scope0 [1:7]:
95 - dependency: read props$4.d
96 ```
97
98 +## Reactive Scopes
99 +
100 +```
101 +function Component(
102 + props,
103 +) {
104 + scope @0 [1:7] deps=[read props$4.a, read props$4.b, read props$4.d] {
105 + [1] Const mutate a_DEBUG$5_@0[1:7] = Array []
106 + [2] Call mutate a_DEBUG$5_@0.push(read props$4.a)
107 + if (read props$4.b) {
108 + [4] Const mutate $6_@1 = null
109 + return read $6_@1
110 + }
111 + [6] Call mutate a_DEBUG$5_@0.push(read props$4.d)
112 + }
113 + return freeze a_DEBUG$5_@0
114 +}
115 +
116 +```
117 +
118 ### CFG
119
120 ```mermaid
@@ -163,6 +183,25 @@ scope0 [1:7]:
183 - dependency: read props$3.d
184 ```
185
186 +## Reactive Scopes
187 +
188 +```
189 +function Component(
190 + props,
191 +) {
192 + scope @0 [1:7] deps=[read props$3.a, read props$3.c, read props$3.b, read props$3.d] {
193 + [1] Const mutate a$4_@0[1:7] = Array []
194 + [2] Call mutate a$4_@0.push(read props$3.a)
195 + if (read props$3.b) {
196 + [4] Call mutate a$4_@0.push(read props$3.c)
197 + }
198 + [6] Call mutate a$4_@0.push(read props$3.d)
199 + }
200 + return freeze a$4_@0
201 +}
202 +
203 +```
204 +
205 ### CFG
206
207 ```mermaid
@@ -233,6 +272,27 @@ scope0 [1:8]:
272 - dependency: read props$4.d
273 ```
274
275 +## Reactive Scopes
276 +
277 +```
278 +function Component(
279 + props,
280 +) {
281 + scope @0 [1:8] deps=[read props$4.a, read props$4.c, read props$4.b, read props$4.d] {
282 + [1] Const mutate a$5_@0[1:8] = Array []
283 + [2] Call mutate a$5_@0.push(read props$4.a)
284 + if (read props$4.b) {
285 + [4] Call mutate a$5_@0.push(read props$4.c)
286 + [5] Const mutate $6_@1 = null
287 + return read $6_@1
288 + }
289 + [7] Call mutate a$5_@0.push(read props$4.d)
290 + }
291 + return freeze a$5_@0
292 +}
293 +
294 +```
295 +
296 ### CFG
297
298 ```mermaid
@@ -303,6 +363,26 @@ scope0 [1:7]:
363 - dependency: read props$3.d
364 ```
365
366 +## Reactive Scopes
367 +
368 +```
369 +function Component(
370 + props,
371 +) {
372 + scope @0 [1:7] deps=[read props$3.a, read props$3.c, read props$3.b, read props$3.d] {
373 + [1] Const mutate a$4_@0[1:7] = Array []
374 + [2] Call mutate a$4_@0.push(read props$3.a)
375 + if (read props$3.b) {
376 + [4] Call mutate a$4_@0.push(read props$3.c)
377 + return freeze a$4_@0
378 + }
379 + [6] Call mutate a$4_@0.push(read props$3.d)
380 + }
381 + return freeze a$4_@0
382 +}
383 +
384 +```
385 +
386 ### CFG
387
388 ```mermaid
@@ -371,6 +451,25 @@ scope0 [1:7]:
451 - dependency: read props$3.c
452 ```
453
454 +## Reactive Scopes
455 +
456 +```
457 +function Component(
458 + props,
459 +) {
460 + scope @0 [1:7] deps=[read props$3.a, read props$3.d, read props$3.c] {
461 + [1] Const mutate a$4_@0[1:7] = Array []
462 + [2] Call mutate a$4_@0.push(read props$3.a)
463 + if (read props$3.b) {
464 + [6] Call mutate a$4_@0.push(read props$3.d)
465 + return freeze a$4_@0
466 + }
467 + [4] Call mutate a$4_@0.push(read props$3.c)
468 + }
469 +}
470 +
471 +```
472 +
473 ### CFG
474
475 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+75 -6
@@ -58,6 +58,30 @@ scope2 [9:10]:
58 - dependency: freeze b$8_@0
59 ```
60
61 +## Reactive Scopes
62 +
63 +```
64 +function Component(
65 + props,
66 +) {
67 + scope @0 [1:9] deps=[] {
68 + [1] Const mutate a$7_@0[1:9] = Array []
69 + [2] Const mutate b$8_@0[1:9] = Array []
70 + if (read b$8_@0) {
71 + [4] Call mutate a$7_@0.push(read props$6.p0)
72 + }
73 + if (read props$6.p1) {
74 + [7] Call mutate b$8_@0.push(read props$6.p2)
75 + }
76 + }
77 + scope @2 [9:10] deps=[freeze a$7_@0, freeze b$8_@0] {
78 + [9] Const mutate $16_@2 = JSX <read Foo$4 a={freeze a$7_@0} b={freeze b$8_@0} ></read Foo$4>
79 + }
80 + return read $16_@2
81 +}
82 +
83 +```
84 +
85 ### CFG
86
87 ```mermaid
@@ -124,9 +148,9 @@ function Component$0(props$6) {
148
149 ```
150 bb0:
127 - [1] Const mutate a$9_@0[0:10] = Array []
128 - [2] Const mutate b$10_@0[0:10] = Array []
129 - [3] Const mutate $11_@0[0:10] = Call mutate mayMutate$4_@0(mutate b$10_@0)
151 + [1] Const mutate a$9_@0[1:10] = Array []
152 + [2] Const mutate b$10_@0[1:10] = Array []
153 + [3] Const mutate $11_@0[1:10] = Call mutate mayMutate$4(mutate b$10_@0)
154 [4] If (read $11_@0) then:bb2 else:bb1 fallthrough=bb1
155 bb2:
156 predecessor blocks: bb0
@@ -148,6 +172,31 @@ scope2 [10:11]:
172 - dependency: freeze b$10_@0
173 ```
174
175 +## Reactive Scopes
176 +
177 +```
178 +function Component(
179 + props,
180 +) {
181 + scope @0 [1:10] deps=[] {
182 + [1] Const mutate a$9_@0[1:10] = Array []
183 + [2] Const mutate b$10_@0[1:10] = Array []
184 + [3] Const mutate $11_@0[1:10] = Call mutate mayMutate$4(mutate b$10_@0)
185 + if (read $11_@0) {
186 + [5] Call mutate a$9_@0.push(read props$8.p0)
187 + }
188 + if (read props$8.p1) {
189 + [8] Call mutate b$10_@0.push(read props$8.p2)
190 + }
191 + }
192 + scope @2 [10:11] deps=[freeze a$9_@0, freeze b$10_@0] {
193 + [10] Const mutate $19_@2 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
194 + }
195 + return read $19_@2
196 +}
197 +
198 +```
199 +
200 ### CFG
201
202 ```mermaid
@@ -155,9 +204,9 @@ flowchart TB
204 %% Basic Blocks
205 subgraph bb0
206 bb0_instrs["
158 - [1] Const mutate a$9_@0[0:10] = Array []
159 - [2] Const mutate b$10_@0[0:10] = Array []
160 - [3] Const mutate $11_@0[0:10] = Call mutate mayMutate$4_@0(mutate b$10_@0)
207 + [1] Const mutate a$9_@0[1:10] = Array []
208 + [2] Const mutate b$10_@0[1:10] = Array []
209 + [3] Const mutate $11_@0[1:10] = Call mutate mayMutate$4(mutate b$10_@0)
210 "]
211 bb0_instrs --> bb0_terminal(["If (read $11_@0)"])
212 end
@@ -219,6 +268,16 @@ bb0:
268
269 ```
270
271 +## Reactive Scopes
272 +
273 +```
274 +function Foo(
275 +) {
276 + return
277 +}
278 +
279 +```
280 +
281 ### CFG
282
283 ```mermaid
@@ -246,6 +305,16 @@ bb0:
305
306 ```
307
308 +## Reactive Scopes
309 +
310 +```
311 +function mayMutate(
312 +) {
313 + return
314 +}
315 +
316 +```
317 +
318 ### CFG
319
320 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md
+43 -8
@@ -23,6 +23,16 @@ bb0:
23
24 ```
25
26 +## Reactive Scopes
27 +
28 +```
29 +function Foo(
30 +) {
31 + return
32 +}
33 +
34 +```
35 +
36 ### CFG
37
38 ```mermaid
@@ -46,12 +56,12 @@ function Foo$0() {}
56
57 ```
58 bb0:
49 - [1] Const mutate a$10_@0[0:7] = Array []
50 - [2] Const mutate b$11_@0[0:7] = Object { }
51 - [3] New mutate Foo$4_@0(mutate a$10_@0, mutate b$11_@0)
59 + [1] Const mutate a$10_@0[1:7] = Array []
60 + [2] Const mutate b$11_@0[1:7] = Object { }
61 + [3] New mutate Foo$4(mutate a$10_@0, mutate b$11_@0)
62 [4] Const mutate $12_@1 = "div"
63 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
54 - [6] New mutate Foo$4_@0(mutate b$11_@0)
64 + [6] New mutate Foo$4(mutate b$11_@0)
65 [7] Const mutate $14_@3 = "div"
66 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
67 [9] Return read $15_@4
@@ -63,6 +73,31 @@ scope4 [8:9]:
73 - dependency: freeze b$11_@0
74 ```
75
76 +## Reactive Scopes
77 +
78 +```
79 +function Component(
80 + props,
81 +) {
82 + scope @0 [1:7] deps=[] {
83 + [1] Const mutate a$10_@0[1:7] = Array []
84 + [2] Const mutate b$11_@0[1:7] = Object { }
85 + [3] New mutate Foo$4(mutate a$10_@0, mutate b$11_@0)
86 + [4] Const mutate $12_@1 = "div"
87 + scope @2 [5:6] deps=[read $12_@1] {
88 + [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
89 + }
90 + [6] New mutate Foo$4(mutate b$11_@0)
91 + }
92 + [7] Const mutate $14_@3 = "div"
93 + scope @4 [8:9] deps=[read $14_@3, read a$10_@0, freeze b$11_@0] {
94 + [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
95 + }
96 + return read $15_@4
97 +}
98 +
99 +```
100 +
101 ### CFG
102
103 ```mermaid
@@ -70,12 +105,12 @@ flowchart TB
105 %% Basic Blocks
106 subgraph bb0
107 bb0_instrs["
73 - [1] Const mutate a$10_@0[0:7] = Array []
74 - [2] Const mutate b$11_@0[0:7] = Object { }
75 - [3] New mutate Foo$4_@0(mutate a$10_@0, mutate b$11_@0)
108 + [1] Const mutate a$10_@0[1:7] = Array []
109 + [2] Const mutate b$11_@0[1:7] = Object { }
110 + [3] New mutate Foo$4(mutate a$10_@0, mutate b$11_@0)
111 [4] Const mutate $12_@1 = 'div'
112 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
78 - [6] New mutate Foo$4_@0(mutate b$11_@0)
113 + [6] New mutate Foo$4(mutate b$11_@0)
114 [7] Const mutate $14_@3 = 'div'
115 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
116 "]
compiler/forget/src/__tests__/fixtures/hir/dependencies-outputs.expect.md
+27
@@ -53,6 +53,33 @@ scope2 [5:12]:
53 - dependency: read b$7
54 ```
55
56 +## Reactive Scopes
57 +
58 +```
59 +function foo(
60 + a,
61 + b,
62 +) {
63 + scope @0 [1:3] deps=[read a$6] {
64 + [1] Const mutate x$8_@0[1:3] = Array []
65 + [2] Call mutate x$8_@0.push(read a$6)
66 + }
67 + [3] Const mutate $9_@1 = "div"
68 + [4] JSX <read $9_@1>{freeze x$8_@0}</read $9_@1>
69 + scope @2 [5:12] deps=[read x$8_@0, read x$8_@0.length, read b$7, read b$7] {
70 + [5] Const mutate y$10_@2[5:12] = Array []
71 + if (read x$8_@0.length) {
72 + [7] Call mutate y$10_@2.push(read x$8_@0)
73 + }
74 + if (read b$7) {
75 + [10] Call mutate y$10_@2.push(read b$7)
76 + }
77 + }
78 + return
79 +}
80 +
81 +```
82 +
83 ### CFG
84
85 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/dependencies.expect.md
+26
@@ -52,6 +52,32 @@ scope1 [3:7]:
52 - dependency: read x$6
53 ```
54
55 +## Reactive Scopes
56 +
57 +```
58 +function foo(
59 + x,
60 + y,
61 + z,
62 +) {
63 + scope @0 [1:10] deps=[read z$8, read x$6, read x$6, read y$7] {
64 + [1] Const mutate items$9_@0[1:10] = Array [read z$8]
65 + [2] Call mutate items$9_@0.push(read x$6)
66 + scope @1 [3:7] deps=[read y$7, read x$6] {
67 + [3] Const mutate items2$10_@1[3:7] = Array []
68 + if (read x$6) {
69 + [5] Call mutate items2$10_@1.push(read y$7)
70 + }
71 + }
72 + if (read y$7) {
73 + [8] Call mutate items$9_@0.push(read x$6)
74 + }
75 + }
76 + return freeze items2$10_@1
77 +}
78 +
79 +```
80 +
81 ### CFG
82
83 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/extend-scopes-if.expect.md
+28
@@ -52,6 +52,34 @@ scope0 [1:8]:
52 - dependency: read a$7
53 ```
54
55 +## Reactive Scopes
56 +
57 +```
58 +function foo(
59 + a,
60 + b,
61 + c,
62 +) {
63 + scope @0 [1:8] deps=[read c$9, read b$8, read a$7] {
64 + [1] Const mutate x$10_@0[1:8] = Array []
65 + if (read a$7) {
66 + if (read b$8) {
67 + if (read c$9) {
68 + [5] Const mutate $11_@1 = 0
69 + [6] Call mutate x$10_@0.push(read $11_@1)
70 + }
71 + }
72 + }
73 + }
74 + if (read a$7.length) {
75 + return read a$7
76 + }
77 + [10] Const mutate $13_@2 = null
78 + return read $13_@2
79 +}
80 +
81 +```
82 +
83 ### CFG
84
85 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md
+39 -2
@@ -21,13 +21,29 @@ bb0:
21 [1] Const mutate a$5_@0 = Array []
22 [2] Const mutate b$6_@1 = read a$5_@0
23 [3] Call read useFreeze$3(freeze a$5_@0)
24 - [4] Call mutate foo$4_@2(read b$6_@1)
24 + [4] Call mutate foo$4(read b$6_@1)
25 [5] Return
26 scope1 [2:3]:
27 - dependency: read a$5_@0
28 - dependency: freeze a$5_@0
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function Component(
35 +) {
36 + scope @0 [1:2] deps=[] {
37 + [1] Const mutate a$5_@0 = Array []
38 + }
39 + [2] Const mutate b$6_@1 = read a$5_@0
40 + [3] Call read useFreeze$3(freeze a$5_@0)
41 + [4] Call mutate foo$4(read b$6_@1)
42 + return
43 +}
44 +
45 +```
46 +
47 ### CFG
48
49 ```mermaid
@@ -38,7 +54,7 @@ flowchart TB
54 [1] Const mutate a$5_@0 = Array []
55 [2] Const mutate b$6_@1 = read a$5_@0
56 [3] Call read useFreeze$3(freeze a$5_@0)
41 - [4] Call mutate foo$4_@2(read b$6_@1)
57 + [4] Call mutate foo$4(read b$6_@1)
58 "]
59 bb0_instrs --> bb0_terminal(["Return"])
60 end
@@ -66,6 +82,16 @@ bb0:
82
83 ```
84
85 +## Reactive Scopes
86 +
87 +```
88 +function useFreeze(
89 +) {
90 + return
91 +}
92 +
93 +```
94 +
95 ### CFG
96
97 ```mermaid
@@ -93,6 +119,17 @@ bb0:
119
120 ```
121
122 +## Reactive Scopes
123 +
124 +```
125 +function foo(
126 + x,
127 +) {
128 + return
129 +}
130 +
131 +```
132 +
133 ### CFG
134
135 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md
+61 -16
@@ -27,6 +27,16 @@ bb0:
27
28 ```
29
30 +## Reactive Scopes
31 +
32 +```
33 +function useFreeze(
34 +) {
35 + return
36 +}
37 +
38 +```
39 +
40 ### CFG
41
42 ```mermaid
@@ -54,6 +64,16 @@ bb0:
64
65 ```
66
67 +## Reactive Scopes
68 +
69 +```
70 +function foo(
71 +) {
72 + return
73 +}
74 +
75 +```
76 +
77 ### CFG
78
79 ```mermaid
@@ -79,21 +99,46 @@ function foo$0() {}
99 bb0:
100 [1] Const mutate x$11_@0 = Array []
101 [2] Const mutate y$12_@1 = Call read useFreeze$4(freeze x$11_@0)
82 - [3] Call mutate foo$5_@2(read y$12_@1, read x$11_@0)
83 - [4] Const mutate $13_@3 = "\n "
84 - [5] Const mutate $14_@4 = "\n "
85 - [6] Const mutate $15_@5 = "\n "
86 - [7] Const mutate $16_@6 = JSX <read Component$0>{read $13_@3}{read x$11_@0}{read $14_@4}{read y$12_@1}{read $15_@5}</read Component$0>
87 - [8] Return read $16_@6
102 + [3] Call mutate foo$5(read y$12_@1, read x$11_@0)
103 + [4] Const mutate $13_@2 = "\n "
104 + [5] Const mutate $14_@3 = "\n "
105 + [6] Const mutate $15_@4 = "\n "
106 + [7] Const mutate $16_@5 = JSX <read Component$0>{read $13_@2}{read x$11_@0}{read $14_@3}{read y$12_@1}{read $15_@4}</read Component$0>
107 + [8] Return read $16_@5
108 scope1 [2:3]:
109 - dependency: freeze x$11_@0
90 -scope6 [7:8]:
110 + - dependency: read x$11_@0
111 +scope5 [7:8]:
112 - dependency: read Component$0
92 - - dependency: read $13_@3
113 + - dependency: read $13_@2
114 - dependency: read x$11_@0
94 - - dependency: read $14_@4
115 + - dependency: read $14_@3
116 - dependency: read y$12_@1
96 - - dependency: read $15_@5
117 + - dependency: read $15_@4
118 +```
119 +
120 +## Reactive Scopes
121 +
122 +```
123 +function Component(
124 + props,
125 +) {
126 + scope @0 [1:2] deps=[] {
127 + [1] Const mutate x$11_@0 = Array []
128 + }
129 + scope @1 [2:3] deps=[freeze x$11_@0, read x$11_@0] {
130 + [2] Const mutate y$12_@1 = Call read useFreeze$4(freeze x$11_@0)
131 + }
132 + [3] Call mutate foo$5(read y$12_@1, read x$11_@0)
133 + [4] Const mutate $13_@2 = "\n "
134 + [5] Const mutate $14_@3 = "\n "
135 + [6] Const mutate $15_@4 = "\n "
136 + scope @5 [7:8] deps=[read Component$0, read $13_@2, read x$11_@0, read $14_@3, read y$12_@1, read $15_@4] {
137 + [7] Const mutate $16_@5 = JSX <read Component$0>{read $13_@2}{read x$11_@0}{read $14_@3}{read y$12_@1}{read $15_@4}</read Component$0>
138 + }
139 + return read $16_@5
140 +}
141 +
142 ```
143
144 ### CFG
@@ -105,13 +150,13 @@ flowchart TB
150 bb0_instrs["
151 [1] Const mutate x$11_@0 = Array []
152 [2] Const mutate y$12_@1 = Call read useFreeze$4(freeze x$11_@0)
108 - [3] Call mutate foo$5_@2(read y$12_@1, read x$11_@0)
109 - [4] Const mutate $13_@3 = '\n '
110 - [5] Const mutate $14_@4 = '\n '
111 - [6] Const mutate $15_@5 = '\n '
112 - [7] Const mutate $16_@6 = JSX <read Component$0>{read $13_@3}{read x$11_@0}{read $14_@4}{read y$12_@1}{read $15_@5}</read Component$0>
153 + [3] Call mutate foo$5(read y$12_@1, read x$11_@0)
154 + [4] Const mutate $13_@2 = '\n '
155 + [5] Const mutate $14_@3 = '\n '
156 + [6] Const mutate $15_@4 = '\n '
157 + [7] Const mutate $16_@5 = JSX <read Component$0>{read $13_@2}{read x$11_@0}{read $14_@3}{read y$12_@1}{read $15_@4}</read Component$0>
158 "]
114 - bb0_instrs --> bb0_terminal(["Return read $16_@6"])
159 + bb0_instrs --> bb0_terminal(["Return read $16_@5"])
160 end
161
162 %% Jumps
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md
+40 -2
@@ -22,11 +22,27 @@ bb0:
22 [1] Const mutate a$4_@0 = Array []
23 [2] Call read useFreeze$2(freeze a$4_@0)
24 [3] Call read useFreeze$2(read a$4_@0)
25 - [4] Call mutate call$3_@1(read a$4_@0)
25 + [4] Call mutate call$3(read a$4_@0)
26 [5] Return read a$4_@0
27
28 ```
29
30 +## Reactive Scopes
31 +
32 +```
33 +function Component(
34 +) {
35 + scope @0 [1:2] deps=[] {
36 + [1] Const mutate a$4_@0 = Array []
37 + }
38 + [2] Call read useFreeze$2(freeze a$4_@0)
39 + [3] Call read useFreeze$2(read a$4_@0)
40 + [4] Call mutate call$3(read a$4_@0)
41 + return read a$4_@0
42 +}
43 +
44 +```
45 +
46 ### CFG
47
48 ```mermaid
@@ -37,7 +53,7 @@ flowchart TB
53 [1] Const mutate a$4_@0 = Array []
54 [2] Call read useFreeze$2(freeze a$4_@0)
55 [3] Call read useFreeze$2(read a$4_@0)
40 - [4] Call mutate call$3_@1(read a$4_@0)
56 + [4] Call mutate call$3(read a$4_@0)
57 "]
58 bb0_instrs --> bb0_terminal(["Return read a$4_@0"])
59 end
@@ -66,6 +82,17 @@ bb0:
82
83 ```
84
85 +## Reactive Scopes
86 +
87 +```
88 +function useFreeze(
89 + x,
90 +) {
91 + return
92 +}
93 +
94 +```
95 +
96 ### CFG
97
98 ```mermaid
@@ -93,6 +120,17 @@ bb0:
120
121 ```
122
123 +## Reactive Scopes
124 +
125 +```
126 +function call(
127 + x,
128 +) {
129 + return
130 +}
131 +
132 +```
133 +
134 ### CFG
135
136 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+49 -2
@@ -43,7 +43,7 @@ bb1:
43 predecessor blocks: bb2 bb3
44 [9] Call read useFreeze$5(freeze a$11_@3)
45 [10] Call read useFreeze$5(read a$11_@3)
46 - [11] Call mutate call$6_@4(read a$11_@3)
46 + [11] Call mutate call$6(read a$11_@3)
47 [12] Return read a$11_@3
48 scope0 [1:2]:
49 - dependency: read props$7.cond
@@ -54,6 +54,31 @@ scope3 [4:9]:
54 - dependency: read cond$8_@0
55 ```
56
57 +## Reactive Scopes
58 +
59 +```
60 +function Component(
61 + props,
62 +) {
63 + [1] Const mutate cond$8_@0 = read props$7.cond
64 + [2] Const mutate x$9_@1 = read props$7.x
65 + [3] Const mutate a$10_@2 = undefined
66 + scope @3 [4:9] deps=[read x$9_@1, read cond$8_@0] {
67 + [4] Let mutate a$11_@3[4:9] = undefined
68 + if (read cond$8_@0) {
69 + [5] Reassign mutate a$11_@3[4:9] = read x$9_@1
70 + } else {
71 + [7] Reassign mutate a$11_@3[4:9] = Array []
72 + }
73 + }
74 + [9] Call read useFreeze$5(freeze a$11_@3)
75 + [10] Call read useFreeze$5(read a$11_@3)
76 + [11] Call mutate call$6(read a$11_@3)
77 + return read a$11_@3
78 +}
79 +
80 +```
81 +
82 ### CFG
83
84 ```mermaid
@@ -84,7 +109,7 @@ flowchart TB
109 bb1_instrs["
110 [9] Call read useFreeze$5(freeze a$11_@3)
111 [10] Call read useFreeze$5(read a$11_@3)
87 - [11] Call mutate call$6_@4(read a$11_@3)
112 + [11] Call mutate call$6(read a$11_@3)
113 "]
114 bb1_instrs --> bb1_terminal(["Return read a$11_@3"])
115 end
@@ -127,6 +152,17 @@ bb0:
152
153 ```
154
155 +## Reactive Scopes
156 +
157 +```
158 +function useFreeze(
159 + x,
160 +) {
161 + return
162 +}
163 +
164 +```
165 +
166 ### CFG
167
168 ```mermaid
@@ -154,6 +190,17 @@ bb0:
190
191 ```
192
193 +## Reactive Scopes
194 +
195 +```
196 +function call(
197 + x,
198 +) {
199 + return
200 +}
201 +
202 +```
203 +
204 ### CFG
205
206 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+79 -15
@@ -41,6 +41,16 @@ bb0:
41
42 ```
43
44 +## Reactive Scopes
45 +
46 +```
47 +function compute(
48 +) {
49 + return
50 +}
51 +
52 +```
53 +
54 ### CFG
55
56 ```mermaid
@@ -68,6 +78,16 @@ bb0:
78
79 ```
80
81 +## Reactive Scopes
82 +
83 +```
84 +function mutate(
85 +) {
86 + return
87 +}
88 +
89 +```
90 +
91 ### CFG
92
93 ```mermaid
@@ -95,6 +115,16 @@ bb0:
115
116 ```
117
118 +## Reactive Scopes
119 +
120 +```
121 +function foo(
122 +) {
123 + return
124 +}
125 +
126 +```
127 +
128 ### CFG
129
130 ```mermaid
@@ -122,6 +152,16 @@ bb0:
152
153 ```
154
155 +## Reactive Scopes
156 +
157 +```
158 +function Foo(
159 +) {
160 + return
161 +}
162 +
163 +```
164 +
165 ### CFG
166
167 ```mermaid
@@ -145,21 +185,45 @@ function Foo$0() {}
185
186 ```
187 bb0:
148 - [1] Const mutate a$9_@0[0:7] = Call mutate compute$3_@0(read props$8.a)
149 - [2] Const mutate b$10_@0[0:7] = Call mutate compute$3_@0(read props$8.b)
188 + [1] Const mutate a$9_@1[1:7] = Call mutate compute$3(read props$8.a)
189 + [2] Const mutate b$10_@1[1:7] = Call mutate compute$3(read props$8.b)
190 [3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
191 bb2:
192 predecessor blocks: bb0
153 - [4] Call mutate mutate$5_@0(mutate a$9_@0)
154 - [5] Call mutate mutate$5_@0(mutate b$10_@0)
193 + [4] Call mutate mutate$5(mutate a$9_@1)
194 + [5] Call mutate mutate$5(mutate b$10_@1)
195 [6] Goto bb1
196 bb1:
197 predecessor blocks: bb2 bb0
158 - [7] Const mutate $14_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
159 - [8] Return read $14_@1
160 -scope1 [7:8]:
161 - - dependency: freeze a$9_@0
162 - - dependency: freeze b$10_@0
198 + [7] Const mutate $14_@2 = JSX <read Foo$6 a={freeze a$9_@1} b={freeze b$10_@1} ></read Foo$6>
199 + [8] Return read $14_@2
200 +scope1 [1:7]:
201 + - dependency: read props$8.a
202 +scope2 [7:8]:
203 + - dependency: freeze a$9_@1
204 + - dependency: freeze b$10_@1
205 +```
206 +
207 +## Reactive Scopes
208 +
209 +```
210 +function Component(
211 + props,
212 +) {
213 + scope @1 [1:7] deps=[read props$8.a] {
214 + [1] Const mutate a$9_@1[1:7] = Call mutate compute$3(read props$8.a)
215 + [2] Const mutate b$10_@1[1:7] = Call mutate compute$3(read props$8.b)
216 + if (read props$8.c) {
217 + [4] Call mutate mutate$5(mutate a$9_@1)
218 + [5] Call mutate mutate$5(mutate b$10_@1)
219 + }
220 + }
221 + scope @2 [7:8] deps=[freeze a$9_@1, freeze b$10_@1] {
222 + [7] Const mutate $14_@2 = JSX <read Foo$6 a={freeze a$9_@1} b={freeze b$10_@1} ></read Foo$6>
223 + }
224 + return read $14_@2
225 +}
226 +
227 ```
228
229 ### CFG
@@ -169,23 +233,23 @@ flowchart TB
233 %% Basic Blocks
234 subgraph bb0
235 bb0_instrs["
172 - [1] Const mutate a$9_@0[0:7] = Call mutate compute$3_@0(read props$8.a)
173 - [2] Const mutate b$10_@0[0:7] = Call mutate compute$3_@0(read props$8.b)
236 + [1] Const mutate a$9_@1[1:7] = Call mutate compute$3(read props$8.a)
237 + [2] Const mutate b$10_@1[1:7] = Call mutate compute$3(read props$8.b)
238 "]
239 bb0_instrs --> bb0_terminal(["If (read props$8.c)"])
240 end
241 subgraph bb2
242 bb2_instrs["
179 - [4] Call mutate mutate$5_@0(mutate a$9_@0)
180 - [5] Call mutate mutate$5_@0(mutate b$10_@0)
243 + [4] Call mutate mutate$5(mutate a$9_@1)
244 + [5] Call mutate mutate$5(mutate b$10_@1)
245 "]
246 bb2_instrs --> bb2_terminal(["Goto"])
247 end
248 subgraph bb1
249 bb1_instrs["
186 - [7] Const mutate $14_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
250 + [7] Const mutate $14_@2 = JSX <read Foo$6 a={freeze a$9_@1} b={freeze b$10_@1} ></read Foo$6>
251 "]
188 - bb1_instrs --> bb1_terminal(["Return read $14_@1"])
252 + bb1_instrs --> bb1_terminal(["Return read $14_@2"])
253 end
254
255 %% Jumps
compiler/forget/src/__tests__/fixtures/hir/independent.expect.md
+64 -10
@@ -28,13 +28,37 @@ function Foo() {}
28
29 ```
30 bb0:
31 - [1] Const mutate a$8_@0[0:3] = Call mutate compute$3_@0(read props$7.a)
32 - [2] Const mutate b$9_@0[0:3] = Call mutate compute$3_@0(read props$7.b)
33 - [3] Const mutate $10_@1 = JSX <read Foo$5 a={freeze a$8_@0} b={freeze b$9_@0} ></read Foo$5>
34 - [4] Return read $10_@1
35 -scope1 [3:4]:
31 + [1] Const mutate a$8_@0 = Call mutate compute$3(read props$7.a)
32 + [2] Const mutate b$9_@1 = Call mutate compute$3(read props$7.b)
33 + [3] Const mutate $10_@2 = JSX <read Foo$5 a={freeze a$8_@0} b={freeze b$9_@1} ></read Foo$5>
34 + [4] Return read $10_@2
35 +scope0 [1:2]:
36 + - dependency: read props$7.a
37 +scope1 [2:3]:
38 + - dependency: read props$7.b
39 +scope2 [3:4]:
40 - dependency: freeze a$8_@0
37 - - dependency: freeze b$9_@0
41 + - dependency: freeze b$9_@1
42 +```
43 +
44 +## Reactive Scopes
45 +
46 +```
47 +function Component(
48 + props,
49 +) {
50 + scope @0 [1:2] deps=[read props$7.a] {
51 + [1] Const mutate a$8_@0 = Call mutate compute$3(read props$7.a)
52 + }
53 + scope @1 [2:3] deps=[read props$7.b] {
54 + [2] Const mutate b$9_@1 = Call mutate compute$3(read props$7.b)
55 + }
56 + scope @2 [3:4] deps=[freeze a$8_@0, freeze b$9_@1] {
57 + [3] Const mutate $10_@2 = JSX <read Foo$5 a={freeze a$8_@0} b={freeze b$9_@1} ></read Foo$5>
58 + }
59 + return read $10_@2
60 +}
61 +
62 ```
63
64 ### CFG
@@ -44,11 +68,11 @@ flowchart TB
68 %% Basic Blocks
69 subgraph bb0
70 bb0_instrs["
47 - [1] Const mutate a$8_@0[0:3] = Call mutate compute$3_@0(read props$7.a)
48 - [2] Const mutate b$9_@0[0:3] = Call mutate compute$3_@0(read props$7.b)
49 - [3] Const mutate $10_@1 = JSX <read Foo$5 a={freeze a$8_@0} b={freeze b$9_@0} ></read Foo$5>
71 + [1] Const mutate a$8_@0 = Call mutate compute$3(read props$7.a)
72 + [2] Const mutate b$9_@1 = Call mutate compute$3(read props$7.b)
73 + [3] Const mutate $10_@2 = JSX <read Foo$5 a={freeze a$8_@0} b={freeze b$9_@1} ></read Foo$5>
74 "]
51 - bb0_instrs --> bb0_terminal(["Return read $10_@1"])
75 + bb0_instrs --> bb0_terminal(["Return read $10_@2"])
76 end
77
78 %% Jumps
@@ -73,6 +97,16 @@ bb0:
97
98 ```
99
100 +## Reactive Scopes
101 +
102 +```
103 +function compute(
104 +) {
105 + return
106 +}
107 +
108 +```
109 +
110 ### CFG
111
112 ```mermaid
@@ -100,6 +134,16 @@ bb0:
134
135 ```
136
137 +## Reactive Scopes
138 +
139 +```
140 +function foo(
141 +) {
142 + return
143 +}
144 +
145 +```
146 +
147 ### CFG
148
149 ```mermaid
@@ -127,6 +171,16 @@ bb0:
171
172 ```
173
174 +## Reactive Scopes
175 +
176 +```
177 +function Foo(
178 +) {
179 + return
180 +}
181 +
182 +```
183 +
184 ### CFG
185
186 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+61 -6
@@ -35,6 +35,16 @@ bb0:
35
36 ```
37
38 +## Reactive Scopes
39 +
40 +```
41 +function compute(
42 +) {
43 + return
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
@@ -62,6 +72,16 @@ bb0:
72
73 ```
74
75 +## Reactive Scopes
76 +
77 +```
78 +function foo(
79 +) {
80 + return
81 +}
82 +
83 +```
84 +
85 ### CFG
86
87 ```mermaid
@@ -89,6 +109,16 @@ bb0:
109
110 ```
111
112 +## Reactive Scopes
113 +
114 +```
115 +function Foo(
116 +) {
117 + return
118 +}
119 +
120 +```
121 +
122 ### CFG
123
124 ```mermaid
@@ -112,22 +142,47 @@ function Foo$0() {}
142
143 ```
144 bb0:
115 - [1] Const mutate a$9_@0[0:6] = Call mutate compute$3_@0(read props$8.a)
116 - [2] Const mutate b$10_@0[0:6] = Call mutate compute$3_@0(read props$8.b)
145 + [1] Const mutate a$9_@0[1:6] = Call mutate compute$3(read props$8.a)
146 + [2] Const mutate b$10_@0[1:6] = Call mutate compute$3(read props$8.b)
147 [3] If (read props$8.c) then:bb2 else:bb1 fallthrough=bb1
148 bb2:
149 predecessor blocks: bb0
120 - [4] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
150 + [4] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
151 [5] Goto bb1
152 bb1:
153 predecessor blocks: bb2 bb0
154 [6] Const mutate $14_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
155 [7] Return read $14_@1
156 +scope0 [1:6]:
157 + - dependency: read props$8.a
158 + - dependency: read props$8.b
159 + - dependency: read props$8.c
160 scope1 [6:7]:
161 - dependency: freeze a$9_@0
162 - dependency: freeze b$10_@0
163 ```
164
165 +## Reactive Scopes
166 +
167 +```
168 +function Component(
169 + props,
170 +) {
171 + scope @0 [1:6] deps=[read props$8.a, read props$8.b, read props$8.c] {
172 + [1] Const mutate a$9_@0[1:6] = Call mutate compute$3(read props$8.a)
173 + [2] Const mutate b$10_@0[1:6] = Call mutate compute$3(read props$8.b)
174 + if (read props$8.c) {
175 + [4] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
176 + }
177 + }
178 + scope @1 [6:7] deps=[freeze a$9_@0, freeze b$10_@0] {
179 + [6] Const mutate $14_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
180 + }
181 + return read $14_@1
182 +}
183 +
184 +```
185 +
186 ### CFG
187
188 ```mermaid
@@ -135,14 +190,14 @@ flowchart TB
190 %% Basic Blocks
191 subgraph bb0
192 bb0_instrs["
138 - [1] Const mutate a$9_@0[0:6] = Call mutate compute$3_@0(read props$8.a)
139 - [2] Const mutate b$10_@0[0:6] = Call mutate compute$3_@0(read props$8.b)
193 + [1] Const mutate a$9_@0[1:6] = Call mutate compute$3(read props$8.a)
194 + [2] Const mutate b$10_@0[1:6] = Call mutate compute$3(read props$8.b)
195 "]
196 bb0_instrs --> bb0_terminal(["If (read props$8.c)"])
197 end
198 subgraph bb2
199 bb2_instrs["
145 - [4] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
200 + [4] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
201 "]
202 bb2_instrs --> bb2_terminal(["Goto"])
203 end
compiler/forget/src/__tests__/fixtures/hir/interdependent.expect.md
+58 -6
@@ -28,16 +28,38 @@ function Foo() {}
28
29 ```
30 bb0:
31 - [1] Const mutate a$9_@0[0:4] = Call mutate compute$3_@0(read props$8.a)
32 - [2] Const mutate b$10_@0[0:4] = Call mutate compute$3_@0(read props$8.b)
33 - [3] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
31 + [1] Const mutate a$9_@0[1:4] = Call mutate compute$3(read props$8.a)
32 + [2] Const mutate b$10_@0[1:4] = Call mutate compute$3(read props$8.b)
33 + [3] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
34 [4] Const mutate $11_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
35 [5] Return read $11_@1
36 +scope0 [1:4]:
37 + - dependency: read props$8.a
38 + - dependency: read props$8.b
39 scope1 [4:5]:
40 - dependency: freeze a$9_@0
41 - dependency: freeze b$10_@0
42 ```
43
44 +## Reactive Scopes
45 +
46 +```
47 +function Component(
48 + props,
49 +) {
50 + scope @0 [1:4] deps=[read props$8.a, read props$8.b] {
51 + [1] Const mutate a$9_@0[1:4] = Call mutate compute$3(read props$8.a)
52 + [2] Const mutate b$10_@0[1:4] = Call mutate compute$3(read props$8.b)
53 + [3] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
54 + }
55 + scope @1 [4:5] deps=[freeze a$9_@0, freeze b$10_@0] {
56 + [4] Const mutate $11_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
57 + }
58 + return read $11_@1
59 +}
60 +
61 +```
62 +
63 ### CFG
64
65 ```mermaid
@@ -45,9 +67,9 @@ flowchart TB
67 %% Basic Blocks
68 subgraph bb0
69 bb0_instrs["
48 - [1] Const mutate a$9_@0[0:4] = Call mutate compute$3_@0(read props$8.a)
49 - [2] Const mutate b$10_@0[0:4] = Call mutate compute$3_@0(read props$8.b)
50 - [3] Call mutate foo$5_@0(mutate a$9_@0, mutate b$10_@0)
70 + [1] Const mutate a$9_@0[1:4] = Call mutate compute$3(read props$8.a)
71 + [2] Const mutate b$10_@0[1:4] = Call mutate compute$3(read props$8.b)
72 + [3] Call mutate foo$5(mutate a$9_@0, mutate b$10_@0)
73 [4] Const mutate $11_@1 = JSX <read Foo$6 a={freeze a$9_@0} b={freeze b$10_@0} ></read Foo$6>
74 "]
75 bb0_instrs --> bb0_terminal(["Return read $11_@1"])
@@ -76,6 +98,16 @@ bb0:
98
99 ```
100
101 +## Reactive Scopes
102 +
103 +```
104 +function compute(
105 +) {
106 + return
107 +}
108 +
109 +```
110 +
111 ### CFG
112
113 ```mermaid
@@ -103,6 +135,16 @@ bb0:
135
136 ```
137
138 +## Reactive Scopes
139 +
140 +```
141 +function foo(
142 +) {
143 + return
144 +}
145 +
146 +```
147 +
148 ### CFG
149
150 ```mermaid
@@ -130,6 +172,16 @@ bb0:
172
173 ```
174
175 +## Reactive Scopes
176 +
177 +```
178 +function Foo(
179 +) {
180 + return
181 +}
182 +
183 +```
184 +
185 ### CFG
186
187 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/inverted-if.expect.md
+21
@@ -36,6 +36,27 @@ scope0 [1:6]:
36 - dependency: read a$5
37 ```
38
39 +## Reactive Scopes
40 +
41 +```
42 +function foo(
43 + a,
44 + b,
45 + c,
46 +) {
47 + scope @0 [1:6] deps=[read c$7, read b$6, read a$5] {
48 + [1] Const mutate y$8_@0[1:6] = Array []
49 + if (read a$5) {
50 + if (read b$6) {
51 + [4] Call mutate y$8_@0.push(read c$7)
52 + }
53 + }
54 + }
55 + return
56 +}
57 +
58 +```
59 +
60 ### CFG
61
62 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/issue852.expect.md
+23 -4
@@ -15,17 +15,36 @@ function Component(c) {
15
16 ```
17 bb0:
18 - [1] Const mutate x$7_@0[0:3] = Object { c: read c$6 }
19 - [2] Call mutate mutate$3_@0(mutate x$7_@0)
18 + [1] Const mutate x$7_@0[1:3] = Object { c: read c$6 }
19 + [2] Call mutate mutate$3(mutate x$7_@0)
20 [3] Const mutate a$8_@1 = read x$7_@0
21 [4] Const mutate b$9_@2 = read a$8_@1
22 [5] Return
23 +scope0 [1:3]:
24 + - dependency: read c$6
25 scope1 [3:4]:
26 - dependency: read x$7_@0
27 scope2 [4:5]:
28 - dependency: read a$8_@1
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function Component(
35 + c,
36 +) {
37 + scope @0 [1:3] deps=[read c$6] {
38 + [1] Const mutate x$7_@0[1:3] = Object { c: read c$6 }
39 + [2] Call mutate mutate$3(mutate x$7_@0)
40 + }
41 + [3] Const mutate a$8_@1 = read x$7_@0
42 + [4] Const mutate b$9_@2 = read a$8_@1
43 + return
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
@@ -33,8 +52,8 @@ flowchart TB
52 %% Basic Blocks
53 subgraph bb0
54 bb0_instrs["
36 - [1] Const mutate x$7_@0[0:3] = Object { c: read c$6 }
37 - [2] Call mutate mutate$3_@0(mutate x$7_@0)
55 + [1] Const mutate x$7_@0[1:3] = Object { c: read c$6 }
56 + [2] Call mutate mutate$3(mutate x$7_@0)
57 [3] Const mutate a$8_@1 = read x$7_@0
58 [4] Const mutate b$9_@2 = read a$8_@1
59 "]
compiler/forget/src/__tests__/fixtures/hir/jsx-fragment.expect.md
+28
@@ -47,6 +47,34 @@ scope10 [11:12]:
47 - dependency: read $23_@9
48 ```
49
50 +## Reactive Scopes
51 +
52 +```
53 +function Foo(
54 + props,
55 +) {
56 + [1] Const mutate $14_@0 = "\n Hello "
57 + [2] Const mutate $15_@1 = " "
58 + [3] Const mutate $16_@2 = "\n "
59 + [4] Const mutate $17_@3 = "div"
60 + [5] Const mutate $18_@4 = "\n "
61 + [6] Const mutate $19_@5 = "Text"
62 + scope @6 [7:8] deps=[read $19_@5] {
63 + [7] Const mutate $20_@6 = JsxFragment [read $19_@5]
64 + }
65 + [8] Const mutate $21_@7 = "\n "
66 + scope @8 [9:10] deps=[read $17_@3, read $18_@4, read $20_@6, read $21_@7] {
67 + [9] Const mutate $22_@8 = JSX <read $17_@3>{read $18_@4}{read $20_@6}{read $21_@7}</read $17_@3>
68 + }
69 + [10] Const mutate $23_@9 = "\n "
70 + scope @10 [11:12] deps=[read $14_@0, read props$13.greeting, read $15_@1, read $16_@2, read $22_@8, read $23_@9] {
71 + [11] Const mutate $24_@10 = JsxFragment [read $14_@0, read props$13.greeting, read $15_@1, read $16_@2, read $22_@8, read $23_@9]
72 + }
73 + return read $24_@10
74 +}
75 +
76 +```
77 +
78 ### CFG
79
80 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/logical-expression.expect.md
+117 -24
@@ -23,20 +23,43 @@ function g() {}
23
24 ```
25 bb0:
26 - [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
27 - [2] Let mutate $6_@1[0:7] = undefined
26 + [1] Const mutate $5_@0 = Call mutate f$1()
27 + [2] Let mutate $6_@1[2:7] = undefined
28 [2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
29 bb2:
30 predecessor blocks: bb0
31 - [3] Const mutate $6_@1[0:7] = Call mutate g$4_@1()
31 + [3] Const mutate $6_@1[2:7] = Call mutate g$4()
32 [4] Goto bb1
33 bb3:
34 predecessor blocks: bb0
35 - [5] Const mutate $6_@1[0:7] = read $5_@0
35 + [5] Const mutate $6_@1[2:7] = read $5_@0
36 [6] Goto bb1
37 bb1:
38 predecessor blocks: bb2 bb3
39 [7] Return freeze $6_@1
40 +scope1 [2:7]:
41 + - dependency: read $5_@0
42 + - dependency: read $5_@0
43 +```
44 +
45 +## Reactive Scopes
46 +
47 +```
48 +function And(
49 +) {
50 + scope @0 [1:2] deps=[] {
51 + [1] Const mutate $5_@0 = Call mutate f$1()
52 + }
53 + scope @1 [2:7] deps=[read $5_@0, read $5_@0] {
54 + [2] Let mutate $6_@1[2:7] = undefined
55 + if (read $5_@0) {
56 + [3] Const mutate $6_@1[2:7] = Call mutate g$4()
57 + } else {
58 + [5] Const mutate $6_@1[2:7] = read $5_@0
59 + }
60 + }
61 + return freeze $6_@1
62 +}
63
64 ```
65
@@ -47,20 +70,20 @@ flowchart TB
70 %% Basic Blocks
71 subgraph bb0
72 bb0_instrs["
50 - [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
51 - [2] Let mutate $6_@1[0:7] = undefined
73 + [1] Const mutate $5_@0 = Call mutate f$1()
74 + [2] Let mutate $6_@1[2:7] = undefined
75 "]
76 bb0_instrs --> bb0_terminal(["If (read $5_@0)"])
77 end
78 subgraph bb2
79 bb2_instrs["
57 - [3] Const mutate $6_@1[0:7] = Call mutate g$4_@1()
80 + [3] Const mutate $6_@1[2:7] = Call mutate g$4()
81 "]
82 bb2_instrs --> bb2_terminal(["Goto"])
83 end
84 subgraph bb3
85 bb3_instrs["
63 - [5] Const mutate $6_@1[0:7] = read $5_@0
86 + [5] Const mutate $6_@1[2:7] = read $5_@0
87 "]
88 bb3_instrs --> bb3_terminal(["Goto"])
89 end
@@ -92,20 +115,43 @@ function And$0() {
115
116 ```
117 bb0:
95 - [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
96 - [2] Let mutate $6_@1[0:7] = undefined
118 + [1] Const mutate $5_@0 = Call mutate f$1()
119 + [2] Let mutate $6_@1[2:7] = undefined
120 [2] If (read $5_@0) then:bb2 else:bb3 fallthrough=bb1
121 bb2:
122 predecessor blocks: bb0
100 - [3] Const mutate $6_@1[0:7] = read $5_@0
123 + [3] Const mutate $6_@1[2:7] = read $5_@0
124 [4] Goto bb1
125 bb3:
126 predecessor blocks: bb0
104 - [5] Const mutate $6_@1[0:7] = Call mutate g$4_@1()
127 + [5] Const mutate $6_@1[2:7] = Call mutate g$4()
128 [6] Goto bb1
129 bb1:
130 predecessor blocks: bb2 bb3
131 [7] Return freeze $6_@1
132 +scope1 [2:7]:
133 + - dependency: read $5_@0
134 + - dependency: read $5_@0
135 +```
136 +
137 +## Reactive Scopes
138 +
139 +```
140 +function Or(
141 +) {
142 + scope @0 [1:2] deps=[] {
143 + [1] Const mutate $5_@0 = Call mutate f$1()
144 + }
145 + scope @1 [2:7] deps=[read $5_@0, read $5_@0] {
146 + [2] Let mutate $6_@1[2:7] = undefined
147 + if (read $5_@0) {
148 + [3] Const mutate $6_@1[2:7] = read $5_@0
149 + } else {
150 + [5] Const mutate $6_@1[2:7] = Call mutate g$4()
151 + }
152 + }
153 + return freeze $6_@1
154 +}
155
156 ```
157
@@ -116,20 +162,20 @@ flowchart TB
162 %% Basic Blocks
163 subgraph bb0
164 bb0_instrs["
119 - [1] Const mutate $5_@0[0:2] = Call mutate f$1_@0()
120 - [2] Let mutate $6_@1[0:7] = undefined
165 + [1] Const mutate $5_@0 = Call mutate f$1()
166 + [2] Let mutate $6_@1[2:7] = undefined
167 "]
168 bb0_instrs --> bb0_terminal(["If (read $5_@0)"])
169 end
170 subgraph bb2
171 bb2_instrs["
126 - [3] Const mutate $6_@1[0:7] = read $5_@0
172 + [3] Const mutate $6_@1[2:7] = read $5_@0
173 "]
174 bb2_instrs --> bb2_terminal(["Goto"])
175 end
176 subgraph bb3
177 bb3_instrs["
132 - [5] Const mutate $6_@1[0:7] = Call mutate g$4_@1()
178 + [5] Const mutate $6_@1[2:7] = Call mutate g$4()
179 "]
180 bb3_instrs --> bb3_terminal(["Goto"])
181 end
@@ -161,18 +207,18 @@ function Or$0() {
207
208 ```
209 bb0:
164 - [1] Const mutate $9_@0[0:2] = Call mutate f$2_@0()
210 + [1] Const mutate $9_@0 = Call mutate f$2()
211 [2] Const mutate $10_@1 = null
212 [3] Const mutate $11_@2 = Binary read $9_@0 != read $10_@1
167 - [4] Let mutate $12_@3[0:9] = undefined
213 + [4] Let mutate $12_@3[4:9] = undefined
214 [4] If (read $11_@2) then:bb2 else:bb3 fallthrough=bb1
215 bb2:
216 predecessor blocks: bb0
171 - [5] Const mutate $12_@3[0:9] = read $9_@0
217 + [5] Const mutate $12_@3[4:9] = read $9_@0
218 [6] Goto bb1
219 bb3:
220 predecessor blocks: bb0
175 - [7] Const mutate $12_@3[0:9] = Call mutate g$7_@3()
221 + [7] Const mutate $12_@3[4:9] = Call mutate g$7()
222 [8] Goto bb1
223 bb1:
224 predecessor blocks: bb2 bb3
@@ -180,6 +226,33 @@ bb1:
226 scope2 [3:4]:
227 - dependency: read $9_@0
228 - dependency: read $10_@1
229 +scope3 [4:9]:
230 + - dependency: read $9_@0
231 + - dependency: read $11_@2
232 +```
233 +
234 +## Reactive Scopes
235 +
236 +```
237 +function QuestionQuestion(
238 + props,
239 +) {
240 + scope @0 [1:2] deps=[] {
241 + [1] Const mutate $9_@0 = Call mutate f$2()
242 + }
243 + [2] Const mutate $10_@1 = null
244 + [3] Const mutate $11_@2 = Binary read $9_@0 != read $10_@1
245 + scope @3 [4:9] deps=[read $9_@0, read $11_@2] {
246 + [4] Let mutate $12_@3[4:9] = undefined
247 + if (read $11_@2) {
248 + [5] Const mutate $12_@3[4:9] = read $9_@0
249 + } else {
250 + [7] Const mutate $12_@3[4:9] = Call mutate g$7()
251 + }
252 + }
253 + return freeze $12_@3
254 +}
255 +
256 ```
257
258 ### CFG
@@ -189,22 +262,22 @@ flowchart TB
262 %% Basic Blocks
263 subgraph bb0
264 bb0_instrs["
192 - [1] Const mutate $9_@0[0:2] = Call mutate f$2_@0()
265 + [1] Const mutate $9_@0 = Call mutate f$2()
266 [2] Const mutate $10_@1 = null
267 [3] Const mutate $11_@2 = Binary read $9_@0 != read $10_@1
195 - [4] Let mutate $12_@3[0:9] = undefined
268 + [4] Let mutate $12_@3[4:9] = undefined
269 "]
270 bb0_instrs --> bb0_terminal(["If (read $11_@2)"])
271 end
272 subgraph bb2
273 bb2_instrs["
201 - [5] Const mutate $12_@3[0:9] = read $9_@0
274 + [5] Const mutate $12_@3[4:9] = read $9_@0
275 "]
276 bb2_instrs --> bb2_terminal(["Goto"])
277 end
278 subgraph bb3
279 bb3_instrs["
207 - [7] Const mutate $12_@3[0:9] = Call mutate g$7_@3()
280 + [7] Const mutate $12_@3[4:9] = Call mutate g$7()
281 "]
282 bb3_instrs --> bb3_terminal(["Goto"])
283 end
@@ -240,6 +313,16 @@ bb0:
313
314 ```
315
316 +## Reactive Scopes
317 +
318 +```
319 +function f(
320 +) {
321 + return
322 +}
323 +
324 +```
325 +
326 ### CFG
327
328 ```mermaid
@@ -267,6 +350,16 @@ bb0:
350
351 ```
352
353 +## Reactive Scopes
354 +
355 +```
356 +function g(
357 +) {
358 + return
359 +}
360 +
361 +```
362 +
363 ### CFG
364
365 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+91 -24
@@ -47,6 +47,18 @@ bb0:
47
48 ```
49
50 +## Reactive Scopes
51 +
52 +```
53 +function mutate(
54 + x,
55 + y,
56 +) {
57 + return
58 +}
59 +
60 +```
61 +
62 ### CFG
63
64 ```mermaid
@@ -74,6 +86,17 @@ bb0:
86
87 ```
88
89 +## Reactive Scopes
90 +
91 +```
92 +function cond(
93 + x,
94 +) {
95 + return
96 +}
97 +
98 +```
99 +
100 ### CFG
101
102 ```mermaid
@@ -97,10 +120,10 @@ function cond$0(x$2) {}
120
121 ```
122 bb0:
100 - [1] Let mutate a$18_@0[0:23] = Object { }
101 - [2] Let mutate b$20_@0[0:23] = Object { }
102 - [3] Let mutate c$22_@0[0:23] = Object { }
103 - [4] Let mutate d$24_@0[0:23] = Object { }
123 + [1] Let mutate a$18_@0[1:23] = Object { }
124 + [2] Let mutate b$20_@0[1:23] = Object { }
125 + [3] Let mutate c$22_@0[1:23] = Object { }
126 + [4] Let mutate d$24_@0[1:23] = Object { }
127 [5] While test=bb1 loop=bb3 fallthrough=bb2
128 bb1:
129 predecessor blocks: bb0 bb4
@@ -108,13 +131,13 @@ bb1:
131 [7] If (read $17_@1) then:bb3 else:bb2 fallthrough=bb2
132 bb3:
133 predecessor blocks: bb1
111 - [8] Const mutate z$19_@0[0:23] = read a$18_@0
112 - [9] Reassign mutate a$18_@0[0:23] = read b$20_@0
113 - [10] Reassign mutate b$20_@0[0:23] = read c$22_@0
114 - [11] Reassign mutate c$22_@0[0:23] = read d$24_@0
115 - [12] Reassign mutate d$24_@0[0:23] = read z$19_@0
116 - [13] Call mutate mutate$7_@0(mutate a$18_@0, mutate b$20_@0)
117 - [14] Const mutate $29_@0[0:23] = Call mutate cond$8_@0(mutate a$18_@0)
134 + [8] Const mutate z$19_@0[1:23] = read a$18_@0
135 + [9] Reassign mutate a$18_@0[1:23] = read b$20_@0
136 + [10] Reassign mutate b$20_@0[1:23] = read c$22_@0
137 + [11] Reassign mutate c$22_@0[1:23] = read d$24_@0
138 + [12] Reassign mutate d$24_@0[1:23] = read z$19_@0
139 + [13] Call mutate mutate$7(mutate a$18_@0, mutate b$20_@0)
140 + [14] Const mutate $29_@0[1:23] = Call mutate cond$8(mutate a$18_@0)
141 [15] If (read $29_@0) then:bb2 else:bb4 fallthrough=bb4
142 bb4:
143 predecessor blocks: bb3
@@ -134,11 +157,55 @@ bb11:
157 bb13:
158 predecessor blocks: bb11
159 [21] Const mutate $34_@2 = null
137 - [22] Call mutate mutate$7_@0(mutate d$24_@0, read $34_@2)
160 + [22] Call mutate mutate$7(mutate d$24_@0, read $34_@2)
161 [23] Return
162
163 ```
164
165 +## Reactive Scopes
166 +
167 +```
168 +function Component(
169 + props,
170 +) {
171 + scope @0 [1:23] deps=[] {
172 + [1] Let mutate a$18_@0[1:23] = Object { }
173 + [2] Let mutate b$20_@0[1:23] = Object { }
174 + [3] Let mutate c$22_@0[1:23] = Object { }
175 + [4] Let mutate d$24_@0[1:23] = Object { }
176 + scope @1 [6:8] deps=[] {
177 + while (
178 + [6] Const mutate $17_@1[6:8] = true
179 + read $17_@1
180 + ) {
181 + [8] Const mutate z$19_@0[1:23] = read a$18_@0
182 + [9] Reassign mutate a$18_@0[1:23] = read b$20_@0
183 + [10] Reassign mutate b$20_@0[1:23] = read c$22_@0
184 + [11] Reassign mutate c$22_@0[1:23] = read d$24_@0
185 + [12] Reassign mutate d$24_@0[1:23] = read z$19_@0
186 + [13] Call mutate mutate$7(mutate a$18_@0, mutate b$20_@0)
187 + [14] Const mutate $29_@0[1:23] = Call mutate cond$8(mutate a$18_@0)
188 + if (read $29_@0) {
189 + break
190 + }
191 + }
192 + }
193 + if (read a$18_@0) {
194 + }
195 + if (read b$20_@0) {
196 + }
197 + if (read c$22_@0) {
198 + }
199 + if (read d$24_@0) {
200 + }
201 + [21] Const mutate $34_@2 = null
202 + [22] Call mutate mutate$7(mutate d$24_@0, read $34_@2)
203 + }
204 + return
205 +}
206 +
207 +```
208 +
209 ### CFG
210
211 ```mermaid
@@ -146,10 +213,10 @@ flowchart TB
213 %% Basic Blocks
214 subgraph bb0
215 bb0_instrs["
149 - [1] Let mutate a$18_@0[0:23] = Object { }
150 - [2] Let mutate b$20_@0[0:23] = Object { }
151 - [3] Let mutate c$22_@0[0:23] = Object { }
152 - [4] Let mutate d$24_@0[0:23] = Object { }
216 + [1] Let mutate a$18_@0[1:23] = Object { }
217 + [2] Let mutate b$20_@0[1:23] = Object { }
218 + [3] Let mutate c$22_@0[1:23] = Object { }
219 + [4] Let mutate d$24_@0[1:23] = Object { }
220 "]
221 bb0_instrs --> bb0_terminal(["While"])
222 end
@@ -161,13 +228,13 @@ flowchart TB
228 end
229 subgraph bb3
230 bb3_instrs["
164 - [8] Const mutate z$19_@0[0:23] = read a$18_@0
165 - [9] Reassign mutate a$18_@0[0:23] = read b$20_@0
166 - [10] Reassign mutate b$20_@0[0:23] = read c$22_@0
167 - [11] Reassign mutate c$22_@0[0:23] = read d$24_@0
168 - [12] Reassign mutate d$24_@0[0:23] = read z$19_@0
169 - [13] Call mutate mutate$7_@0(mutate a$18_@0, mutate b$20_@0)
170 - [14] Const mutate $29_@0[0:23] = Call mutate cond$8_@0(mutate a$18_@0)
231 + [8] Const mutate z$19_@0[1:23] = read a$18_@0
232 + [9] Reassign mutate a$18_@0[1:23] = read b$20_@0
233 + [10] Reassign mutate b$20_@0[1:23] = read c$22_@0
234 + [11] Reassign mutate c$22_@0[1:23] = read d$24_@0
235 + [12] Reassign mutate d$24_@0[1:23] = read z$19_@0
236 + [13] Call mutate mutate$7(mutate a$18_@0, mutate b$20_@0)
237 + [14] Const mutate $29_@0[1:23] = Call mutate cond$8(mutate a$18_@0)
238 "]
239 bb3_instrs --> bb3_terminal(["If (read $29_@0)"])
240 end
@@ -189,7 +256,7 @@ flowchart TB
256 subgraph bb13
257 bb13_instrs["
258 [21] Const mutate $34_@2 = null
192 - [22] Call mutate mutate$7_@0(mutate d$24_@0, read $34_@2)
259 + [22] Call mutate mutate$7(mutate d$24_@0, read $34_@2)
260 "]
261 bb13_instrs --> bb13_terminal(["Return"])
262 end
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-with-aliasing.expect.md
+62 -12
@@ -43,6 +43,18 @@ bb0:
43
44 ```
45
46 +## Reactive Scopes
47 +
48 +```
49 +function mutate(
50 + x,
51 + y,
52 +) {
53 + return
54 +}
55 +
56 +```
57 +
58 ### CFG
59
60 ```mermaid
@@ -67,12 +79,12 @@ function mutate$0(x$3, y$4) {}
79 ```
80 bb0:
81 [1] Const mutate a$11_@0 = Object { }
70 - [2] Const mutate b$12_@1[0:15] = Array [read a$11_@0]
82 + [2] Const mutate b$12_@1[2:15] = Array [read a$11_@0]
83 [3] Const mutate c$13_@2 = Object { }
72 - [4] Const mutate d$14_@1[0:15] = Object { c: read c$13_@2 }
73 - [5] Const mutate x$15_@1[0:15] = Object { }
74 - [6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
75 - [7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
84 + [4] Const mutate d$14_@1[2:15] = Object { c: read c$13_@2 }
85 + [5] Const mutate x$15_@1[2:15] = Object { }
86 + [6] Reassign mutate x$15_@1.b[2:15] = read b$12_@1
87 + [7] Const mutate y$16_@1[2:15] = Call mutate mutate$8(mutate x$15_@1, mutate d$14_@1)
88 [8] If (read a$11_@0) then:bb1 else:bb1 fallthrough=bb1
89 bb1:
90 predecessor blocks: bb0
@@ -89,8 +101,46 @@ bb7:
101 bb9:
102 predecessor blocks: bb7
103 [13] Const mutate $17_@3 = null
92 - [14] Call mutate mutate$8_@1(mutate x$15_@1, read $17_@3)
104 + [14] Call mutate mutate$8(mutate x$15_@1, read $17_@3)
105 [15] Return
106 +scope1 [2:15]:
107 + - dependency: read a$11_@0
108 + - dependency: read a$11_@0
109 +```
110 +
111 +## Reactive Scopes
112 +
113 +```
114 +function Component(
115 + props,
116 +) {
117 + scope @0 [1:2] deps=[] {
118 + [1] Const mutate a$11_@0 = Object { }
119 + }
120 + scope @1 [2:15] deps=[read a$11_@0, read a$11_@0] {
121 + [2] Const mutate b$12_@1[2:15] = Array [read a$11_@0]
122 + scope @2 [3:4] deps=[] {
123 + [3] Const mutate c$13_@2 = Object { }
124 + }
125 + [4] Const mutate d$14_@1[2:15] = Object { c: read c$13_@2 }
126 + [5] Const mutate x$15_@1[2:15] = Object { }
127 + [6] Reassign mutate x$15_@1.b[2:15] = read b$12_@1
128 + [7] Const mutate y$16_@1[2:15] = Call mutate mutate$8(mutate x$15_@1, mutate d$14_@1)
129 + if (read a$11_@0) {
130 + }
131 + if (read b$12_@1) {
132 + }
133 + if (read c$13_@2) {
134 + }
135 + if (read d$14_@1) {
136 + }
137 + if (read y$16_@1) {
138 + }
139 + [13] Const mutate $17_@3 = null
140 + [14] Call mutate mutate$8(mutate x$15_@1, read $17_@3)
141 + }
142 + return
143 +}
144
145 ```
146
@@ -102,12 +152,12 @@ flowchart TB
152 subgraph bb0
153 bb0_instrs["
154 [1] Const mutate a$11_@0 = Object { }
105 - [2] Const mutate b$12_@1[0:15] = Array [read a$11_@0]
155 + [2] Const mutate b$12_@1[2:15] = Array [read a$11_@0]
156 [3] Const mutate c$13_@2 = Object { }
107 - [4] Const mutate d$14_@1[0:15] = Object { c: read c$13_@2 }
108 - [5] Const mutate x$15_@1[0:15] = Object { }
109 - [6] Reassign mutate x$15_@1.b[0:15] = read b$12_@1
110 - [7] Const mutate y$16_@1[0:15] = Call mutate mutate$8_@1(mutate x$15_@1, mutate d$14_@1)
157 + [4] Const mutate d$14_@1[2:15] = Object { c: read c$13_@2 }
158 + [5] Const mutate x$15_@1[2:15] = Object { }
159 + [6] Reassign mutate x$15_@1.b[2:15] = read b$12_@1
160 + [7] Const mutate y$16_@1[2:15] = Call mutate mutate$8(mutate x$15_@1, mutate d$14_@1)
161 "]
162 bb0_instrs --> bb0_terminal(["If (read a$11_@0)"])
163 end
@@ -126,7 +176,7 @@ flowchart TB
176 subgraph bb9
177 bb9_instrs["
178 [13] Const mutate $17_@3 = null
129 - [14] Call mutate mutate$8_@1(mutate x$15_@1, read $17_@3)
179 + [14] Call mutate mutate$8(mutate x$15_@1, read $17_@3)
180 "]
181 bb9_instrs --> bb9_terminal(["Return"])
182 end
compiler/forget/src/__tests__/fixtures/hir/mutable-liverange-loop.expect.md
+79 -18
@@ -42,6 +42,16 @@ bb0:
42
43 ```
44
45 +## Reactive Scopes
46 +
47 +```
48 +function mutate(
49 +) {
50 + return
51 +}
52 +
53 +```
54 +
55 ### CFG
56
57 ```mermaid
@@ -69,6 +79,16 @@ bb0:
79
80 ```
81
82 +## Reactive Scopes
83 +
84 +```
85 +function cond(
86 +) {
87 + return
88 +}
89 +
90 +```
91 +
92 ### CFG
93
94 ```mermaid
@@ -92,19 +112,19 @@ function cond$0() {}
112
113 ```
114 bb0:
95 - [1] Const mutate a$12_@0[0:18] = Object { }
96 - [2] Const mutate b$13_@0[0:18] = Object { }
115 + [1] Const mutate a$12_@0[1:18] = Object { }
116 + [2] Const mutate b$13_@0[1:18] = Object { }
117 [3] Const mutate c$14_@1 = Object { }
98 - [4] Const mutate d$15_@0[0:18] = Object { }
118 + [4] Const mutate d$15_@0[1:18] = Object { }
119 [5] While test=bb1 loop=bb3 fallthrough=bb2
120 bb1:
121 predecessor blocks: bb0 bb4
102 - [6] Const mutate $16_@2[6:8] = true
103 - [7] If (read $16_@2) then:bb3 else:bb2 fallthrough=bb2
122 + [6] Const mutate $16_@3[6:8] = true
123 + [7] If (read $16_@3) then:bb3 else:bb2 fallthrough=bb2
124 bb3:
125 predecessor blocks: bb1
106 - [8] Call mutate mutate$6_@0(mutate a$12_@0, mutate b$13_@0)
107 - [9] Const mutate $21_@0[0:18] = Call mutate cond$7_@0(mutate a$12_@0)
126 + [8] Call mutate mutate$6(mutate a$12_@0, mutate b$13_@0)
127 + [9] Const mutate $21_@0[1:18] = Call mutate cond$7(mutate a$12_@0)
128 [10] If (read $21_@0) then:bb2 else:bb4 fallthrough=bb4
129 bb4:
130 predecessor blocks: bb3
@@ -123,12 +143,53 @@ bb11:
143 [15] If (read d$15_@0) then:bb13 else:bb13 fallthrough=bb13
144 bb13:
145 predecessor blocks: bb11
126 - [16] Const mutate $28_@3 = null
127 - [17] Call mutate mutate$6_@0(mutate d$15_@0, read $28_@3)
146 + [16] Const mutate $28_@4 = null
147 + [17] Call mutate mutate$6(mutate d$15_@0, read $28_@4)
148 [18] Return
149
150 ```
151
152 +## Reactive Scopes
153 +
154 +```
155 +function Component(
156 + props,
157 +) {
158 + scope @0 [1:18] deps=[] {
159 + [1] Const mutate a$12_@0[1:18] = Object { }
160 + [2] Const mutate b$13_@0[1:18] = Object { }
161 + scope @1 [3:4] deps=[] {
162 + [3] Const mutate c$14_@1 = Object { }
163 + }
164 + [4] Const mutate d$15_@0[1:18] = Object { }
165 + scope @3 [6:8] deps=[] {
166 + while (
167 + [6] Const mutate $16_@3[6:8] = true
168 + read $16_@3
169 + ) {
170 + [8] Call mutate mutate$6(mutate a$12_@0, mutate b$13_@0)
171 + [9] Const mutate $21_@0[1:18] = Call mutate cond$7(mutate a$12_@0)
172 + if (read $21_@0) {
173 + break
174 + }
175 + }
176 + }
177 + if (read a$12_@0) {
178 + }
179 + if (read b$13_@0) {
180 + }
181 + if (read c$14_@1) {
182 + }
183 + if (read d$15_@0) {
184 + }
185 + [16] Const mutate $28_@4 = null
186 + [17] Call mutate mutate$6(mutate d$15_@0, read $28_@4)
187 + }
188 + return
189 +}
190 +
191 +```
192 +
193 ### CFG
194
195 ```mermaid
@@ -136,23 +197,23 @@ flowchart TB
197 %% Basic Blocks
198 subgraph bb0
199 bb0_instrs["
139 - [1] Const mutate a$12_@0[0:18] = Object { }
140 - [2] Const mutate b$13_@0[0:18] = Object { }
200 + [1] Const mutate a$12_@0[1:18] = Object { }
201 + [2] Const mutate b$13_@0[1:18] = Object { }
202 [3] Const mutate c$14_@1 = Object { }
142 - [4] Const mutate d$15_@0[0:18] = Object { }
203 + [4] Const mutate d$15_@0[1:18] = Object { }
204 "]
205 bb0_instrs --> bb0_terminal(["While"])
206 end
207 subgraph bb1
208 bb1_instrs["
148 - [6] Const mutate $16_@2[6:8] = true
209 + [6] Const mutate $16_@3[6:8] = true
210 "]
150 - bb1_instrs --> bb1_terminal(["If (read $16_@2)"])
211 + bb1_instrs --> bb1_terminal(["If (read $16_@3)"])
212 end
213 subgraph bb3
214 bb3_instrs["
154 - [8] Call mutate mutate$6_@0(mutate a$12_@0, mutate b$13_@0)
155 - [9] Const mutate $21_@0[0:18] = Call mutate cond$7_@0(mutate a$12_@0)
215 + [8] Call mutate mutate$6(mutate a$12_@0, mutate b$13_@0)
216 + [9] Const mutate $21_@0[1:18] = Call mutate cond$7(mutate a$12_@0)
217 "]
218 bb3_instrs --> bb3_terminal(["If (read $21_@0)"])
219 end
@@ -173,8 +234,8 @@ flowchart TB
234 end
235 subgraph bb13
236 bb13_instrs["
176 - [16] Const mutate $28_@3 = null
177 - [17] Call mutate mutate$6_@0(mutate d$15_@0, read $28_@3)
237 + [16] Const mutate $28_@4 = null
238 + [17] Call mutate mutate$6(mutate d$15_@0, read $28_@4)
239 "]
240 bb13_instrs --> bb13_terminal(["Return"])
241 end
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-interleaved-by-terminal.expect.md
+21
@@ -30,6 +30,27 @@ bb1:
30
31 ```
32
33 +## Reactive Scopes
34 +
35 +```
36 +function foo(
37 + a,
38 + b,
39 + c,
40 +) {
41 + scope @0 [1:6] deps=[] {
42 + [1] Const mutate x$9_@0[1:6] = Array []
43 + [2] Const mutate y$10_@0[1:6] = Array []
44 + if (read x$9_@0) {
45 + }
46 + [4] Call mutate y$10_@0.push(read a$6)
47 + [5] Call mutate x$9_@0.push(read b$7)
48 + }
49 + return
50 +}
51 +
52 +```
53 +
54 ### CFG
55
56 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-interleaved.expect.md
+18
@@ -23,6 +23,24 @@ bb0:
23
24 ```
25
26 +## Reactive Scopes
27 +
28 +```
29 +function foo(
30 + a,
31 + b,
32 +) {
33 + scope @0 [1:5] deps=[] {
34 + [1] Const mutate x$7_@0[1:5] = Array []
35 + [2] Const mutate y$8_@0[1:5] = Array []
36 + [3] Call mutate x$7_@0.push(read a$5)
37 + [4] Call mutate y$8_@0.push(read b$6)
38 + }
39 + return
40 +}
41 +
42 +```
43 +
44 ### CFG
45
46 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-shadowed.expect.md
+20
@@ -25,6 +25,26 @@ scope1 [2:4]:
25 - dependency: read a$5
26 ```
27
28 +## Reactive Scopes
29 +
30 +```
31 +function foo(
32 + a,
33 + b,
34 +) {
35 + scope @0 [1:5] deps=[] {
36 + [1] Const mutate x$7_@0[1:5] = Array []
37 + scope @1 [2:4] deps=[read b$6, read a$5] {
38 + [2] Const mutate y$8_@1[2:4] = Array []
39 + [3] Call mutate y$8_@1.push(read b$6)
40 + }
41 + [4] Call mutate x$7_@0.push(read a$5)
42 + }
43 + return
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-shadowing-within-block.expect.md
+29
@@ -50,6 +50,35 @@ scope3 [8:9]:
50 - dependency: freeze y$12_@1
51 ```
52
53 +## Reactive Scopes
54 +
55 +```
56 +function foo(
57 + a,
58 + b,
59 + c,
60 +) {
61 + scope @0 [1:11] deps=[read a$8] {
62 + [1] Const mutate x$11_@0[1:11] = Array []
63 + if (read a$8) {
64 + scope @1 [3:7] deps=[read c$10, read b$9] {
65 + [3] Const mutate y$12_@1[3:7] = Array []
66 + if (read b$9) {
67 + [5] Call mutate y$12_@1.push(read c$10)
68 + }
69 + }
70 + [7] Const mutate $13_@2 = "div"
71 + scope @3 [8:9] deps=[read $13_@2, freeze y$12_@1] {
72 + [8] Const mutate $15_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
73 + }
74 + [9] Call mutate x$11_@0.push(read $15_@3)
75 + }
76 + }
77 + return freeze x$11_@0
78 +}
79 +
80 +```
81 +
82 ### CFG
83
84 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-while.expect.md
+23
@@ -34,6 +34,29 @@ bb2:
34
35 ```
36
37 +## Reactive Scopes
38 +
39 +```
40 +function foo(
41 + a,
42 + b,
43 + c,
44 +) {
45 + scope @0 [1:8] deps=[] {
46 + [1] Const mutate x$9_@0[1:8] = Array []
47 + [2] Const mutate y$10_@0[1:8] = Array []
48 + while (
49 + read c$8
50 + ) {
51 + [5] Call mutate y$10_@0.push(read b$7)
52 + [6] Call mutate x$9_@0.push(read a$6)
53 + }
54 + }
55 + return
56 +}
57 +
58 +```
59 +
60 ### CFG
61
62 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/overlapping-scopes-within-block.expect.md
+23
@@ -44,6 +44,29 @@ scope0 [1:9]:
44 - dependency: read a$6
45 ```
46
47 +## Reactive Scopes
48 +
49 +```
50 +function foo(
51 + a,
52 + b,
53 + c,
54 +) {
55 + scope @0 [1:9] deps=[read c$8, read b$7, read a$6] {
56 + [1] Const mutate x$9_@0[1:9] = Array []
57 + if (read a$6) {
58 + [3] Const mutate y$10_@0[1:9] = Array []
59 + if (read b$7) {
60 + [5] Call mutate y$10_@0.push(read c$8)
61 + }
62 + [7] Call mutate x$9_@0.push(mutate y$10_@0)
63 + }
64 + }
65 + return freeze x$9_@0
66 +}
67 +
68 +```
69 +
70 ### CFG
71
72 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/property-assignment.expect.md
+21
@@ -33,6 +33,27 @@ scope1 [6:7]:
33 - dependency: read child$9_@0
34 ```
35
36 +## Reactive Scopes
37 +
38 +```
39 +function Component(
40 + props,
41 +) {
42 + scope @0 [1:6] deps=[read Component$0, read props$6.p0] {
43 + [1] Const mutate x$7_@0[1:6] = Object { }
44 + [2] Const mutate y$8_@0[1:6] = Array []
45 + [3] Reassign mutate x$7_@0.y[1:6] = read y$8_@0
46 + [4] Const mutate child$9_@0[1:6] = JSX <read Component$0 data={freeze y$8_@0} ></read Component$0>
47 + [5] Call mutate x$7_@0.y.push(read props$6.p0)
48 + }
49 + scope @1 [6:7] deps=[read Component$0, freeze x$7_@0, read child$9_@0] {
50 + [6] Const mutate $10_@1 = JSX <read Component$0 data={freeze x$7_@0} >{read child$9_@0}</read Component$0>
51 + }
52 + return read $10_@1
53 +}
54 +
55 +```
56 +
57 ### CFG
58
59 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reactive-scope-grouping.expect.md
+19
@@ -28,6 +28,25 @@ scope1 [2:5]:
28 - dependency: mutate x$4_@0.y
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function foo(
35 +) {
36 + scope @0 [1:6] deps=[] {
37 + [1] Const mutate x$4_@0[1:6] = Object { }
38 + scope @1 [2:5] deps=[mutate x$4_@0.y] {
39 + [2] Const mutate y$5_@1[2:5] = Array []
40 + [3] Const mutate z$6_@1[2:5] = Object { }
41 + [4] Call mutate y$5_@1.push(mutate z$6_@1)
42 + }
43 + [5] Reassign mutate x$4_@0.y[1:6] = read y$5_@1
44 + }
45 + return freeze x$4_@0
46 +}
47 +
48 +```
49 +
50 ### CFG
51
52 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes-if.expect.md new
+136
@@ -0,0 +1,136 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function foo(a, b, c) {
6 + const x = [];
7 + if (a) {
8 + const y = [];
9 + y.push(b);
10 + x.push(<div>{y}</div>);
11 + } else {
12 + x.push(c);
13 + }
14 + return x;
15 +}
16 +
17 +```
18 +
19 +## HIR
20 +
21 +```
22 +bb0:
23 + [1] Const mutate x$11_@0[1:11] = Array []
24 + [2] If (read a$8) then:bb2 else:bb3 fallthrough=bb1
25 +bb2:
26 + predecessor blocks: bb0
27 + [3] Const mutate y$12_@1[3:5] = Array []
28 + [4] Call mutate y$12_@1.push(read b$9)
29 + [5] Const mutate $13_@2 = "div"
30 + [6] Const mutate $14_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
31 + [7] Call mutate x$11_@0.push(read $14_@3)
32 + [8] Goto bb1
33 +bb3:
34 + predecessor blocks: bb0
35 + [9] Call mutate x$11_@0.push(read c$10)
36 + [10] Goto bb1
37 +bb1:
38 + predecessor blocks: bb2 bb3
39 + [11] Return freeze x$11_@0
40 +scope0 [1:11]:
41 + - dependency: read c$10
42 + - dependency: read a$8
43 +scope1 [3:5]:
44 + - dependency: read b$9
45 +scope3 [6:7]:
46 + - dependency: read $13_@2
47 + - dependency: freeze y$12_@1
48 +```
49 +
50 +## Reactive Scopes
51 +
52 +```
53 +function foo(
54 + a,
55 + b,
56 + c,
57 +) {
58 + scope @0 [1:11] deps=[read c$10, read a$8] {
59 + [1] Const mutate x$11_@0[1:11] = Array []
60 + if (read a$8) {
61 + scope @1 [3:5] deps=[read b$9] {
62 + [3] Const mutate y$12_@1[3:5] = Array []
63 + [4] Call mutate y$12_@1.push(read b$9)
64 + }
65 + [5] Const mutate $13_@2 = "div"
66 + scope @3 [6:7] deps=[read $13_@2, freeze y$12_@1] {
67 + [6] Const mutate $14_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
68 + }
69 + [7] Call mutate x$11_@0.push(read $14_@3)
70 + } else {
71 + [9] Call mutate x$11_@0.push(read c$10)
72 + }
73 + }
74 + return freeze x$11_@0
75 +}
76 +
77 +```
78 +
79 +### CFG
80 +
81 +```mermaid
82 +flowchart TB
83 + %% Basic Blocks
84 + subgraph bb0
85 + bb0_instrs["
86 + [1] Const mutate x$11_@0[1:11] = Array []
87 + "]
88 + bb0_instrs --> bb0_terminal(["If (read a$8)"])
89 + end
90 + subgraph bb2
91 + bb2_instrs["
92 + [3] Const mutate y$12_@1[3:5] = Array []
93 + [4] Call mutate y$12_@1.push(read b$9)
94 + [5] Const mutate $13_@2 = 'div'
95 + [6] Const mutate $14_@3 = JSX <read $13_@2>{freeze y$12_@1}</read $13_@2>
96 + [7] Call mutate x$11_@0.push(read $14_@3)
97 + "]
98 + bb2_instrs --> bb2_terminal(["Goto"])
99 + end
100 + subgraph bb3
101 + bb3_instrs["
102 + [9] Call mutate x$11_@0.push(read c$10)
103 + "]
104 + bb3_instrs --> bb3_terminal(["Goto"])
105 + end
106 + subgraph bb1
107 + bb1_terminal(["Return freeze x$11_@0"])
108 + end
109 +
110 + %% Jumps
111 + bb0_terminal -- "then" --> bb2
112 + bb0_terminal -- "else" --> bb3
113 + bb0_terminal -- "fallthrough" --> bb1
114 + bb2_terminal --> bb1
115 + bb3_terminal --> bb1
116 +
117 +```
118 +
119 +## Code
120 +
121 +```javascript
122 +function foo$0(a$8, b$9, c$10) {
123 + const x$11 = [];
124 + bb1: if (a$8) {
125 + const y$12 = [];
126 + y$12.push(b$9);
127 + x$11.push(<div>{y$12}</div>);
128 + } else {
129 + x$11.push(c$10);
130 + }
131 +
132 + return x$11;
133 +}
134 +
135 +```
136 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes-if.js new
+11
@@ -0,0 +1,11 @@
1 +function foo(a, b, c) {
2 + const x = [];
3 + if (a) {
4 + const y = [];
5 + y.push(b);
6 + x.push(<div>{y}</div>);
7 + } else {
8 + x.push(c);
9 + }
10 + return x;
11 +}
compiler/forget/src/__tests__/fixtures/hir/reactive-scopes.expect.md
+26
@@ -46,6 +46,32 @@ scope4 [9:10]:
46 - dependency: freeze x$10_@0
47 ```
48
49 +## Reactive Scopes
50 +
51 +```
52 +function f(
53 + a,
54 + b,
55 +) {
56 + scope @0 [1:8] deps=[read b$9, read b$9] {
57 + [1] Const mutate x$10_@0[1:8] = Array []
58 + [2] Const mutate $11_@1 = 1
59 + [3] Const mutate $12_@2 = Binary read a$8.length === read $11_@1
60 + if (read $12_@2) {
61 + if (read b$9) {
62 + [6] Call mutate x$10_@0.push(read b$9)
63 + }
64 + }
65 + }
66 + [8] Const mutate $13_@3 = "div"
67 + scope @4 [9:10] deps=[read $13_@3, freeze x$10_@0] {
68 + [9] Const mutate $15_@4 = JSX <read $13_@3>{freeze x$10_@0}</read $13_@3>
69 + }
70 + return read $15_@4
71 +}
72 +
73 +```
74 +
75 ### CFG
76
77 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+26
@@ -51,6 +51,32 @@ scope2 [9:10]:
51 - dependency: read y$8_@0
52 ```
53
54 +## Reactive Scopes
55 +
56 +```
57 +function Component(
58 + props,
59 +) {
60 + scope @0 [1:7] deps=[read props$6.p0, read props$6.p1] {
61 + [1] Let mutate x$7_@0[1:7] = Array []
62 + [2] Call mutate x$7_@0.push(read props$6.p0)
63 + [3] Const mutate y$8_@0[1:7] = read x$7_@0
64 + if (read props$6.p1) {
65 + [5] Reassign mutate x$7_@0[1:7] = Array []
66 + }
67 + }
68 + scope @1 [7:8] deps=[read Component$0, freeze x$7_@0, read y$8_@0.push, read props$6.p2] {
69 + [7] Const mutate _$12_@1 = JSX <read Component$0 x={freeze x$7_@0} ></read Component$0>
70 + }
71 + [8] Call read y$8_@0.push(read props$6.p2)
72 + scope @2 [9:10] deps=[read Component$0, read x$7_@0, read y$8_@0] {
73 + [9] Const mutate $15_@2 = JSX <read Component$0 x={read x$7_@0} y={read y$8_@0} ></read Component$0>
74 + }
75 + return read $15_@2
76 +}
77 +
78 +```
79 +
80 ### CFG
81
82 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reassignment-separate-scopes.expect.md
+45
@@ -87,6 +87,51 @@ scope9 [19:20]:
87 - dependency: read $28_@8
88 ```
89
90 +## Reactive Scopes
91 +
92 +```
93 +function foo(
94 + a,
95 + b,
96 + c,
97 +) {
98 + scope @0 [1:5] deps=[read a$13, read a$13] {
99 + [1] Const mutate x$16_@0[1:5] = Array []
100 + if (read a$13) {
101 + [3] Call mutate x$16_@0.push(read a$13)
102 + }
103 + }
104 + [5] Const mutate $17_@1 = "div"
105 + scope @2 [6:7] deps=[read $17_@1, freeze x$16_@0] {
106 + [6] Const mutate y$19_@2 = JSX <read $17_@1>{freeze x$16_@0}</read $17_@1>
107 + }
108 + [7] Const mutate $20_@3 = 0
109 + scope @4 [8:15] deps=[read c$15, read b$14, read b$14] {
110 + [8] Let mutate x$22_@4[8:15] = undefined
111 + switch (read b$14) {
112 + case read $20_@3: {
113 + [9] Reassign mutate x$22_@4[8:15] = Array []
114 + [10] Call mutate x$22_@4.push(read b$14)
115 + break bb3
116 + }
117 + default: {
118 + [12] Reassign mutate x$22_@4[8:15] = Array []
119 + [13] Call mutate x$22_@4.push(read c$15)
120 + }
121 + }
122 + }
123 + [15] Const mutate $25_@5 = "div"
124 + [16] Const mutate $26_@6 = "\n "
125 + [17] Const mutate $27_@7 = "\n "
126 + [18] Const mutate $28_@8 = "\n "
127 + scope @9 [19:20] deps=[read $25_@5, read $26_@6, read y$19_@2, read $27_@7, freeze x$22_@4, read $28_@8] {
128 + [19] Const mutate $31_@9 = JSX <read $25_@5>{read $26_@6}{read y$19_@2}{read $27_@7}{freeze x$22_@4}{read $28_@8}</read $25_@5>
129 + }
130 + return read $31_@9
131 +}
132 +
133 +```
134 +
135 ### CFG
136
137 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md
+26
@@ -41,6 +41,32 @@ scope3 [7:8]:
41 - dependency: freeze y$8_@0
42 ```
43
44 +## Reactive Scopes
45 +
46 +```
47 +function Component(
48 + props,
49 +) {
50 + scope @0 [1:7] deps=[read props$6.p0] {
51 + [1] Const mutate x$7_@0[1:7] = Array []
52 + [2] Call mutate x$7_@0.push(read props$6.p0)
53 + [3] Const mutate y$8_@0[1:7] = read x$7_@0
54 + scope @1 [4:5] deps=[] {
55 + [4] Const mutate x$9_@1 = Array []
56 + }
57 + scope @2 [5:6] deps=[read Component$0, freeze x$9_@1, read props$6.p1] {
58 + [5] Const mutate _$10_@2 = JSX <read Component$0 x={freeze x$9_@1} ></read Component$0>
59 + }
60 + [6] Call mutate y$8_@0.push(read props$6.p1)
61 + }
62 + scope @3 [7:8] deps=[read Component$0, read x$9_@1, freeze y$8_@0] {
63 + [7] Const mutate $11_@3 = JSX <read Component$0 x={read x$9_@1} y={freeze y$8_@0} ></read Component$0>
64 + }
65 + return read $11_@3
66 +}
67 +
68 +```
69 +
70 ### CFG
71
72 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+42
@@ -88,6 +88,48 @@ scope1 [2:18]:
88 - dependency: read props$6.cond
89 ```
90
91 +## Reactive Scopes
92 +
93 +```
94 +function Component(
95 + props,
96 +) {
97 + [1] Const mutate x$7_@0 = undefined
98 + scope @1 [2:18] deps=[read props$6.v2, read props$6.v1, read props$6.v0, read props$6.test, read props$6.b, read props$6.c, read props$6.cond2, read props$6.cond] {
99 + [2] Let mutate x$11_@1[2:18] = undefined
100 + if (read props$6.cond) {
101 + [3] Const mutate $8_@2 = 2
102 + [4] Const mutate $9_@3 = 1
103 + [5] Const mutate $10_@4 = 0
104 + switch (read props$6.test) {
105 + case read $10_@4: {
106 + [7] Reassign mutate x$11_@1[2:18] = read props$6.v0
107 + break bb1
108 + }
109 + case read $9_@3: {
110 + [9] Reassign mutate x$11_@1[2:18] = read props$6.v1
111 + break bb1
112 + }
113 + case read $8_@2: {
114 + }
115 + default: {
116 + [11] Reassign mutate x$11_@1[2:18] = read props$6.v2
117 + }
118 + }
119 + } else {
120 + if (read props$6.cond2) {
121 + [14] Reassign mutate x$11_@1[2:18] = read props$6.b
122 + } else {
123 + [16] Reassign mutate x$11_@1[2:18] = read props$6.c
124 + }
125 + }
126 + }
127 + [18] read x$11_@1
128 + return
129 +}
130 +
131 +```
132 +
133 ### CFG
134
135 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/simple-alias.expect.md
+43 -12
@@ -24,6 +24,16 @@ bb0:
24
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function mutate(
31 +) {
32 + return
33 +}
34 +
35 +```
36 +
37 ### CFG
38
39 ```mermaid
@@ -48,16 +58,37 @@ function mutate$0() {}
58 ```
59 bb0:
60 [1] Const mutate a$5_@0 = Object { }
51 - [2] Const mutate b$6_@1[0:8] = Object { }
52 - [3] Const mutate c$7_@1[0:8] = Object { }
53 - [4] Const mutate a$8_@1[0:8] = read b$6_@1
54 - [5] Const mutate b$9_@1[0:8] = read c$7_@1
55 - [6] Const mutate c$10_@1[0:8] = read a$8_@1
56 - [7] Call mutate mutate$4_@1(mutate a$8_@1, mutate b$9_@1)
61 + [2] Const mutate b$6_@1[2:8] = Object { }
62 + [3] Const mutate c$7_@1[2:8] = Object { }
63 + [4] Const mutate a$8_@1[2:8] = read b$6_@1
64 + [5] Const mutate b$9_@1[2:8] = read c$7_@1
65 + [6] Const mutate c$10_@1[2:8] = read a$8_@1
66 + [7] Call mutate mutate$4(mutate a$8_@1, mutate b$9_@1)
67 [8] Return freeze c$10_@1
68
69 ```
70
71 +## Reactive Scopes
72 +
73 +```
74 +function foo(
75 +) {
76 + scope @0 [1:2] deps=[] {
77 + [1] Const mutate a$5_@0 = Object { }
78 + }
79 + scope @1 [2:8] deps=[] {
80 + [2] Const mutate b$6_@1[2:8] = Object { }
81 + [3] Const mutate c$7_@1[2:8] = Object { }
82 + [4] Const mutate a$8_@1[2:8] = read b$6_@1
83 + [5] Const mutate b$9_@1[2:8] = read c$7_@1
84 + [6] Const mutate c$10_@1[2:8] = read a$8_@1
85 + [7] Call mutate mutate$4(mutate a$8_@1, mutate b$9_@1)
86 + }
87 + return freeze c$10_@1
88 +}
89 +
90 +```
91 +
92 ### CFG
93
94 ```mermaid
@@ -66,12 +97,12 @@ flowchart TB
97 subgraph bb0
98 bb0_instrs["
99 [1] Const mutate a$5_@0 = Object { }
69 - [2] Const mutate b$6_@1[0:8] = Object { }
70 - [3] Const mutate c$7_@1[0:8] = Object { }
71 - [4] Const mutate a$8_@1[0:8] = read b$6_@1
72 - [5] Const mutate b$9_@1[0:8] = read c$7_@1
73 - [6] Const mutate c$10_@1[0:8] = read a$8_@1
74 - [7] Call mutate mutate$4_@1(mutate a$8_@1, mutate b$9_@1)
100 + [2] Const mutate b$6_@1[2:8] = Object { }
101 + [3] Const mutate c$7_@1[2:8] = Object { }
102 + [4] Const mutate a$8_@1[2:8] = read b$6_@1
103 + [5] Const mutate b$9_@1[2:8] = read c$7_@1
104 + [6] Const mutate c$10_@1[2:8] = read a$8_@1
105 + [7] Call mutate mutate$4(mutate a$8_@1, mutate b$9_@1)
106 "]
107 bb0_instrs --> bb0_terminal(["Return freeze c$10_@1"])
108 end
compiler/forget/src/__tests__/fixtures/hir/simple.expect.md
+24
@@ -38,6 +38,30 @@ scope4 [7:8]:
38 - dependency: read $13_@3
39 ```
40
41 +## Reactive Scopes
42 +
43 +```
44 +function foo(
45 + x,
46 + y,
47 +) {
48 + if (read x$8) {
49 + [2] Const mutate $10_@0 = false
50 + scope @1 [3:4] deps=[read foo$0, read $10_@0, read y$9] {
51 + [3] Const mutate $11_@1 = Call read foo$0(read $10_@0, read y$9)
52 + }
53 + return freeze $11_@1
54 + }
55 + [5] Const mutate $12_@2 = 10
56 + [6] Const mutate $13_@3 = Binary read y$9 * read $12_@2
57 + scope @4 [7:8] deps=[read $13_@3] {
58 + [7] Const mutate $14_@4 = Array [read $13_@3]
59 + }
60 + return freeze $14_@4
61 +}
62 +
63 +```
64 +
65 ### CFG
66
67 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-arrayexpression.expect.md
+16
@@ -24,6 +24,22 @@ scope2 [3:4]:
24 - dependency: read b$7_@1
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function Component(
31 + props,
32 +) {
33 + [1] Const mutate a$6_@0 = 1
34 + [2] Const mutate b$7_@1 = 2
35 + scope @2 [3:4] deps=[read a$6_@0, read b$7_@1] {
36 + [3] Const mutate x$8_@2 = Array [read a$6_@0, read b$7_@1]
37 + }
38 + return freeze x$8_@2
39 +}
40 +
41 +```
42 +
43 ### CFG
44
45 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx-2.expect.md
+66 -26
@@ -26,6 +26,16 @@ bb0:
26
27 ```
28
29 +## Reactive Scopes
30 +
31 +```
32 +function foo(
33 +) {
34 + return
35 +}
36 +
37 +```
38 +
39 ### CFG
40
41 ```mermaid
@@ -49,30 +59,60 @@ function foo$0() {}
59
60 ```
61 bb0:
52 - [1] Const mutate a$11_@0[0:10] = Array []
53 - [2] Const mutate b$12_@0[0:10] = Object { }
54 - [3] Call mutate foo$4_@0(mutate a$11_@0, mutate b$12_@0)
55 - [4] Const mutate $13_@0[0:10] = Call mutate foo$4_@0()
56 - [5] If (read $13_@0) then:bb2 else:bb1 fallthrough=bb1
62 + [1] Const mutate a$11_@0[1:10] = Array []
63 + [2] Const mutate b$12_@0[1:10] = Object { }
64 + [3] Call mutate foo$4(mutate a$11_@0, mutate b$12_@0)
65 + [4] Const mutate $13_@1 = Call mutate foo$4()
66 + [5] If (read $13_@1) then:bb2 else:bb1 fallthrough=bb1
67 bb2:
68 predecessor blocks: bb0
59 - [6] Const mutate $14_@1 = "div"
60 - [7] Const mutate _$15_@2 = JSX <read $14_@1 a={freeze a$11_@0} ></read $14_@1>
69 + [6] Const mutate $14_@2 = "div"
70 + [7] Const mutate _$15_@3 = JSX <read $14_@2 a={freeze a$11_@0} ></read $14_@2>
71 [8] Goto bb1
72 bb1:
73 predecessor blocks: bb2 bb0
64 - [9] Call mutate foo$4_@0(read a$11_@0, mutate b$12_@0)
65 - [10] Const mutate $19_@3 = "div"
66 - [11] Const mutate $20_@4 = JSX <read $19_@3 a={freeze a$11_@0} b={freeze b$12_@0} ></read $19_@3>
67 - [12] Return read $20_@4
68 -scope2 [7:8]:
69 - - dependency: read $14_@1
70 -scope4 [11:12]:
71 - - dependency: read $19_@3
74 + [9] Call mutate foo$4(read a$11_@0, mutate b$12_@0)
75 + [10] Const mutate $19_@4 = "div"
76 + [11] Const mutate $20_@5 = JSX <read $19_@4 a={freeze a$11_@0} b={freeze b$12_@0} ></read $19_@4>
77 + [12] Return read $20_@5
78 +scope3 [7:8]:
79 + - dependency: read $14_@2
80 +scope5 [11:12]:
81 + - dependency: read $19_@4
82 - dependency: freeze a$11_@0
83 - dependency: freeze b$12_@0
84 ```
85
86 +## Reactive Scopes
87 +
88 +```
89 +function Component(
90 + props,
91 +) {
92 + scope @0 [1:10] deps=[] {
93 + [1] Const mutate a$11_@0[1:10] = Array []
94 + [2] Const mutate b$12_@0[1:10] = Object { }
95 + [3] Call mutate foo$4(mutate a$11_@0, mutate b$12_@0)
96 + scope @1 [4:5] deps=[] {
97 + [4] Const mutate $13_@1 = Call mutate foo$4()
98 + }
99 + if (read $13_@1) {
100 + [6] Const mutate $14_@2 = "div"
101 + scope @3 [7:8] deps=[read $14_@2] {
102 + [7] Const mutate _$15_@3 = JSX <read $14_@2 a={freeze a$11_@0} ></read $14_@2>
103 + }
104 + }
105 + [9] Call mutate foo$4(read a$11_@0, mutate b$12_@0)
106 + }
107 + [10] Const mutate $19_@4 = "div"
108 + scope @5 [11:12] deps=[read $19_@4, freeze a$11_@0, freeze b$12_@0] {
109 + [11] Const mutate $20_@5 = JSX <read $19_@4 a={freeze a$11_@0} b={freeze b$12_@0} ></read $19_@4>
110 + }
111 + return read $20_@5
112 +}
113 +
114 +```
115 +
116 ### CFG
117
118 ```mermaid
@@ -80,27 +120,27 @@ flowchart TB
120 %% Basic Blocks
121 subgraph bb0
122 bb0_instrs["
83 - [1] Const mutate a$11_@0[0:10] = Array []
84 - [2] Const mutate b$12_@0[0:10] = Object { }
85 - [3] Call mutate foo$4_@0(mutate a$11_@0, mutate b$12_@0)
86 - [4] Const mutate $13_@0[0:10] = Call mutate foo$4_@0()
123 + [1] Const mutate a$11_@0[1:10] = Array []
124 + [2] Const mutate b$12_@0[1:10] = Object { }
125 + [3] Call mutate foo$4(mutate a$11_@0, mutate b$12_@0)
126 + [4] Const mutate $13_@1 = Call mutate foo$4()
127 "]
88 - bb0_instrs --> bb0_terminal(["If (read $13_@0)"])
128 + bb0_instrs --> bb0_terminal(["If (read $13_@1)"])
129 end
130 subgraph bb2
131 bb2_instrs["
92 - [6] Const mutate $14_@1 = 'div'
93 - [7] Const mutate _$15_@2 = JSX <read $14_@1 a={freeze a$11_@0} ></read $14_@1>
132 + [6] Const mutate $14_@2 = 'div'
133 + [7] Const mutate _$15_@3 = JSX <read $14_@2 a={freeze a$11_@0} ></read $14_@2>
134 "]
135 bb2_instrs --> bb2_terminal(["Goto"])
136 end
137 subgraph bb1
138 bb1_instrs["
99 - [9] Call mutate foo$4_@0(read a$11_@0, mutate b$12_@0)
100 - [10] Const mutate $19_@3 = 'div'
101 - [11] Const mutate $20_@4 = JSX <read $19_@3 a={freeze a$11_@0} b={freeze b$12_@0} ></read $19_@3>
139 + [9] Call mutate foo$4(read a$11_@0, mutate b$12_@0)
140 + [10] Const mutate $19_@4 = 'div'
141 + [11] Const mutate $20_@5 = JSX <read $19_@4 a={freeze a$11_@0} b={freeze b$12_@0} ></read $19_@4>
142 "]
103 - bb1_instrs --> bb1_terminal(["Return read $20_@4"])
143 + bb1_instrs --> bb1_terminal(["Return read $20_@5"])
144 end
145
146 %% Jumps
compiler/forget/src/__tests__/fixtures/hir/ssa-call-jsx.expect.md
+43 -8
@@ -23,6 +23,16 @@ bb0:
23
24 ```
25
26 +## Reactive Scopes
27 +
28 +```
29 +function foo(
30 +) {
31 + return
32 +}
33 +
34 +```
35 +
36 ### CFG
37
38 ```mermaid
@@ -46,12 +56,12 @@ function foo$0() {}
56
57 ```
58 bb0:
49 - [1] Const mutate a$10_@0[0:7] = Array []
50 - [2] Const mutate b$11_@0[0:7] = Object { }
51 - [3] Call mutate foo$4_@0(mutate a$10_@0, mutate b$11_@0)
59 + [1] Const mutate a$10_@0[1:7] = Array []
60 + [2] Const mutate b$11_@0[1:7] = Object { }
61 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
62 [4] Const mutate $12_@1 = "div"
63 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
54 - [6] Call mutate foo$4_@0(read a$10_@0, mutate b$11_@0)
64 + [6] Call mutate foo$4(read a$10_@0, mutate b$11_@0)
65 [7] Const mutate $14_@3 = "div"
66 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
67 [9] Return read $15_@4
@@ -63,6 +73,31 @@ scope4 [8:9]:
73 - dependency: freeze b$11_@0
74 ```
75
76 +## Reactive Scopes
77 +
78 +```
79 +function Component(
80 + props,
81 +) {
82 + scope @0 [1:7] deps=[] {
83 + [1] Const mutate a$10_@0[1:7] = Array []
84 + [2] Const mutate b$11_@0[1:7] = Object { }
85 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
86 + [4] Const mutate $12_@1 = "div"
87 + scope @2 [5:6] deps=[read $12_@1] {
88 + [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
89 + }
90 + [6] Call mutate foo$4(read a$10_@0, mutate b$11_@0)
91 + }
92 + [7] Const mutate $14_@3 = "div"
93 + scope @4 [8:9] deps=[read $14_@3, read a$10_@0, freeze b$11_@0] {
94 + [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
95 + }
96 + return read $15_@4
97 +}
98 +
99 +```
100 +
101 ### CFG
102
103 ```mermaid
@@ -70,12 +105,12 @@ flowchart TB
105 %% Basic Blocks
106 subgraph bb0
107 bb0_instrs["
73 - [1] Const mutate a$10_@0[0:7] = Array []
74 - [2] Const mutate b$11_@0[0:7] = Object { }
75 - [3] Call mutate foo$4_@0(mutate a$10_@0, mutate b$11_@0)
108 + [1] Const mutate a$10_@0[1:7] = Array []
109 + [2] Const mutate b$11_@0[1:7] = Object { }
110 + [3] Call mutate foo$4(mutate a$10_@0, mutate b$11_@0)
111 [4] Const mutate $12_@1 = 'div'
112 [5] Const mutate _$13_@2 = JSX <read $12_@1 a={freeze a$10_@0} ></read $12_@1>
78 - [6] Call mutate foo$4_@0(read a$10_@0, mutate b$11_@0)
113 + [6] Call mutate foo$4(read a$10_@0, mutate b$11_@0)
114 [7] Const mutate $14_@3 = 'div'
115 [8] Const mutate $15_@4 = JSX <read $14_@3 a={read a$10_@0} b={freeze b$11_@0} ></read $14_@3>
116 "]
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-multiple-if.expect.md
+25
@@ -53,6 +53,31 @@ scope6 [13:14]:
53 - dependency: read x$7_@0
54 ```
55
56 +## Reactive Scopes
57 +
58 +```
59 +function foo(
60 +) {
61 + scope @0 [1:13] deps=[] {
62 + [1] Let mutate x$7_@0[1:13] = 1
63 + [2] Const mutate y$8_@1 = 2
64 + [3] Const mutate $9_@2 = 2
65 + [4] Const mutate $10_@3 = Binary read y$8_@1 === read $9_@2
66 + if (read $10_@3) {
67 + [6] Reassign mutate x$7_@0[1:13] = 3
68 + }
69 + [8] Const mutate $12_@4 = 3
70 + [9] Const mutate $14_@5 = Binary read y$8_@1 === read $12_@4
71 + if (read $14_@5) {
72 + [11] Reassign mutate x$7_@0[1:13] = 5
73 + }
74 + }
75 + [13] Const mutate y$18_@6 = read x$7_@0
76 + return
77 +}
78 +
79 +```
80 +
81 ### CFG
82
83 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-complex-single-if.expect.md
+20
@@ -38,6 +38,26 @@ scope4 [8:9]:
38 - dependency: read x$5_@0
39 ```
40
41 +## Reactive Scopes
42 +
43 +```
44 +function foo(
45 +) {
46 + scope @0 [1:8] deps=[] {
47 + [1] Let mutate x$5_@0[1:8] = 1
48 + [2] Const mutate y$6_@1 = 2
49 + [3] Const mutate $7_@2 = 2
50 + [4] Const mutate $8_@3 = Binary read y$6_@1 === read $7_@2
51 + if (read $8_@3) {
52 + [6] Reassign mutate x$5_@0[1:8] = 3
53 + }
54 + }
55 + [8] Const mutate y$11_@4 = read x$5_@0
56 + return
57 +}
58 +
59 +```
60 +
61 ### CFG
62
63 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-for-of.expect.md
+13
@@ -41,6 +41,19 @@ bb2:
41
42 ```
43
44 +## Reactive Scopes
45 +
46 +```
47 +function foo(
48 + cond,
49 +) {
50 + scope @0 [1:2] deps=[] {
51 + [1] Const mutate items$5_@0 = Array []
52 + }
53 +}
54 +
55 +```
56 +
57 ### CFG
58
59 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-for-trivial-update.expect.md
+27
@@ -42,6 +42,33 @@ bb2:
42
43 ```
44
45 +## Reactive Scopes
46 +
47 +```
48 +function foo(
49 +) {
50 + scope @1 [1:13] deps=[] {
51 + [1] Let mutate x$6_@1[1:13] = 1
52 + scope @3 [6:8] deps=[] {
53 + for (
54 + [3] Const mutate i$7_@1[1:13] = 0
55 + ;
56 + [5] Const mutate $8_@1[1:13] = 10
57 + [6] Const mutate $10_@3[6:8] = Binary read i$7_@1 < read $8_@1
58 + read $10_@3
59 + ;
60 + read i$7_@1
61 + ) {
62 + [8] Const mutate $11_@4 = 1
63 + [9] Reassign mutate x$6_@1[1:13] = Binary read x$6_@1 + read $11_@4
64 + }
65 + }
66 + }
67 + return read x$6_@1
68 +}
69 +
70 +```
71 +
72 ### CFG
73
74 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-for.expect.md
+27
@@ -44,6 +44,33 @@ bb2:
44
45 ```
46
47 +## Reactive Scopes
48 +
49 +```
50 +function foo(
51 +) {
52 + scope @1 [1:15] deps=[] {
53 + [1] Let mutate x$7_@1[1:15] = 1
54 + for (
55 + [3] Let mutate i$8_@1[1:15] = 0
56 + ;
57 + [5] Const mutate $9_@1[1:15] = 10
58 + [6] Const mutate $11_@1[1:15] = Binary read i$8_@1 < read $9_@1
59 + read $11_@1
60 + ;
61 + [11] Const mutate $15_@1[1:15] = 1
62 + [12] Reassign mutate i$8_@1[1:15] = Binary read i$8_@1 + read $15_@1
63 + read i$8_@1
64 + ) {
65 + [8] Const mutate $12_@3 = 1
66 + [9] Reassign mutate x$7_@1[1:15] = Binary read x$7_@1 + read $12_@3
67 + }
68 + }
69 + return read x$7_@1
70 +}
71 +
72 +```
73 +
74 ### CFG
75
76 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-if-else.expect.md
+17
@@ -40,6 +40,23 @@ scope3 [6:7]:
40 - dependency: read x$5_@0
41 ```
42
43 +## Reactive Scopes
44 +
45 +```
46 +function foo(
47 +) {
48 + [1] Const mutate x$5_@0 = 1
49 + [2] Const mutate y$6_@1 = 2
50 + if (read y$6_@1) {
51 + [4] Const mutate z$7_@2 = Binary read x$5_@0 + read y$6_@1
52 + } else {
53 + [6] Const mutate z$8_@3 = read x$5_@0
54 + }
55 + return
56 +}
57 +
58 +```
59 +
60 ### CFG
61
62 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-multiple-phis.expect.md
+37
@@ -76,6 +76,43 @@ scope2 [3:20]:
76 - dependency: read $14_@1
77 ```
78
79 +## Reactive Scopes
80 +
81 +```
82 +function foo(
83 + a,
84 + b,
85 + c,
86 + d,
87 +) {
88 + [1] Const mutate x$13_@0 = 0
89 + [2] Const mutate $14_@1 = true
90 + scope @2 [3:20] deps=[read a$9, read b$10, read c$11, read d$12, read $14_@1] {
91 + [3] Let mutate x$18_@2[3:20] = undefined
92 + if (read $14_@1) {
93 + [4] Const mutate $15_@3 = true
94 + if (read $15_@3) {
95 + [6] Reassign mutate x$18_@2[3:20] = read a$9
96 + } else {
97 + [8] Reassign mutate x$18_@2[3:20] = read b$10
98 + }
99 + [10] read x$18_@2
100 + } else {
101 + [12] Const mutate $19_@4 = true
102 + if (read $19_@4) {
103 + [14] Reassign mutate x$18_@2[3:20] = read c$11
104 + } else {
105 + [16] Reassign mutate x$18_@2[3:20] = read d$12
106 + }
107 + [18] read x$18_@2
108 + }
109 + }
110 + [20] read x$18_@2
111 + return
112 +}
113 +
114 +```
115 +
116 ### CFG
117
118 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-loops-no-reassign.expect.md
+28
@@ -56,6 +56,34 @@ scope1 [8:9]:
56 - dependency: read x$9_@0
57 ```
58
59 +## Reactive Scopes
60 +
61 +```
62 +function foo(
63 + a,
64 + b,
65 + c,
66 +) {
67 + [1] Const mutate x$9_@0 = 0
68 + while (
69 + read a$6
70 + ) {
71 + while (
72 + read b$7
73 + ) {
74 + while (
75 + read c$8
76 + ) {
77 + [8] Const mutate $13_@1 = 1
78 + [9] Binary read x$9_@0 + read $13_@1
79 + }
80 + }
81 + }
82 + return read x$9_@0
83 +}
84 +
85 +```
86 +
87 ### CFG
88
89 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-phi.expect.md
+22
@@ -41,6 +41,28 @@ scope0 [1:8]:
41 - dependency: read b$6
42 ```
43
44 +## Reactive Scopes
45 +
46 +```
47 +function foo(
48 + a,
49 + b,
50 + c,
51 +) {
52 + scope @0 [1:8] deps=[read a$5, read c$7, read c$7, read b$6] {
53 + [1] Const mutate x$8_@0[1:8] = read a$5
54 + if (read b$6) {
55 + if (read c$7) {
56 + [4] Reassign mutate x$8_@0[1:8] = read c$7
57 + }
58 + [6] read x$8_@0
59 + }
60 + }
61 + return
62 +}
63 +
64 +```
65 +
66 ### CFG
67
68 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-nested-partial-reassignment.expect.md
+25
@@ -43,6 +43,31 @@ scope0 [1:8]:
43 - dependency: read a$7
44 ```
45
46 +## Reactive Scopes
47 +
48 +```
49 +function foo(
50 + a,
51 + b,
52 + c,
53 + d,
54 + e,
55 +) {
56 + scope @0 [1:8] deps=[read b$8, read d$10, read c$9, read a$7] {
57 + [1] Let mutate x$12_@0[1:8] = null
58 + if (read a$7) {
59 + [3] Reassign mutate x$12_@0[1:8] = read b$8
60 + } else {
61 + if (read c$9) {
62 + [6] Reassign mutate x$12_@0[1:8] = read d$10
63 + }
64 + }
65 + }
66 + return read x$12_@0
67 +}
68 +
69 +```
70 +
71 ### CFG
72
73 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-newexpression.expect.md
+32 -6
@@ -21,6 +21,16 @@ bb0:
21
22 ```
23
24 +## Reactive Scopes
25 +
26 +```
27 +function Foo(
28 +) {
29 + return
30 +}
31 +
32 +```
33 +
34 ### CFG
35
36 ```mermaid
@@ -44,13 +54,29 @@ function Foo$0() {}
54
55 ```
56 bb0:
47 - [1] Const mutate a$7_@0[0:4] = Array []
48 - [2] Const mutate b$8_@0[0:4] = Object { }
49 - [3] Const mutate c$9_@0[0:4] = New mutate Foo$5_@0(mutate a$7_@0, mutate b$8_@0)
57 + [1] Const mutate a$7_@0[1:4] = Array []
58 + [2] Const mutate b$8_@0[1:4] = Object { }
59 + [3] Const mutate c$9_@0[1:4] = New mutate Foo$5(mutate a$7_@0, mutate b$8_@0)
60 [4] Return freeze c$9_@0
61
62 ```
63
64 +## Reactive Scopes
65 +
66 +```
67 +function Component(
68 + props,
69 +) {
70 + scope @0 [1:4] deps=[] {
71 + [1] Const mutate a$7_@0[1:4] = Array []
72 + [2] Const mutate b$8_@0[1:4] = Object { }
73 + [3] Const mutate c$9_@0[1:4] = New mutate Foo$5(mutate a$7_@0, mutate b$8_@0)
74 + }
75 + return freeze c$9_@0
76 +}
77 +
78 +```
79 +
80 ### CFG
81
82 ```mermaid
@@ -58,9 +84,9 @@ flowchart TB
84 %% Basic Blocks
85 subgraph bb0
86 bb0_instrs["
61 - [1] Const mutate a$7_@0[0:4] = Array []
62 - [2] Const mutate b$8_@0[0:4] = Object { }
63 - [3] Const mutate c$9_@0[0:4] = New mutate Foo$5_@0(mutate a$7_@0, mutate b$8_@0)
87 + [1] Const mutate a$7_@0[1:4] = Array []
88 + [2] Const mutate b$8_@0[1:4] = Object { }
89 + [3] Const mutate c$9_@0[1:4] = New mutate Foo$5(mutate a$7_@0, mutate b$8_@0)
90 "]
91 bb0_instrs --> bb0_terminal(["Return freeze c$9_@0"])
92 end
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression-phi.expect.md
+24
@@ -44,6 +44,30 @@ scope3 [10:11]:
44 - dependency: read y$7_@0
45 ```
46
47 +## Reactive Scopes
48 +
49 +```
50 +function foo(
51 +) {
52 + scope @0 [1:10] deps=[] {
53 + [1] Let mutate x$6_@0[1:10] = 1
54 + [2] Let mutate y$7_@0[1:10] = 2
55 + [3] Const mutate $8_@2 = 1
56 + [4] Const mutate $9_@0[1:10] = Binary read x$6_@0 > read $8_@2
57 + if (read $9_@0) {
58 + [6] Reassign mutate x$6_@0[1:10] = 2
59 + } else {
60 + [8] Reassign mutate y$7_@0[1:10] = 3
61 + }
62 + }
63 + scope @3 [10:11] deps=[read x$6_@0, read y$7_@0] {
64 + [10] Const mutate t$14_@3 = Object { x: read x$6_@0, y: read y$7_@0 }
65 + }
66 + return freeze t$14_@3
67 +}
68 +
69 +```
70 +
71 ### CFG
72
73 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-objectexpression.expect.md
+16
@@ -24,6 +24,22 @@ scope2 [3:4]:
24 - dependency: read b$7_@1
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function Component(
31 + props,
32 +) {
33 + [1] Const mutate a$6_@0 = 1
34 + [2] Const mutate b$7_@1 = 2
35 + scope @2 [3:4] deps=[read a$6_@0, read b$7_@1] {
36 + [3] Const mutate x$8_@2 = Object { a: read a$6_@0, b: read b$7_@1 }
37 + }
38 + return freeze x$8_@2
39 +}
40 +
41 +```
42 +
43 ### CFG
44
45 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-alias-mutate-if.expect.md
+38 -14
@@ -22,23 +22,47 @@ function foo(a) {
22
23 ```
24 bb0:
25 - [1] Const mutate b$8_@0[0:11] = Object { }
26 - [2] Const mutate x$9_@0[0:11] = read b$8_@0
25 + [1] Const mutate b$8_@0[1:11] = Object { }
26 + [2] Const mutate x$9_@0[1:11] = read b$8_@0
27 [3] If (read a$7) then:bb2 else:bb3 fallthrough=bb1
28 bb2:
29 predecessor blocks: bb0
30 - [4] Const mutate y$10_@0[0:11] = Object { }
31 - [5] Reassign mutate x$9_@0.y[0:11] = read y$10_@0
30 + [4] Const mutate y$10_@0[1:11] = Object { }
31 + [5] Reassign mutate x$9_@0.y[1:11] = read y$10_@0
32 [6] Goto bb1
33 bb3:
34 predecessor blocks: bb0
35 - [7] Const mutate z$11_@0[0:11] = Object { }
36 - [8] Reassign mutate x$9_@0.z[0:11] = read z$11_@0
35 + [7] Const mutate z$11_@0[1:11] = Object { }
36 + [8] Reassign mutate x$9_@0.z[1:11] = read z$11_@0
37 [9] Goto bb1
38 bb1:
39 predecessor blocks: bb2 bb3
40 - [10] Call mutate mutate$6_@0(mutate b$8_@0)
40 + [10] Call mutate mutate$6(mutate b$8_@0)
41 [11] Return freeze x$9_@0
42 +scope0 [1:11]:
43 + - dependency: read a$7
44 +```
45 +
46 +## Reactive Scopes
47 +
48 +```
49 +function foo(
50 + a,
51 +) {
52 + scope @0 [1:11] deps=[read a$7] {
53 + [1] Const mutate b$8_@0[1:11] = Object { }
54 + [2] Const mutate x$9_@0[1:11] = read b$8_@0
55 + if (read a$7) {
56 + [4] Const mutate y$10_@0[1:11] = Object { }
57 + [5] Reassign mutate x$9_@0.y[1:11] = read y$10_@0
58 + } else {
59 + [7] Const mutate z$11_@0[1:11] = Object { }
60 + [8] Reassign mutate x$9_@0.z[1:11] = read z$11_@0
61 + }
62 + [10] Call mutate mutate$6(mutate b$8_@0)
63 + }
64 + return freeze x$9_@0
65 +}
66
67 ```
68
@@ -49,28 +73,28 @@ flowchart TB
73 %% Basic Blocks
74 subgraph bb0
75 bb0_instrs["
52 - [1] Const mutate b$8_@0[0:11] = Object { }
53 - [2] Const mutate x$9_@0[0:11] = read b$8_@0
76 + [1] Const mutate b$8_@0[1:11] = Object { }
77 + [2] Const mutate x$9_@0[1:11] = read b$8_@0
78 "]
79 bb0_instrs --> bb0_terminal(["If (read a$7)"])
80 end
81 subgraph bb2
82 bb2_instrs["
59 - [4] Const mutate y$10_@0[0:11] = Object { }
60 - [5] Reassign mutate x$9_@0.y[0:11] = read y$10_@0
83 + [4] Const mutate y$10_@0[1:11] = Object { }
84 + [5] Reassign mutate x$9_@0.y[1:11] = read y$10_@0
85 "]
86 bb2_instrs --> bb2_terminal(["Goto"])
87 end
88 subgraph bb3
89 bb3_instrs["
66 - [7] Const mutate z$11_@0[0:11] = Object { }
67 - [8] Reassign mutate x$9_@0.z[0:11] = read z$11_@0
90 + [7] Const mutate z$11_@0[1:11] = Object { }
91 + [8] Reassign mutate x$9_@0.z[1:11] = read z$11_@0
92 "]
93 bb3_instrs --> bb3_terminal(["Goto"])
94 end
95 subgraph bb1
96 bb1_instrs["
73 - [10] Call mutate mutate$6_@0(mutate b$8_@0)
97 + [10] Call mutate mutate$6(mutate b$8_@0)
98 "]
99 bb1_instrs --> bb1_terminal(["Return freeze x$9_@0"])
100 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-if.expect.md
+25
@@ -43,6 +43,31 @@ scope2 [6:7]:
43 - dependency: mutate x$6_@0.z
44 ```
45
46 +## Reactive Scopes
47 +
48 +```
49 +function foo(
50 + a,
51 +) {
52 + scope @0 [1:9] deps=[read a$5] {
53 + [1] Const mutate x$6_@0[1:9] = Object { }
54 + if (read a$5) {
55 + scope @1 [3:4] deps=[mutate x$6_@0.y] {
56 + [3] Const mutate y$7_@1 = Object { }
57 + }
58 + [4] Reassign mutate x$6_@0.y[1:9] = read y$7_@1
59 + } else {
60 + scope @2 [6:7] deps=[mutate x$6_@0.z] {
61 + [6] Const mutate z$8_@2 = Object { }
62 + }
63 + [7] Reassign mutate x$6_@0.z[1:9] = read z$8_@2
64 + }
65 + }
66 + return freeze x$6_@0
67 +}
68 +
69 +```
70 +
71 ### CFG
72
73 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-if.expect.md
+35 -12
@@ -21,22 +21,45 @@ function foo(a) {
21
22 ```
23 bb0:
24 - [1] Const mutate x$7_@0[0:10] = Object { }
24 + [1] Const mutate x$7_@0[1:10] = Object { }
25 [2] If (read a$6) then:bb2 else:bb3 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 - [3] Const mutate y$8_@0[0:10] = Object { }
29 - [4] Reassign mutate x$7_@0.y[0:10] = read y$8_@0
28 + [3] Const mutate y$8_@0[1:10] = Object { }
29 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
30 [5] Goto bb1
31 bb3:
32 predecessor blocks: bb0
33 - [6] Const mutate z$9_@0[0:10] = Object { }
34 - [7] Reassign mutate x$7_@0.z[0:10] = read z$9_@0
33 + [6] Const mutate z$9_@0[1:10] = Object { }
34 + [7] Reassign mutate x$7_@0.z[1:10] = read z$9_@0
35 [8] Goto bb1
36 bb1:
37 predecessor blocks: bb2 bb3
38 - [9] Call mutate mutate$5_@0(mutate x$7_@0)
38 + [9] Call mutate mutate$5(mutate x$7_@0)
39 [10] Return freeze x$7_@0
40 +scope0 [1:10]:
41 + - dependency: read a$6
42 +```
43 +
44 +## Reactive Scopes
45 +
46 +```
47 +function foo(
48 + a,
49 +) {
50 + scope @0 [1:10] deps=[read a$6] {
51 + [1] Const mutate x$7_@0[1:10] = Object { }
52 + if (read a$6) {
53 + [3] Const mutate y$8_@0[1:10] = Object { }
54 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
55 + } else {
56 + [6] Const mutate z$9_@0[1:10] = Object { }
57 + [7] Reassign mutate x$7_@0.z[1:10] = read z$9_@0
58 + }
59 + [9] Call mutate mutate$5(mutate x$7_@0)
60 + }
61 + return freeze x$7_@0
62 +}
63
64 ```
65
@@ -47,27 +70,27 @@ flowchart TB
70 %% Basic Blocks
71 subgraph bb0
72 bb0_instrs["
50 - [1] Const mutate x$7_@0[0:10] = Object { }
73 + [1] Const mutate x$7_@0[1:10] = Object { }
74 "]
75 bb0_instrs --> bb0_terminal(["If (read a$6)"])
76 end
77 subgraph bb2
78 bb2_instrs["
56 - [3] Const mutate y$8_@0[0:10] = Object { }
57 - [4] Reassign mutate x$7_@0.y[0:10] = read y$8_@0
79 + [3] Const mutate y$8_@0[1:10] = Object { }
80 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
81 "]
82 bb2_instrs --> bb2_terminal(["Goto"])
83 end
84 subgraph bb3
85 bb3_instrs["
63 - [6] Const mutate z$9_@0[0:10] = Object { }
64 - [7] Reassign mutate x$7_@0.z[0:10] = read z$9_@0
86 + [6] Const mutate z$9_@0[1:10] = Object { }
87 + [7] Reassign mutate x$7_@0.z[1:10] = read z$9_@0
88 "]
89 bb3_instrs --> bb3_terminal(["Goto"])
90 end
91 subgraph bb1
92 bb1_instrs["
70 - [9] Call mutate mutate$5_@0(mutate x$7_@0)
93 + [9] Call mutate mutate$5(mutate x$7_@0)
94 "]
95 bb1_instrs --> bb1_terminal(["Return freeze x$7_@0"])
96 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate-inside-if.expect.md
+36 -10
@@ -21,26 +21,52 @@ function foo(a) {
21
22 ```
23 bb0:
24 - [1] Const mutate x$7_@0[0:10] = Object { }
24 + [1] Const mutate x$7_@0[1:10] = Object { }
25 [2] If (read a$6) then:bb2 else:bb3 fallthrough=bb1
26 bb2:
27 predecessor blocks: bb0
28 - [3] Const mutate y$8_@0[0:10] = Object { }
29 - [4] Reassign mutate x$7_@0.y[0:10] = read y$8_@0
30 - [5] Call mutate mutate$4_@0(mutate y$8_@0)
28 + [3] Const mutate y$8_@0[1:10] = Object { }
29 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
30 + [5] Call mutate mutate$4(mutate y$8_@0)
31 [6] Goto bb1
32 bb3:
33 predecessor blocks: bb0
34 [7] Const mutate z$9_@1 = Object { }
35 - [8] Reassign mutate x$7_@0.z[0:10] = read z$9_@1
35 + [8] Reassign mutate x$7_@0.z[1:10] = read z$9_@1
36 [9] Goto bb1
37 bb1:
38 predecessor blocks: bb2 bb3
39 [10] Return freeze x$7_@0
40 +scope0 [1:10]:
41 + - dependency: read a$6
42 scope1 [7:8]:
43 - dependency: mutate x$7_@0.z
44 ```
45
46 +## Reactive Scopes
47 +
48 +```
49 +function foo(
50 + a,
51 +) {
52 + scope @0 [1:10] deps=[read a$6] {
53 + [1] Const mutate x$7_@0[1:10] = Object { }
54 + if (read a$6) {
55 + [3] Const mutate y$8_@0[1:10] = Object { }
56 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
57 + [5] Call mutate mutate$4(mutate y$8_@0)
58 + } else {
59 + scope @1 [7:8] deps=[mutate x$7_@0.z] {
60 + [7] Const mutate z$9_@1 = Object { }
61 + }
62 + [8] Reassign mutate x$7_@0.z[1:10] = read z$9_@1
63 + }
64 + }
65 + return freeze x$7_@0
66 +}
67 +
68 +```
69 +
70 ### CFG
71
72 ```mermaid
@@ -48,22 +74,22 @@ flowchart TB
74 %% Basic Blocks
75 subgraph bb0
76 bb0_instrs["
51 - [1] Const mutate x$7_@0[0:10] = Object { }
77 + [1] Const mutate x$7_@0[1:10] = Object { }
78 "]
79 bb0_instrs --> bb0_terminal(["If (read a$6)"])
80 end
81 subgraph bb2
82 bb2_instrs["
57 - [3] Const mutate y$8_@0[0:10] = Object { }
58 - [4] Reassign mutate x$7_@0.y[0:10] = read y$8_@0
59 - [5] Call mutate mutate$4_@0(mutate y$8_@0)
83 + [3] Const mutate y$8_@0[1:10] = Object { }
84 + [4] Reassign mutate x$7_@0.y[1:10] = read y$8_@0
85 + [5] Call mutate mutate$4(mutate y$8_@0)
86 "]
87 bb2_instrs --> bb2_terminal(["Goto"])
88 end
89 subgraph bb3
90 bb3_instrs["
91 [7] Const mutate z$9_@1 = Object { }
66 - [8] Reassign mutate x$7_@0.z[0:10] = read z$9_@1
92 + [8] Reassign mutate x$7_@0.z[1:10] = read z$9_@1
93 "]
94 bb3_instrs --> bb3_terminal(["Goto"])
95 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-alias-mutate.expect.md
+27 -10
@@ -19,15 +19,32 @@ function foo() {
19
20 ```
21 bb0:
22 - [1] Const mutate a$5_@0[0:6] = Object { }
23 - [2] Const mutate x$6_@0[0:6] = read a$5_@0
24 - [3] Const mutate y$7_@0[0:6] = Object { }
25 - [4] Reassign mutate y$7_@0.x[0:6] = read x$6_@0
26 - [5] Call mutate mutate$4_@0(mutate a$5_@0)
22 + [1] Const mutate a$5_@0[1:6] = Object { }
23 + [2] Const mutate x$6_@0[1:6] = read a$5_@0
24 + [3] Const mutate y$7_@0[1:6] = Object { }
25 + [4] Reassign mutate y$7_@0.x[1:6] = read x$6_@0
26 + [5] Call mutate mutate$4(mutate a$5_@0)
27 [6] Return freeze y$7_@0
28
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function foo(
35 +) {
36 + scope @0 [1:6] deps=[] {
37 + [1] Const mutate a$5_@0[1:6] = Object { }
38 + [2] Const mutate x$6_@0[1:6] = read a$5_@0
39 + [3] Const mutate y$7_@0[1:6] = Object { }
40 + [4] Reassign mutate y$7_@0.x[1:6] = read x$6_@0
41 + [5] Call mutate mutate$4(mutate a$5_@0)
42 + }
43 + return freeze y$7_@0
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
@@ -35,11 +52,11 @@ flowchart TB
52 %% Basic Blocks
53 subgraph bb0
54 bb0_instrs["
38 - [1] Const mutate a$5_@0[0:6] = Object { }
39 - [2] Const mutate x$6_@0[0:6] = read a$5_@0
40 - [3] Const mutate y$7_@0[0:6] = Object { }
41 - [4] Reassign mutate y$7_@0.x[0:6] = read x$6_@0
42 - [5] Call mutate mutate$4_@0(mutate a$5_@0)
55 + [1] Const mutate a$5_@0[1:6] = Object { }
56 + [2] Const mutate x$6_@0[1:6] = read a$5_@0
57 + [3] Const mutate y$7_@0[1:6] = Object { }
58 + [4] Reassign mutate y$7_@0.x[1:6] = read x$6_@0
59 + [5] Call mutate mutate$4(mutate a$5_@0)
60 "]
61 bb0_instrs --> bb0_terminal(["Return freeze y$7_@0"])
62 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-call.expect.md
+18
@@ -24,6 +24,24 @@ scope1 [2:5]:
24 - dependency: read x$4_@0
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function foo(
31 +) {
32 + scope @0 [1:2] deps=[] {
33 + [1] Const mutate x$4_@0 = Array []
34 + }
35 + scope @1 [2:5] deps=[read x$4_@0] {
36 + [2] Const mutate y$5_@1[2:5] = Object { x: read x$4_@0 }
37 + [3] Const mutate $6_@1[2:5] = Array []
38 + [4] Call mutate y$5_@1.x.push(mutate $6_@1)
39 + }
40 + return freeze y$5_@1
41 +}
42 +
43 +```
44 +
45 ### CFG
46
47 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-property-mutate-2.expect.md
+24 -8
@@ -16,14 +16,30 @@ function foo() {
16
17 ```
18 bb0:
19 - [1] Const mutate x$4_@0[0:5] = Array []
20 - [2] Const mutate y$5_@0[0:5] = Object { }
21 - [3] Reassign mutate y$5_@0.x[0:5] = read x$4_@0
22 - [4] Call mutate mutate$3_@0(mutate x$4_@0)
19 + [1] Const mutate x$4_@0[1:5] = Array []
20 + [2] Const mutate y$5_@0[1:5] = Object { }
21 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
22 + [4] Call mutate mutate$3(mutate x$4_@0)
23 [5] Return freeze y$5_@0
24
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function foo(
31 +) {
32 + scope @0 [1:5] deps=[] {
33 + [1] Const mutate x$4_@0[1:5] = Array []
34 + [2] Const mutate y$5_@0[1:5] = Object { }
35 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
36 + [4] Call mutate mutate$3(mutate x$4_@0)
37 + }
38 + return freeze y$5_@0
39 +}
40 +
41 +```
42 +
43 ### CFG
44
45 ```mermaid
@@ -31,10 +47,10 @@ flowchart TB
47 %% Basic Blocks
48 subgraph bb0
49 bb0_instrs["
34 - [1] Const mutate x$4_@0[0:5] = Array []
35 - [2] Const mutate y$5_@0[0:5] = Object { }
36 - [3] Reassign mutate y$5_@0.x[0:5] = read x$4_@0
37 - [4] Call mutate mutate$3_@0(mutate x$4_@0)
50 + [1] Const mutate x$4_@0[1:5] = Array []
51 + [2] Const mutate y$5_@0[1:5] = Object { }
52 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
53 + [4] Call mutate mutate$3(mutate x$4_@0)
54 "]
55 bb0_instrs --> bb0_terminal(["Return freeze y$5_@0"])
56 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-mutate-alias.expect.md
+27 -10
@@ -19,15 +19,32 @@ function foo() {
19
20 ```
21 bb0:
22 - [1] Const mutate a$5_@0[0:6] = Object { }
23 - [2] Const mutate y$6_@0[0:6] = read a$5_@0
24 - [3] Const mutate x$7_@0[0:6] = Array []
25 - [4] Reassign mutate y$6_@0.x[0:6] = read x$7_@0
26 - [5] Call mutate mutate$4_@0(mutate a$5_@0)
22 + [1] Const mutate a$5_@0[1:6] = Object { }
23 + [2] Const mutate y$6_@0[1:6] = read a$5_@0
24 + [3] Const mutate x$7_@0[1:6] = Array []
25 + [4] Reassign mutate y$6_@0.x[1:6] = read x$7_@0
26 + [5] Call mutate mutate$4(mutate a$5_@0)
27 [6] Return freeze y$6_@0
28
29 ```
30
31 +## Reactive Scopes
32 +
33 +```
34 +function foo(
35 +) {
36 + scope @0 [1:6] deps=[] {
37 + [1] Const mutate a$5_@0[1:6] = Object { }
38 + [2] Const mutate y$6_@0[1:6] = read a$5_@0
39 + [3] Const mutate x$7_@0[1:6] = Array []
40 + [4] Reassign mutate y$6_@0.x[1:6] = read x$7_@0
41 + [5] Call mutate mutate$4(mutate a$5_@0)
42 + }
43 + return freeze y$6_@0
44 +}
45 +
46 +```
47 +
48 ### CFG
49
50 ```mermaid
@@ -35,11 +52,11 @@ flowchart TB
52 %% Basic Blocks
53 subgraph bb0
54 bb0_instrs["
38 - [1] Const mutate a$5_@0[0:6] = Object { }
39 - [2] Const mutate y$6_@0[0:6] = read a$5_@0
40 - [3] Const mutate x$7_@0[0:6] = Array []
41 - [4] Reassign mutate y$6_@0.x[0:6] = read x$7_@0
42 - [5] Call mutate mutate$4_@0(mutate a$5_@0)
55 + [1] Const mutate a$5_@0[1:6] = Object { }
56 + [2] Const mutate y$6_@0[1:6] = read a$5_@0
57 + [3] Const mutate x$7_@0[1:6] = Array []
58 + [4] Reassign mutate y$6_@0.x[1:6] = read x$7_@0
59 + [5] Call mutate mutate$4(mutate a$5_@0)
60 "]
61 bb0_instrs --> bb0_terminal(["Return freeze y$6_@0"])
62 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property-mutate.expect.md
+24 -8
@@ -16,14 +16,30 @@ function foo() {
16
17 ```
18 bb0:
19 - [1] Const mutate x$4_@0[0:5] = Array []
20 - [2] Const mutate y$5_@0[0:5] = Object { }
21 - [3] Reassign mutate y$5_@0.x[0:5] = read x$4_@0
22 - [4] Call mutate mutate$3_@0(mutate y$5_@0)
19 + [1] Const mutate x$4_@0[1:5] = Array []
20 + [2] Const mutate y$5_@0[1:5] = Object { }
21 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
22 + [4] Call mutate mutate$3(mutate y$5_@0)
23 [5] Return freeze y$5_@0
24
25 ```
26
27 +## Reactive Scopes
28 +
29 +```
30 +function foo(
31 +) {
32 + scope @0 [1:5] deps=[] {
33 + [1] Const mutate x$4_@0[1:5] = Array []
34 + [2] Const mutate y$5_@0[1:5] = Object { }
35 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
36 + [4] Call mutate mutate$3(mutate y$5_@0)
37 + }
38 + return freeze y$5_@0
39 +}
40 +
41 +```
42 +
43 ### CFG
44
45 ```mermaid
@@ -31,10 +47,10 @@ flowchart TB
47 %% Basic Blocks
48 subgraph bb0
49 bb0_instrs["
34 - [1] Const mutate x$4_@0[0:5] = Array []
35 - [2] Const mutate y$5_@0[0:5] = Object { }
36 - [3] Reassign mutate y$5_@0.x[0:5] = read x$4_@0
37 - [4] Call mutate mutate$3_@0(mutate y$5_@0)
50 + [1] Const mutate x$4_@0[1:5] = Array []
51 + [2] Const mutate y$5_@0[1:5] = Object { }
52 + [3] Reassign mutate y$5_@0.x[1:5] = read x$4_@0
53 + [4] Call mutate mutate$3(mutate y$5_@0)
54 "]
55 bb0_instrs --> bb0_terminal(["Return freeze y$5_@0"])
56 end
compiler/forget/src/__tests__/fixtures/hir/ssa-property.expect.md
+17
@@ -23,6 +23,23 @@ scope1 [2:4]:
23 - dependency: read x$3_@0
24 ```
25
26 +## Reactive Scopes
27 +
28 +```
29 +function foo(
30 +) {
31 + scope @0 [1:2] deps=[] {
32 + [1] Const mutate x$3_@0 = Array []
33 + }
34 + scope @1 [2:4] deps=[read x$3_@0] {
35 + [2] Const mutate y$4_@1[2:4] = Object { }
36 + [3] Reassign mutate y$4_@1.x[2:4] = read x$3_@0
37 + }
38 + return freeze y$4_@1
39 +}
40 +
41 +```
42 +
43 ### CFG
44
45 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-reassign.expect.md
+17
@@ -29,6 +29,23 @@ scope3 [4:5]:
29 - dependency: read c$7
30 ```
31
32 +## Reactive Scopes
33 +
34 +```
35 +function foo(
36 + a,
37 + b,
38 + c,
39 +) {
40 + [1] Const mutate x$8_@0 = 0
41 + [2] Const mutate x$9_@1 = read a$5
42 + [3] Const mutate x$10_@2 = read b$6
43 + [4] Const mutate x$11_@3 = read c$7
44 + return read x$11_@3
45 +}
46 +
47 +```
48 +
49 ### CFG
50
51 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-return.expect.md
+18
@@ -31,6 +31,24 @@ bb1:
31
32 ```
33
34 +## Reactive Scopes
35 +
36 +```
37 +function foo(
38 +) {
39 + scope @0 [1:7] deps=[] {
40 + [1] Let mutate x$4_@0[1:7] = 1
41 + [2] Const mutate $5_@1 = 1
42 + [3] Const mutate $6_@0[1:7] = Binary read x$4_@0 === read $5_@1
43 + if (read $6_@0) {
44 + [5] Reassign mutate x$4_@0[1:7] = 2
45 + }
46 + }
47 + return read x$4_@0
48 +}
49 +
50 +```
51 +
52 ### CFG
53
54 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-shadowing.expect.md
+36 -4
@@ -25,6 +25,16 @@ bb0:
25
26 ```
27
28 +## Reactive Scopes
29 +
30 +```
31 +function log(
32 +) {
33 + return
34 +}
35 +
36 +```
37 +
38 ### CFG
39
40 ```mermaid
@@ -53,7 +63,7 @@ bb0:
63 bb2:
64 predecessor blocks: bb0
65 [3] Const mutate str$7_@1 = "other test"
56 - [4] Call mutate log$4_@2(read str$7_@1)
66 + [4] Call mutate log$4(read str$7_@1)
67 [5] Goto bb1
68 bb3:
69 predecessor blocks: bb0
@@ -61,8 +71,30 @@ bb3:
71 [7] Goto bb1
72 bb1:
73 predecessor blocks: bb2 bb3
64 - [8] Call mutate log$4_@2(read str$6_@0)
74 + [8] Call mutate log$4(read str$6_@0)
75 [9] Return
76 +scope0 [1:8]:
77 + - dependency: read cond$5
78 +```
79 +
80 +## Reactive Scopes
81 +
82 +```
83 +function Foo(
84 + cond,
85 +) {
86 + scope @0 [1:8] deps=[read cond$5] {
87 + [1] Let mutate str$6_@0[1:8] = ""
88 + if (read cond$5) {
89 + [3] Const mutate str$7_@1 = "other test"
90 + [4] Call mutate log$4(read str$7_@1)
91 + } else {
92 + [6] Reassign mutate str$6_@0[1:8] = "fallthrough test"
93 + }
94 + }
95 + [8] Call mutate log$4(read str$6_@0)
96 + return
97 +}
98
99 ```
100
@@ -80,7 +112,7 @@ flowchart TB
112 subgraph bb2
113 bb2_instrs["
114 [3] Const mutate str$7_@1 = 'other test'
83 - [4] Call mutate log$4_@2(read str$7_@1)
115 + [4] Call mutate log$4(read str$7_@1)
116 "]
117 bb2_instrs --> bb2_terminal(["Goto"])
118 end
@@ -92,7 +124,7 @@ flowchart TB
124 end
125 subgraph bb1
126 bb1_instrs["
95 - [8] Call mutate log$4_@2(read str$6_@0)
127 + [8] Call mutate log$4(read str$6_@0)
128 "]
129 bb1_instrs --> bb1_terminal(["Return"])
130 end
compiler/forget/src/__tests__/fixtures/hir/ssa-sibling-phis.expect.md
+39
@@ -78,6 +78,45 @@ scope5 [13:18]:
78 - dependency: read $19_@4
79 ```
80
81 +## Reactive Scopes
82 +
83 +```
84 +function foo(
85 + a,
86 + b,
87 + c,
88 + d,
89 +) {
90 + [1] Const mutate x$13_@0 = 0
91 + [2] Const mutate $14_@1 = true
92 + if (read $14_@1) {
93 + [4] Const mutate $15_@2 = true
94 + scope @3 [5:10] deps=[read a$9, read b$10, read $15_@2] {
95 + [5] Let mutate x$16_@3[5:10] = undefined
96 + if (read $15_@2) {
97 + [6] Reassign mutate x$16_@3[5:10] = read a$9
98 + } else {
99 + [8] Reassign mutate x$16_@3[5:10] = read b$10
100 + }
101 + }
102 + [10] read x$16_@3
103 + } else {
104 + [12] Const mutate $19_@4 = true
105 + scope @5 [13:18] deps=[read c$11, read d$12, read $19_@4] {
106 + [13] Let mutate x$20_@5[13:18] = undefined
107 + if (read $19_@4) {
108 + [14] Reassign mutate x$20_@5[13:18] = read c$11
109 + } else {
110 + [16] Reassign mutate x$20_@5[13:18] = read d$12
111 + }
112 + }
113 + [18] read x$20_@5
114 + }
115 + return
116 +}
117 +
118 +```
119 +
120 ### CFG
121
122 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-simple-phi.expect.md
+22
@@ -46,6 +46,28 @@ scope4 [9:10]:
46 - dependency: read y$8_@3
47 ```
48
49 +## Reactive Scopes
50 +
51 +```
52 +function foo(
53 +) {
54 + [1] Const mutate y$5_@0 = 2
55 + [2] Const mutate $6_@1 = 1
56 + [3] Const mutate $7_@2 = Binary read y$5_@0 > read $6_@1
57 + scope @3 [4:9] deps=[read $7_@2] {
58 + [4] Let mutate y$8_@3[4:9] = undefined
59 + if (read $7_@2) {
60 + [5] Reassign mutate y$8_@3[4:9] = 1
61 + } else {
62 + [7] Reassign mutate y$8_@3[4:9] = 2
63 + }
64 + }
65 + [9] Const mutate x$11_@4 = read y$8_@3
66 + return
67 +}
68 +
69 +```
70 +
71 ### CFG
72
73 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-simple.expect.md
+12
@@ -19,6 +19,18 @@ bb0:
19
20 ```
21
22 +## Reactive Scopes
23 +
24 +```
25 +function foo(
26 +) {
27 + [1] Const mutate x$3_@0 = 1
28 + [2] Const mutate y$4_@1 = 2
29 + return
30 +}
31 +
32 +```
33 +
34 ### CFG
35
36 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-single-if.expect.md
+15
@@ -32,6 +32,21 @@ scope2 [4:5]:
32 - dependency: read y$5_@1
33 ```
34
35 +## Reactive Scopes
36 +
37 +```
38 +function foo(
39 +) {
40 + [1] Const mutate x$4_@0 = 1
41 + [2] Const mutate y$5_@1 = 2
42 + if (read y$5_@1) {
43 + [4] Const mutate z$6_@2 = Binary read x$4_@0 + read y$5_@1
44 + }
45 + return
46 +}
47 +
48 +```
49 +
50 ### CFG
51
52 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-switch.expect.md
+35
@@ -76,6 +76,41 @@ scope9 [16:17]:
76 - dependency: read x$16_@5
77 ```
78
79 +## Reactive Scopes
80 +
81 +```
82 +function foo(
83 +) {
84 + [1] Const mutate x$10_@0 = 1
85 + [2] Const mutate $11_@1 = 2
86 + [3] Const mutate $12_@2 = Binary read x$10_@0 === read $11_@1
87 + [4] Const mutate $13_@3 = 1
88 + [5] Const mutate $14_@4 = Binary read x$10_@0 === read $13_@3
89 + scope @5 [6:16] deps=[read x$10_@0] {
90 + [6] Let mutate x$16_@5[6:16] = undefined
91 + switch (read x$10_@0) {
92 + case read $14_@4: {
93 + [7] Const mutate $15_@6 = 1
94 + [8] Reassign mutate x$16_@5[6:16] = Binary read x$10_@0 + read $15_@6
95 + break bb1
96 + }
97 + case read $12_@2: {
98 + [10] Const mutate $17_@7 = 2
99 + [11] Reassign mutate x$16_@5[6:16] = Binary read x$10_@0 + read $17_@7
100 + break bb1
101 + }
102 + default: {
103 + [13] Const mutate $19_@8 = 3
104 + [14] Reassign mutate x$16_@5[6:16] = Binary read x$10_@0 + read $19_@8
105 + }
106 + }
107 + }
108 + [16] Const mutate y$22_@9 = read x$16_@5
109 + return
110 +}
111 +
112 +```
113 +
114 ### CFG
115
116 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-throw.expect.md
+18
@@ -30,6 +30,24 @@ bb1:
30
31 ```
32
33 +## Reactive Scopes
34 +
35 +```
36 +function foo(
37 +) {
38 + scope @0 [1:7] deps=[] {
39 + [1] Let mutate x$4_@0[1:7] = 1
40 + [2] Const mutate $5_@1 = 1
41 + [3] Const mutate $6_@0[1:7] = Binary read x$4_@0 === read $5_@1
42 + if (read $6_@0) {
43 + [5] Reassign mutate x$4_@0[1:7] = 2
44 + }
45 + }
46 + throw read x$4_@0
47 +}
48 +
49 +```
50 +
51 ### CFG
52
53 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-while-no-reassign.expect.md
+23
@@ -38,6 +38,29 @@ scope3 [6:7]:
38 - dependency: read x$5_@0
39 ```
40
41 +## Reactive Scopes
42 +
43 +```
44 +function foo(
45 +) {
46 + [1] Const mutate x$5_@0 = 1
47 + scope @1 [3:6] deps=[] {
48 + scope @2 [4:6] deps=[read x$5_@0] {
49 + while (
50 + [3] Const mutate $6_@1[3:6] = 10
51 + [4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
52 + read $8_@2
53 + ) {
54 + [6] Const mutate $9_@3 = 1
55 + [7] Binary read x$5_@0 + read $9_@3
56 + }
57 + }
58 + }
59 + return read x$5_@0
60 +}
61 +
62 +```
63 +
64 ### CFG
65
66 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/ssa-while.expect.md
+21
@@ -35,6 +35,27 @@ bb2:
35
36 ```
37
38 +## Reactive Scopes
39 +
40 +```
41 +function foo(
42 +) {
43 + scope @0 [1:9] deps=[] {
44 + [1] Let mutate x$5_@0[1:9] = 1
45 + while (
46 + [3] Const mutate $6_@0[1:9] = 10
47 + [4] Const mutate $8_@0[1:9] = Binary read x$5_@0 < read $6_@0
48 + read $8_@0
49 + ) {
50 + [6] Const mutate $9_@2 = 1
51 + [7] Reassign mutate x$5_@0[1:9] = Binary read x$5_@0 + read $9_@2
52 + }
53 + }
54 + return read x$5_@0
55 +}
56 +
57 +```
58 +
59 ### CFG
60
61 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+41
@@ -69,6 +69,47 @@ scope6 [14:15]:
69 - dependency: read child$19_@5
70 ```
71
72 +## Reactive Scopes
73 +
74 +```
75 +function Component(
76 + props,
77 +) {
78 + scope @1 [1:12] deps=[] {
79 + [1] Const mutate x$10_@1[1:12] = Array []
80 + [2] Let mutate y$11_@1[1:12] = undefined
81 + [3] Const mutate $12_@2 = false
82 + [4] Const mutate $13_@3 = true
83 + [5] Const mutate $14_@4 = 1
84 + switch (read props$9.p0) {
85 + case read $14_@4: {
86 + break bb1
87 + }
88 + case read $13_@3: {
89 + [7] Call mutate x$10_@1.push(read props$9.p2)
90 + [8] Reassign mutate y$11_@1[1:12] = Array []
91 + break bb1
92 + }
93 + default: {
94 + break bb1
95 + }
96 + case read $12_@2: {
97 + [10] Reassign mutate y$11_@1[1:12] = read x$10_@1
98 + }
99 + }
100 + }
101 + scope @5 [12:13] deps=[read Component$0, freeze x$10_@1, read y$11_@1.push, read props$9.p4] {
102 + [12] Const mutate child$19_@5 = JSX <read Component$0 data={freeze x$10_@1} ></read Component$0>
103 + }
104 + [13] Call read y$11_@1.push(read props$9.p4)
105 + scope @6 [14:15] deps=[read Component$0, freeze y$11_@1, read child$19_@5] {
106 + [14] Const mutate $22_@6 = JSX <read Component$0 data={freeze y$11_@1} >{read child$19_@5}</read Component$0>
107 + }
108 + return read $22_@6
109 +}
110 +
111 +```
112 +
113 ### CFG
114
115 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/switch-with-fallthrough.expect.md
+43
@@ -82,6 +82,49 @@ bb1:
82
83 ```
84
85 +## Reactive Scopes
86 +
87 +```
88 +function foo(
89 + x,
90 +) {
91 + [1] Const mutate y$10_@0 = undefined
92 + [2] Const mutate $11_@1 = 5
93 + [3] Const mutate $12_@2 = 4
94 + [4] Const mutate $13_@3 = 3
95 + [5] Const mutate $14_@4 = 2
96 + [6] Const mutate $15_@5 = 1
97 + [7] Const mutate $16_@6 = 0
98 + switch (read x$9) {
99 + case read $16_@6: {
100 + [9] Const mutate y$17_@7 = 0
101 + }
102 + case read $15_@5: {
103 + [11] Const mutate y$18_@8 = 1
104 + break bb1
105 + }
106 + case read $14_@4: {
107 + break bb1
108 + }
109 + case read $13_@3: {
110 + [13] Const mutate y$19_@9 = 3
111 + break bb1
112 + }
113 + case read $12_@2: {
114 + [15] Const mutate y$20_@10 = 4
115 + }
116 + case read $11_@1: {
117 + [17] Const mutate y$21_@11 = 5
118 + }
119 + default: {
120 + [19] Const mutate y$22_@12 = 0
121 + }
122 + }
123 + return
124 +}
125 +
126 +```
127 +
128 ### CFG
129
130 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+36
@@ -64,6 +64,42 @@ scope6 [14:15]:
64 - dependency: read child$19_@5
65 ```
66
67 +## Reactive Scopes
68 +
69 +```
70 +function Component(
71 + props,
72 +) {
73 + scope @1 [1:12] deps=[] {
74 + [1] Const mutate x$9_@1[1:12] = Array []
75 + [2] Let mutate y$10_@1[1:12] = undefined
76 + [3] Const mutate $11_@2 = false
77 + [4] Const mutate $12_@3 = true
78 + switch (read props$8.p0) {
79 + case read $12_@3: {
80 + [6] Call mutate x$9_@1.push(read props$8.p2)
81 + [7] Call mutate x$9_@1.push(read props$8.p3)
82 + scope @4 [8:9] deps=[] {
83 + [8] Const mutate y$13_@4 = Array []
84 + }
85 + }
86 + case read $11_@2: {
87 + [10] Reassign mutate y$10_@1[1:12] = read x$9_@1
88 + }
89 + }
90 + }
91 + scope @5 [12:13] deps=[read Component$0, freeze x$9_@1, read y$10_@1.push, read props$8.p4] {
92 + [12] Const mutate child$19_@5 = JSX <read Component$0 data={freeze x$9_@1} ></read Component$0>
93 + }
94 + [13] Call read y$10_@1.push(read props$8.p4)
95 + scope @6 [14:15] deps=[read Component$0, read y$10_@1, read child$19_@5] {
96 + [14] Const mutate $23_@6 = JSX <read Component$0 data={read y$10_@1} >{read child$19_@5}</read Component$0>
97 + }
98 + return read $23_@6
99 +}
100 +
101 +```
102 +
103 ### CFG
104
105 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/transitive-alias-fields.expect.md
+36 -16
@@ -21,18 +21,38 @@ function component() {
21
22 ```
23 bb0:
24 - [1] Const mutate x$6_@0[0:9] = Object { }
25 - [2] Const mutate p$7_@0[0:9] = Object { }
26 - [3] Const mutate q$8_@0[0:9] = Object { }
27 - [4] Const mutate y$9_@0[0:9] = Object { }
28 - [5] Reassign mutate x$6_@0.y[0:9] = read y$9_@0
29 - [6] Reassign mutate p$7_@0.y[0:9] = read x$6_@0.y
30 - [7] Reassign mutate q$8_@0.y[0:9] = read p$7_@0.y
31 - [8] Call mutate mutate$5_@0(mutate q$8_@0)
24 + [1] Const mutate x$6_@0[1:9] = Object { }
25 + [2] Const mutate p$7_@0[1:9] = Object { }
26 + [3] Const mutate q$8_@0[1:9] = Object { }
27 + [4] Const mutate y$9_@0[1:9] = Object { }
28 + [5] Reassign mutate x$6_@0.y[1:9] = read y$9_@0
29 + [6] Reassign mutate p$7_@0.y[1:9] = read x$6_@0.y
30 + [7] Reassign mutate q$8_@0.y[1:9] = read p$7_@0.y
31 + [8] Call mutate mutate$5(mutate q$8_@0)
32 [9] Return
33
34 ```
35
36 +## Reactive Scopes
37 +
38 +```
39 +function component(
40 +) {
41 + scope @0 [1:9] deps=[] {
42 + [1] Const mutate x$6_@0[1:9] = Object { }
43 + [2] Const mutate p$7_@0[1:9] = Object { }
44 + [3] Const mutate q$8_@0[1:9] = Object { }
45 + [4] Const mutate y$9_@0[1:9] = Object { }
46 + [5] Reassign mutate x$6_@0.y[1:9] = read y$9_@0
47 + [6] Reassign mutate p$7_@0.y[1:9] = read x$6_@0.y
48 + [7] Reassign mutate q$8_@0.y[1:9] = read p$7_@0.y
49 + [8] Call mutate mutate$5(mutate q$8_@0)
50 + }
51 + return
52 +}
53 +
54 +```
55 +
56 ### CFG
57
58 ```mermaid
@@ -40,14 +60,14 @@ flowchart TB
60 %% Basic Blocks
61 subgraph bb0
62 bb0_instrs["
43 - [1] Const mutate x$6_@0[0:9] = Object { }
44 - [2] Const mutate p$7_@0[0:9] = Object { }
45 - [3] Const mutate q$8_@0[0:9] = Object { }
46 - [4] Const mutate y$9_@0[0:9] = Object { }
47 - [5] Reassign mutate x$6_@0.y[0:9] = read y$9_@0
48 - [6] Reassign mutate p$7_@0.y[0:9] = read x$6_@0.y
49 - [7] Reassign mutate q$8_@0.y[0:9] = read p$7_@0.y
50 - [8] Call mutate mutate$5_@0(mutate q$8_@0)
63 + [1] Const mutate x$6_@0[1:9] = Object { }
64 + [2] Const mutate p$7_@0[1:9] = Object { }
65 + [3] Const mutate q$8_@0[1:9] = Object { }
66 + [4] Const mutate y$9_@0[1:9] = Object { }
67 + [5] Reassign mutate x$6_@0.y[1:9] = read y$9_@0
68 + [6] Reassign mutate p$7_@0.y[1:9] = read x$6_@0.y
69 + [7] Reassign mutate q$8_@0.y[1:9] = read p$7_@0.y
70 + [8] Call mutate mutate$5(mutate q$8_@0)
71 "]
72 bb0_instrs --> bb0_terminal(["Return"])
73 end
compiler/forget/src/__tests__/fixtures/hir/while-break.expect.md
+17
@@ -25,6 +25,23 @@ bb2:
25
26 ```
27
28 +## Reactive Scopes
29 +
30 +```
31 +function foo(
32 + a,
33 + b,
34 +) {
35 + while (
36 + read a$3
37 + ) {
38 + break
39 + }
40 + return read b$4
41 +}
42 +
43 +```
44 +
45 ### CFG
46
47 ```mermaid
compiler/forget/src/__tests__/fixtures/hir/while-conditional-continue.expect.md
+23
@@ -40,6 +40,29 @@ bb2:
40
41 ```
42
43 +## Reactive Scopes
44 +
45 +```
46 +function foo(
47 + a,
48 + b,
49 + c,
50 + d,
51 +) {
52 + while (
53 + read a$5
54 + ) {
55 + if (read b$6) {
56 + continue
57 + }
58 + [5] Call read c$7()
59 + }
60 + [7] Call read d$8()
61 + return
62 +}
63 +
64 +```
65 +
66 ### CFG
67
68 ```mermaid
compiler/forget/src/__tests__/hir-test.ts
+26 -13
@@ -14,9 +14,11 @@ import { wasmFolder } from "@hpcc-js/wasm";
14 import invariant from "invariant";
15 import path from "path";
16 import prettier from "prettier";
17 +import { buildReactiveFunction } from "../HIR/BuildReactiveFunction";
18 import { toggleLogging } from "../HIR/logger";
19 import run from "../HIR/Pipeline";
20 import { printFunction } from "../HIR/PrintHIR";
21 +import { printReactiveFunction } from "../HIR/PrintReactiveFunction";
22 import visualizeHIRMermaid from "../HIR/VisualizeHIRMermaid";
23 import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
24
@@ -49,7 +51,7 @@ describe("React Forget (HIR version)", () => {
51 }
52 }
53
52 - let items: Array<[string, string, string]> | null = null;
54 + let items: Array<TestOutput> | null = null;
55 let error: Error | null = null;
56 if (options.debug) {
57 toggleLogging(options.debug);
@@ -101,29 +103,37 @@ ${wrapWithTripleBackticks(error.message)}
103 `;
104 }
105
104 -function formatOutput(items: Array<[string, string, string]>): Array<string> {
105 - return items.map(([hir, text, visualization]) => {
106 +function formatOutput(items: Array<TestOutput>): Array<string> {
107 + return items.map(({ ir, js, mermaid, scopes }) => {
108 return `
109 ## HIR
110
109 -${wrapWithTripleBackticks(hir)}
111 +${wrapWithTripleBackticks(ir)}
112 +
113 +## Reactive Scopes
114 +
115 +${wrapWithTripleBackticks(scopes)}
116
117 ### CFG
118
113 -${wrapWithTripleBackticks(visualization, "mermaid")}
119 +${wrapWithTripleBackticks(mermaid, "mermaid")}
120
121 ## Code
122
117 -${wrapWithTripleBackticks(text, "javascript")}
123 +${wrapWithTripleBackticks(js, "javascript")}
124 `.trim();
125 });
126 }
127
122 -function transform(
123 - text: string,
124 - file: string
125 -): Array<[string, string, string]> {
126 - const items: Array<[string, string, string]> = [];
128 +type TestOutput = {
129 + ir: string;
130 + js: string;
131 + mermaid: string;
132 + scopes: string;
133 +};
134 +
135 +function transform(text: string, file: string): Array<TestOutput> {
136 + const items: Array<TestOutput> = [];
137 const ast = parser.parse(text, {
138 sourceFilename: file,
139 plugins: ["typescript", "jsx"],
@@ -142,15 +152,18 @@ function transform(
152 codegen: true,
153 });
154
155 + const reactiveFunction = buildReactiveFunction(ir);
156 + const scopes = printReactiveFunction(reactiveFunction);
157 +
158 const textHIR = printFunction(ir);
146 - const visualization = visualizeHIRMermaid(ir);
159 + const mermaid = visualizeHIRMermaid(ir);
160
161 invariant(ast !== null, "ast is null when codegen option is enabled");
162 const text = prettier.format(generate(ast).code.replace("\n\n", "\n"), {
163 semi: true,
164 parser: "babel-ts",
165 });
153 - items.push([textHIR, text, visualization]);
166 + items.push({ ir: textHIR, js: text, scopes, mermaid });
167 },
168 },
169 });
compiler/forget/src/index.ts
+6 -1
@@ -25,6 +25,7 @@ import { parse } from "@babel/parser";
25 import traverse, { NodePath } from "@babel/traverse";
26 import * as t from "@babel/types";
27 import { lower } from "./HIR/BuildHIR";
28 +import { buildReactiveFunction } from "./HIR/BuildReactiveFunction";
29 import codegen from "./HIR/Codegen";
30 import { eliminateRedundantPhi } from "./HIR/EliminateRedundantPhi";
31 import enterSSA from "./HIR/EnterSSA";
@@ -35,7 +36,8 @@ import { inferReactiveScopes } from "./HIR/InferReactiveScopes";
36 import { inferReactiveScopeVariables } from "./HIR/InferReactiveScopeVariables";
37 import inferReferenceEffects from "./HIR/InferReferenceEffects";
38 import { leaveSSA } from "./HIR/LeaveSSA";
38 -import printHIR from "./HIR/PrintHIR";
39 +import printHIR, { printFunction } from "./HIR/PrintHIR";
40 +import { printReactiveFunction } from "./HIR/PrintReactiveFunction";
41
42 function parseFunctions(
43 source: string
@@ -68,6 +70,9 @@ export const HIR = {
70 inferReactiveScopeDependencies,
71 inferReactiveScopeVariables,
72 inferReactiveScopes,
73 + buildReactiveFunction,
74 + printReactiveFunction,
75 + printFunction,
76 printHIR,
77 Environment,
78 leaveSSA,