@samitouri / QOS-React-2 / commits / 0000ab6ca4

[new-arch] HIR cleanup per discussion

* Renames `Capability` to `Effect` and clarifies the kinds as Freeze, Read, and Mutate. The real intent of what we're inferring/representing is "what effect does this reference to the value have on its value". Ie freeze freezes the value, mutate mutates it. * Consolidates Capability and EffectKind into Effect * Renames some properties on Place for clarity * Adds `value: ValueKind` to Place, which indicates the (merged) kind of the value at that place at that point in the program. * Changes HIR printing to show the effect and the value kind * Simplifies some inference logic

Joseph Savona committed Oct 13, 2022 at 11:23 UTC 0000ab6ca4ac5a983ffea36503ebf1f046c7f789
28 files changed +394 -415
compiler/forget/src/HIR/BuildHIR.ts
+21 -21
@@ -10,7 +10,7 @@ import * as t from "@babel/types";
10 import { assertExhaustive } from "../Common/utils";
11 import { invariant } from "../CompilerError";
12 import {
13 - Capability,
13 + Effect,
14 HIRFunction,
15 IfTerminal,
16 InstructionKind,
@@ -60,9 +60,9 @@ export function lower(func: NodePath<t.Function>): HIRFunction {
60 const identifier = builder.resolveIdentifier(param);
61 const place: Place = {
62 kind: "Identifier",
63 - value: identifier,
63 + identifier,
64 memberPath: null,
65 - capability: Capability.Unknown,
65 + effect: Effect.Unknown,
66 path: null as any,
67 };
68 params.push(place);
@@ -843,9 +843,9 @@ function lowerExpression(
843 );
844 const place: Place = {
845 kind: "Identifier",
846 - value: object.value,
846 + identifier: object.identifier,
847 memberPath: [...(object.memberPath ?? []), property.node.name],
848 - capability: Capability.Unknown,
848 + effect: Effect.Unknown,
849 path: exprPath,
850 };
851 return place;
@@ -907,9 +907,9 @@ function lowerConditional(
907 ): Place {
908 const place: Place = {
909 kind: "Identifier",
910 - value: builder.makeTemporary(),
910 + identifier: builder.makeTemporary(),
911 memberPath: null,
912 - capability: Capability.Readonly,
912 + effect: Effect.Read,
913 path: null as any, // TODO
914 };
915 // Block for code following the if
@@ -970,18 +970,18 @@ function lowerJsxElementName(
970 const identifier = builder.resolveIdentifier(binding);
971 const place: Place = {
972 kind: "Identifier",
973 - value: identifier,
973 + identifier: identifier,
974 memberPath: null,
975 - capability: Capability.Unknown,
975 + effect: Effect.Unknown,
976 path: exprPath,
977 };
978 return place;
979 } else {
980 const place: Place = {
981 kind: "Identifier",
982 - value: builder.makeTemporary(),
982 + identifier: builder.makeTemporary(),
983 memberPath: null,
984 - capability: Capability.Unknown,
984 + effect: Effect.Unknown,
985 path: exprPath,
986 };
987 builder.push({
@@ -1012,9 +1012,9 @@ function lowerJsxElement(
1012 } else if (exprPath.isJSXText()) {
1013 const place: Place = {
1014 kind: "Identifier",
1015 - value: builder.makeTemporary(),
1015 + identifier: builder.makeTemporary(),
1016 memberPath: null,
1017 - capability: Capability.Unknown,
1017 + effect: Effect.Unknown,
1018 path: exprPath,
1019 };
1020 builder.push({
@@ -1026,9 +1026,9 @@ function lowerJsxElement(
1026 } else {
1027 const place: Place = {
1028 kind: "Identifier",
1029 - value: builder.makeTemporary(),
1029 + identifier: builder.makeTemporary(),
1030 memberPath: null,
1031 - capability: Capability.Unknown,
1031 + effect: Effect.Unknown,
1032 path: exprPath,
1033 };
1034 builder.push({
@@ -1050,9 +1050,9 @@ function lowerExpressionToPlace(
1050 }
1051 const place: Place = {
1052 kind: "Identifier",
1053 - value: builder.makeTemporary(),
1053 + identifier: builder.makeTemporary(),
1054 memberPath: null,
1055 - capability: Capability.Unknown,
1055 + effect: Effect.Unknown,
1056 path: exprPath,
1057 };
1058 builder.push({
@@ -1080,9 +1080,9 @@ function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
1080 const identifier = builder.resolveIdentifier(binding);
1081 const place: Place = {
1082 kind: "Identifier",
1083 - value: identifier,
1083 + identifier: identifier,
1084 memberPath: null,
1085 - capability: Capability.Unknown,
1085 + effect: Effect.Unknown,
1086 path: exprPath,
1087 };
1088 return place;
@@ -1099,9 +1099,9 @@ function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
1099 );
1100 const place: Place = {
1101 kind: "Identifier",
1102 - value: object.value,
1102 + identifier: object.identifier,
1103 memberPath: [...(object.memberPath ?? []), propertyPath.node.name],
1104 - capability: Capability.Unknown,
1104 + effect: Effect.Unknown,
1105 path: exprPath,
1106 };
1107 return place;
compiler/forget/src/HIR/Codegen.ts
+7 -7
@@ -50,7 +50,7 @@ export default function codegen(fn: HIRFunction): t.Function {
50 t.isFunctionDeclaration(node),
51 "todo: handle other than function declaration"
52 );
53 - const params = fn.params.map((param) => convertIdentifier(param.value));
53 + const params = fn.params.map((param) => convertIdentifier(param.identifier));
54 return t.functionDeclaration(
55 fn.id !== null ? convertIdentifier(fn.id) : null,
56 params,
@@ -273,11 +273,11 @@ function writeInstr(cx: Context, instr: Instruction, body: Array<t.Statement>) {
273 }
274 if (instr.lvalue !== null) {
275 if (
276 - instr.lvalue.place.value.name === null &&
276 + instr.lvalue.place.identifier.name === null &&
277 instr.lvalue.place.memberPath === null
278 ) {
279 // Temporary value: don't immediately emit, instead save the value to refer to later
280 - cx.temp.set(instr.lvalue.place.value.id, value);
280 + cx.temp.set(instr.lvalue.place.identifier.id, value);
281 } else {
282 switch (instr.lvalue.kind) {
283 case InstructionKind.Const: {
@@ -338,7 +338,7 @@ function codegenJsxElement(
338 }
339
340 function codegenLVal(lval: LValue): t.LVal {
341 - return convertIdentifier(lval.place.value);
341 + return convertIdentifier(lval.place.identifier);
342 }
343
344 function codegenValue(
@@ -363,13 +363,13 @@ function codegenValue(
363 function codegenPlace(cx: Context, place: Place): t.Expression {
364 todoInvariant(place.kind === "Identifier", "support scope values");
365 if (place.memberPath === null) {
366 - let tmp = cx.temp.get(place.value.id);
366 + let tmp = cx.temp.get(place.identifier.id);
367 if (tmp != null) {
368 return tmp;
369 }
370 - return convertIdentifier(place.value);
370 + return convertIdentifier(place.identifier);
371 } else {
372 - let object: t.Expression = convertIdentifier(place.value);
372 + let object: t.Expression = convertIdentifier(place.identifier);
373 for (const path of place.memberPath) {
374 object = t.memberExpression(object, t.identifier(path));
375 }
compiler/forget/src/HIR/HIR.ts
+20 -9
@@ -200,9 +200,9 @@ export type InstructionData =
200 */
201 export type Place = {
202 kind: "Identifier";
203 - value: Identifier;
203 + identifier: Identifier;
204 memberPath: Array<string> | null;
205 - capability: Capability;
205 + effect: Effect;
206 path: NodePath;
207 };
208
@@ -224,17 +224,28 @@ export type Identifier = {
224 };
225
226 /**
227 - * The capability with which a value is modified.
227 + * Distinguish between different kinds of values relevant to inference purposes:
228 + * see the main docblock for the module for details.
229 */
229 -export enum Capability {
230 +export enum ValueKind {
231 + MaybeFrozen = "maybefrozen",
232 + Frozen = "frozen",
233 + Immutable = "immutable",
234 + Mutable = "mutable",
235 +}
236 +
237 +/**
238 + * The effect with which a value is modified.
239 + */
240 +export enum Effect {
241 // Default value: not allowed after lifetime inference
242 Unknown = "<unknown>",
232 - // The value is made frozen at this point.
243 + // This reference freezes the value (corresponds to a place where codegen should emit a freeze instruction)
244 Freeze = "freeze",
234 - // The value is not modified at this point.
235 - Readonly = "readonly",
236 - // The value is modified at this point.
237 - Mutable = "mutable",
245 + // This reference reads the value
246 + Read = "read",
247 + // This reference may write to (mutate) the value
248 + Mutate = "mutate",
249 }
250
251 /**
compiler/forget/src/HIR/InferReferenceCapability.ts
+89 -118
@@ -10,19 +10,20 @@ import { invariant } from "../CompilerError";
10 import {
11 BasicBlock,
12 BlockId,
13 - Capability,
13 + Effect,
14 HIRFunction,
15 IdentifierId,
16 Instruction,
17 InstructionValue,
18 Place,
19 Terminal,
20 + ValueKind,
21 } from "./HIR";
22 import { mapTerminalSuccessors } from "./HIRBuilder";
23 import { printMixedHIR } from "./PrintHIR";
24
25 /**
25 - * For every usage of a value in the given function, infers the capability or action
26 + * For every usage of a value in the given function, infers the effect or action
27 * taken at that reference. Each reference is inferred as exactly one of:
28 * - freeze: this usage freezes the value, ie converts it to frozen. This is only inferred
29 * when the value *may* not already be frozen.
@@ -50,7 +51,7 @@ import { printMixedHIR } from "./PrintHIR";
51 * is created.
52 *
53 * Internally, the inference tracks the approximate type of value held by each variable,
53 - * and iterates over the control flow graph. The inferred capability of reach reference is
54 + * and iterates over the control flow graph. The inferred effect of reach reference is
55 * a combination of the operation performed (ie, assignment into an object mutably uses the
56 * object; an if condition reads the condition) and the type of the value. The types of values
57 * are:
@@ -70,9 +71,9 @@ export default function inferReferenceCapability(fn: HIRFunction) {
71 const id: Place = {
72 kind: "Identifier",
73 memberPath: null,
73 - value: fn.id as any,
74 + identifier: fn.id as any,
75 path: null as any, // TODO
75 - capability: Capability.Freeze,
76 + effect: Effect.Freeze,
77 };
78 const value: InstructionValue = {
79 kind: "Primitive",
@@ -83,20 +84,13 @@ export default function inferReferenceCapability(fn: HIRFunction) {
84 initialEnvironment.define(id, value);
85
86 for (const param of fn.params) {
86 - const place: Place = {
87 - kind: "Identifier",
88 - memberPath: null,
89 - value: param.value,
90 - path: null as any, // TODO
91 - capability: Capability.Freeze,
92 - };
87 const value: InstructionValue = {
88 kind: "Primitive",
89 path: null as any, // TODO
90 value: undefined,
91 };
92 initialEnvironment.initialize(value, ValueKind.Frozen);
99 - initialEnvironment.define(place, value);
93 + initialEnvironment.define(param, value);
94 }
95
96 // Map of blocks to the last (merged) incoming environment that was processed
@@ -154,11 +148,6 @@ export default function inferReferenceCapability(fn: HIRFunction) {
148 }
149 }
150
157 -type QueueEntry = {
158 - blockId: BlockId;
159 - environment: Environment;
160 -};
161 -
151 /**
152 * Maintains a mapping of top-level variables to the kind of value they hold
153 */
@@ -201,7 +190,7 @@ class Environment {
190 * Lookup the kind of the given @param value.
191 */
192 kind(place: Place): ValueKind {
204 - const values = this.#variables.get(place.value.id);
193 + const values = this.#variables.get(place.identifier.id);
194 invariant(
195 values != null,
196 `Expected value kind to be initialized at '${String(place.path)}'`
@@ -219,14 +208,14 @@ class Environment {
208 * Updates the value at @param place to point to the same value as @param value.
209 */
210 alias(place: Place, value: Place) {
222 - const values = this.#variables.get(value.value.id);
211 + const values = this.#variables.get(value.identifier.id);
212 invariant(
213 values != null,
214 `Expected value to be populated at '${String(value.path)}' in '${String(
215 value.path.parentPath
216 )}'`
217 );
229 - this.#variables.set(place.value.id, new Set(values));
218 + this.#variables.set(place.identifier.id, new Set(values));
219 }
220
221 /**
@@ -243,12 +232,12 @@ class Environment {
232 value.path?.parentPath
233 )}'`
234 );
246 - this.#variables.set(place.value.id, new Set([value]));
235 + this.#variables.set(place.identifier.id, new Set([value]));
236 }
237
238 /**
239 * Records that a given Place was accessed with the given kind and:
251 - * - Updates the capability of @param place based on the kind of value
240 + * - Updates the effect of @param place based on the kind of value
241 * and the kind of reference (@param effectKind).
242 * - Updates the value kind to reflect the effect of the reference.
243 *
@@ -258,56 +247,51 @@ class Environment {
247 * Similarly, a freeze reference is converted to readonly if the
248 * value is already frozen or is immutable.
249 */
261 - reference(place: Place, effectKind: EffectKind) {
262 - const values = this.#variables.get(place.value.id);
250 + reference(place: Place, effectKind: Effect) {
251 + const values = this.#variables.get(place.identifier.id);
252 if (values === undefined) {
264 - place.capability =
265 - effectKind === EffectKind.Write
266 - ? Capability.Mutable
267 - : Capability.Readonly;
253 + place.effect = effectKind === Effect.Mutate ? Effect.Mutate : Effect.Read;
254 return;
255 }
270 - let capability: Capability | null = null;
256 + let valueKind: ValueKind | null = null;
257 + for (const value of values) {
258 + const kind = this.#values.get(value)!;
259 + valueKind = valueKind !== null ? mergeValues(valueKind, kind) : kind;
260 + }
261 + invariant(valueKind !== null, "Expected a value to be set");
262 + let effect: Effect | null = null;
263 switch (effectKind) {
272 - case EffectKind.Freeze: {
273 - values.forEach((value) => {
274 - const valueKind = this.#values.get(value)!;
275 - if (
276 - valueKind === ValueKind.Mutable ||
277 - valueKind === ValueKind.MaybeFrozen
278 - ) {
279 - this.#values.set(value, ValueKind.Frozen);
280 - capability = Capability.Freeze;
281 - }
282 - });
283 - capability = capability ?? Capability.Readonly;
264 + case Effect.Freeze: {
265 + if (
266 + valueKind === ValueKind.Mutable ||
267 + valueKind === ValueKind.MaybeFrozen
268 + ) {
269 + effect = Effect.Freeze;
270 + valueKind = ValueKind.Frozen;
271 + values.forEach((value) => this.#values.set(value, ValueKind.Frozen));
272 + } else {
273 + effect = Effect.Read;
274 + }
275 break;
276 }
286 - case EffectKind.Write: {
287 - let maybeFrozen = false;
288 - let maybeMutable = false;
289 - values.forEach((value) => {
290 - const valueKind = this.#values.get(value)!;
291 - if (
292 - valueKind === ValueKind.Frozen ||
293 - valueKind === ValueKind.MaybeFrozen
294 - ) {
295 - maybeFrozen = true;
296 - } else if (valueKind === ValueKind.Mutable) {
297 - maybeMutable = true;
298 - }
299 - });
300 - capability = maybeFrozen
301 - ? Capability.Readonly
302 - : maybeMutable
303 - ? Capability.Mutable
304 - : Capability.Readonly;
277 + case Effect.Mutate: {
278 + if (valueKind === ValueKind.Mutable) {
279 + effect = Effect.Mutate;
280 + } else {
281 + effect = Effect.Read;
282 + }
283 break;
284 }
307 - case EffectKind.Read: {
308 - capability = Capability.Readonly;
285 + case Effect.Read: {
286 + effect = Effect.Read;
287 break;
288 }
289 + case Effect.Unknown: {
290 + invariant(
291 + false,
292 + "Unexpected unknown effect, expected to infer a precise effect kind"
293 + );
294 + }
295 default: {
296 assertExhaustive(
297 effectKind,
@@ -315,8 +299,8 @@ class Environment {
299 );
300 }
301 }
318 - invariant(capability !== null, "Expected capability to be set");
319 - place.capability = capability;
302 + invariant(effect !== null, "Expected effect to be set");
303 + place.effect = effect;
304 }
305
306 /**
@@ -448,8 +432,21 @@ class Environment {
432 * └─────────────────────────┘
433 *
434 * == Join Lattice ==
451 - * - immutable | frozen => frozen
435 + * - immutable | mutable => mutable
436 + * The justification is that immutable and mutable values are different types,
437 + * and functions can introspect them to tell the difference (if the argument
438 + * is null return early, else if its an object mutate it).
439 * - frozen | mutable => maybe-frozen
440 + * Frozen values are indistinguishable from mutable values at runtime, so callers
441 + * cannot dynamically avoid mutation of "frozen" values. If a value could be
442 + * frozen we have to distinguish it from a mutable value. But it also isn't known
443 + * frozen yet, so we distinguish as maybe-frozen.
444 + * - immutable | frozen => frozen
445 + * This is subtle and falls out of the above rules. If a value could be any of
446 + * immutable, mutable, or frozen, then at runtime it could either be a primitive
447 + * or a reference type, and callers can't distinguish frozen or not for reference
448 + * types. To ensure that any sequence of joins btw those three states yields the
449 + * correct maybe-frozen, these two have to produce a frozen value.
450 * - <any> | maybe-frozen => maybe-frozen
451 *
452 * ┌──────────────────────────┐
@@ -486,26 +483,6 @@ function mergeValues(a: ValueKind, b: ValueKind): ValueKind {
483 }
484 }
485
489 -/**
490 - * Distinguish between different kinds of values relevant to inference purposes:
491 - * see the main docblock for the module for details.
492 - */
493 -enum ValueKind {
494 - MaybeFrozen = "MaybeFrozen",
495 - Frozen = "Frozen",
496 - Immutable = "Immutable",
497 - Mutable = "Mutable",
498 -}
499 -
500 -/**
501 - * Distinguish between different kinds of references.
502 - */
503 -enum EffectKind {
504 - Write = "Write",
505 - Read = "Read",
506 - Freeze = "Freeze",
507 -}
508 -
486 /**
487 * Iterates over the given @param block, defining variables and
488 * recording references on the @param env according to JS semantics.
@@ -517,27 +494,27 @@ function inferBlock(env: Environment, block: BasicBlock) {
494 switch (instrValue.kind) {
495 case "BinaryExpression": {
496 valueKind = ValueKind.Immutable;
520 - env.reference(instrValue.left, EffectKind.Read);
521 - env.reference(instrValue.right, EffectKind.Read);
497 + env.reference(instrValue.left, Effect.Read);
498 + env.reference(instrValue.right, Effect.Read);
499 break;
500 }
501 case "ArrayExpression": {
502 valueKind = ValueKind.Mutable;
503 for (const element of instrValue.elements) {
527 - env.reference(element, EffectKind.Read);
504 + env.reference(element, Effect.Read);
505 }
506 break;
507 }
508 case "NewExpression": {
509 valueKind = ValueKind.Mutable;
533 - env.reference(instrValue.callee, EffectKind.Write);
510 + env.reference(instrValue.callee, Effect.Mutate);
511 for (const arg of instrValue.args) {
535 - env.reference(arg, EffectKind.Write);
512 + env.reference(arg, Effect.Mutate);
513 }
514 break;
515 }
516 case "CallExpression": {
540 - let effectKind = EffectKind.Write;
517 + let effectKind = Effect.Mutate;
518 valueKind = ValueKind.Mutable;
519 const hook = parseHookCall(instrValue.callee);
520 if (hook !== null) {
@@ -555,7 +532,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
532 // Object construction captures but does not modify the key/property values
533 if (instrValue.properties !== null) {
534 for (const [_key, value] of Object.entries(instrValue.properties)) {
558 - env.reference(value, EffectKind.Read);
535 + env.reference(value, Effect.Read);
536 }
537 }
538 break;
@@ -563,7 +540,7 @@ function inferBlock(env: Environment, block: BasicBlock) {
540 case "UnaryExpression": {
541 // TODO check that value must be a primitive, or make conditional based on the operator
542 valueKind = ValueKind.Immutable;
566 - env.reference(instrValue.value, EffectKind.Read);
543 + env.reference(instrValue.value, Effect.Read);
544 break;
545 }
546 case "OtherStatement": {
@@ -573,13 +550,13 @@ function inferBlock(env: Environment, block: BasicBlock) {
550 }
551 case "JsxExpression": {
552 valueKind = ValueKind.Frozen;
576 - env.reference(instrValue.tag, EffectKind.Freeze);
553 + env.reference(instrValue.tag, Effect.Freeze);
554 for (const [_prop, value] of Object.entries(instrValue.props)) {
578 - env.reference(value, EffectKind.Freeze);
555 + env.reference(value, Effect.Freeze);
556 }
557 if (instrValue.children !== null) {
558 for (const child of instrValue.children) {
582 - env.reference(child, EffectKind.Freeze);
559 + env.reference(child, Effect.Freeze);
560 }
561 }
562 break;
@@ -590,10 +567,10 @@ function inferBlock(env: Environment, block: BasicBlock) {
567 break;
568 }
569 case "Identifier": {
593 - env.reference(instrValue, EffectKind.Read);
570 + env.reference(instrValue, Effect.Read);
571 const lvalue = instr.lvalue;
572 if (lvalue !== null) {
596 - lvalue.place.capability = Capability.Mutable;
573 + lvalue.place.effect = Effect.Mutate;
574 if (
575 lvalue.place.memberPath === null &&
576 instrValue.memberPath === null
@@ -606,10 +583,10 @@ function inferBlock(env: Environment, block: BasicBlock) {
583 env.define(lvalue.place, instrValue);
584 } else if (instrValue.memberPath === null) {
585 // no-op: `a.b.c = d`
609 - env.reference(lvalue.place, EffectKind.Write);
586 + env.reference(lvalue.place, Effect.Mutate);
587 } else {
588 // no-op: `a.b.c = d.e.f`
612 - env.reference(lvalue.place, EffectKind.Write);
589 + env.reference(lvalue.place, Effect.Mutate);
590 }
591 }
592 continue;
@@ -623,30 +600,30 @@ function inferBlock(env: Environment, block: BasicBlock) {
600 if (instr.lvalue.place.memberPath === null) {
601 env.define(instr.lvalue.place, instrValue);
602 } else {
626 - env.reference(instr.lvalue.place, EffectKind.Write);
603 + env.reference(instr.lvalue.place, Effect.Mutate);
604 }
628 - instr.lvalue.place.capability = Capability.Mutable;
605 + instr.lvalue.place.effect = Effect.Mutate;
606 }
607 }
608 switch (block.terminal.kind) {
609 case "throw": {
633 - env.reference(block.terminal.value, EffectKind.Freeze);
610 + env.reference(block.terminal.value, Effect.Freeze);
611 break;
612 }
613 case "return": {
614 if (block.terminal.value !== null) {
638 - env.reference(block.terminal.value, EffectKind.Freeze);
615 + env.reference(block.terminal.value, Effect.Freeze);
616 }
617 break;
618 }
619 case "if": {
643 - env.reference(block.terminal.test, EffectKind.Read);
620 + env.reference(block.terminal.test, Effect.Read);
621 break;
622 }
623 case "switch": {
624 for (const case_ of block.terminal.cases) {
625 if (case_.test !== null) {
649 - env.reference(case_.test, EffectKind.Read);
626 + env.reference(case_.test, Effect.Read);
627 }
628 }
629 break;
@@ -663,18 +640,12 @@ function inferBlock(env: Environment, block: BasicBlock) {
640 }
641 }
642
666 -const GLOBALS: Map<string, ValueKind> = new Map([
667 - ["Map", ValueKind.Mutable],
668 - ["Set", ValueKind.Mutable],
669 - ["Math.max", ValueKind.Immutable],
670 -]);
671 -
643 const HOOKS: Map<string, Hook> = new Map([
644 [
645 "useState",
646 {
647 kind: "State",
677 - effectKind: EffectKind.Freeze,
648 + effectKind: Effect.Freeze,
649 valueKind: ValueKind.Frozen,
650 },
651 ],
@@ -682,21 +653,21 @@ const HOOKS: Map<string, Hook> = new Map([
653 "useRef",
654 {
655 kind: "Ref",
685 - effectKind: EffectKind.Read,
656 + effectKind: Effect.Read,
657 valueKind: ValueKind.Mutable,
658 },
659 ],
660 ]);
661
662 type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" };
692 -type Hook = HookKind & { effectKind: EffectKind; valueKind: ValueKind };
663 +type Hook = HookKind & { effectKind: Effect; valueKind: ValueKind };
664
665 function parseHookCall(place: Place): Hook | null {
666 if (place.memberPath !== null) {
667 // Hook calls must be statically resolved
668 return null;
669 }
699 - const name = place.value.name;
670 + const name = place.identifier.name;
671 if (name === null || !name.match(/^_?use/)) {
672 return null;
673 }
@@ -706,7 +677,7 @@ function parseHookCall(place: Place): Hook | null {
677 }
678 return {
679 kind: "Custom",
709 - effectKind: EffectKind.Freeze,
680 + effectKind: Effect.Freeze,
681 valueKind: ValueKind.Frozen,
682 };
683 }
compiler/forget/src/HIR/PrintHIR.ts
+7 -1
@@ -231,7 +231,13 @@ export function printLValue(lval: LValue): string {
231 }
232
233 export function printPlace(place: Place): string {
234 - const items = [place.capability, " ", place.value.name, "$", place.value.id];
234 + const items = [
235 + place.effect,
236 + " ",
237 + place.identifier.name,
238 + "$",
239 + place.identifier.id,
240 + ];
241 if (place.memberPath != null) {
242 for (const path of place.memberPath) {
243 items.push(".");
compiler/forget/src/HIR/ScopeAnalysis.ts
+1 -10
@@ -6,7 +6,6 @@
6 */
7
8 import {
9 - Capability,
9 HIRFunction,
10 makeScopeId,
11 ReactFunction,
@@ -61,15 +60,7 @@ export default function analyzeScopes(fn: HIRFunction): ReactFunction {
60 const returnScopeId = makeScopeId(0);
61 const scopes: Map<ScopeId, ReactiveScope> = new Map();
62 scopes.set(returnScopeId, {
64 - inputs: new Set(
65 - fn.params.map((param) => ({
66 - kind: "Identifier",
67 - value: param.value,
68 - memberPath: null,
69 - capability: Capability.Freeze,
70 - path: null as any,
71 - }))
72 - ),
63 + inputs: new Set([...fn.params]),
64 outputs: new Set(),
65 instructions: fn.body,
66 });
compiler/forget/src/__tests__/fixtures/hir/call.expect.md
+9 -9
@@ -34,15 +34,15 @@ function foo$0() {
34
35 ```
36 bb0:
37 - Const mutable a$2 = Array []
38 - Const mutable b$3 = Object { }
39 - Call mutable foo$4(mutable a$2, mutable b$3)
40 - Const mutable $6 = "div"
41 - Let mutable _$5 = JSX <readonly $6 a={freeze a$2} ></readonly $6>
42 - Call mutable foo$4(mutable b$3)
43 - Const mutable $7 = "div"
44 - Const mutable $8 = JSX <readonly $7 a={readonly a$2} b={freeze b$3} ></readonly $7>
45 - Return readonly $8
37 + Const mutate a$2 = Array []
38 + Const mutate b$3 = Object { }
39 + Call mutate foo$4(mutate a$2, mutate b$3)
40 + Const mutate $6 = "div"
41 + Let mutate _$5 = JSX <read $6 a={freeze a$2} ></read $6>
42 + Call mutate foo$4(mutate b$3)
43 + Const mutate $7 = "div"
44 + Const mutate $8 = JSX <read $7 a={read a$2} b={freeze b$3} ></read $7>
45 + Return read $8
46 ```
47
48 ## Code
compiler/forget/src/__tests__/fixtures/hir/component.expect.md
+29 -29
@@ -35,45 +35,45 @@ function Component(props) {
35
36 ```
37 bb0:
38 - Const mutable items$2 = readonly props$1.items
39 - Const mutable maxItems$3 = readonly props$1.maxItems
40 - Const mutable renderedItems$4 = Array []
41 - Const mutable seen$5 = New mutable Set$6()
42 - Const mutable $9 = 0
43 - Const mutable max$7 = Call mutable Math$8.max(readonly $9, readonly maxItems$3)
38 + Const mutate items$2 = read props$1.items
39 + Const mutate maxItems$3 = read props$1.maxItems
40 + Const mutate renderedItems$4 = Array []
41 + Const mutate seen$5 = New mutate Set$6()
42 + Const mutate $9 = 0
43 + Const mutate max$7 = Call mutate Math$8.max(read $9, read maxItems$3)
44 Goto bb1
45 bb1:
46 - If (readonly items$2) then:bb3 else:bb2
46 + If (read items$2) then:bb3 else:bb2
47 bb3:
48 - Const mutable $11 = null
49 - Const mutable $12 = Binary readonly item$10 == readonly $11
50 - If (readonly $12) then:bb8 else:bb9
48 + Const mutate $11 = null
49 + Const mutate $12 = Binary read item$10 == read $11
50 + If (read $12) then:bb8 else:bb9
51 bb8:
52 - Const mutable $13 = readonly $12
52 + Const mutate $13 = read $12
53 Goto bb7
54 bb9:
55 - Const mutable $13 = Call mutable seen$5.has(mutable item$10)
55 + Const mutate $13 = Call mutate seen$5.has(mutate item$10)
56 Goto bb7
57 bb7:
58 - If (readonly $13) then:bb1 else:bb4
58 + If (read $13) then:bb1 else:bb4
59 bb4:
60 - Call mutable seen$5.add(mutable item$10)
61 - Const mutable $14 = "div"
62 - Const mutable $15 = JSX <readonly $14>{readonly item$10}</readonly $14>
63 - Call mutable renderedItems$4.push(readonly $15)
64 - Const mutable $16 = Binary readonly renderedItems$4.length >= readonly max$7
65 - If (readonly $16) then:bb2 else:bb1
60 + Call mutate seen$5.add(mutate item$10)
61 + Const mutate $14 = "div"
62 + Const mutate $15 = JSX <read $14>{read item$10}</read $14>
63 + Call mutate renderedItems$4.push(read $15)
64 + Const mutate $16 = Binary read renderedItems$4.length >= read max$7
65 + If (read $16) then:bb2 else:bb1
66 bb2:
67 - Const mutable count$17 = readonly renderedItems$4.length
68 - Const mutable $18 = "div"
69 - Const mutable $19 = "\n "
70 - Const mutable $20 = "h1"
71 - Const mutable $21 = " Items"
72 - Const mutable $22 = JSX <readonly $20>{freeze count$17}{readonly $21}</readonly $20>
73 - Const mutable $23 = "\n "
74 - Const mutable $24 = "\n "
75 - Const mutable $25 = JSX <readonly $18>{readonly $19}{readonly $22}{readonly $23}{freeze renderedItems$4}{readonly $24}</readonly $18>
76 - Return readonly $25
67 + Const mutate count$17 = read renderedItems$4.length
68 + Const mutate $18 = "div"
69 + Const mutate $19 = "\n "
70 + Const mutate $20 = "h1"
71 + Const mutate $21 = " Items"
72 + Const mutate $22 = JSX <read $20>{freeze count$17}{read $21}</read $20>
73 + Const mutate $23 = "\n "
74 + Const mutate $24 = "\n "
75 + Const mutate $25 = JSX <read $18>{read $19}{read $22}{read $23}{freeze renderedItems$4}{read $24}</read $18>
76 + Return read $25
77 ```
78
79 ## Code
compiler/forget/src/__tests__/fixtures/hir/conditional-break.expect.md
+28 -28
@@ -78,14 +78,14 @@ function Component(props) {
78
79 ```
80 bb0:
81 - Const mutable a_DEBUG$2 = Array []
82 - Call mutable a_DEBUG$2.push(readonly props$1.a)
83 - If (readonly props$1.b) then:bb2 else:bb1
81 + Const mutate a_DEBUG$2 = Array []
82 + Call mutate a_DEBUG$2.push(read props$1.a)
83 + If (read props$1.b) then:bb2 else:bb1
84 bb2:
85 - Const mutable $3 = null
86 - Return readonly $3
85 + Const mutate $3 = null
86 + Return read $3
87 bb1:
88 - Call mutable a_DEBUG$2.push(readonly props$1.d)
88 + Call mutate a_DEBUG$2.push(read props$1.d)
89 Return freeze a_DEBUG$2
90 ```
91
@@ -107,14 +107,14 @@ function Component$0(props$1) {
107
108 ```
109 bb0:
110 - Const mutable a$2 = Array []
111 - Call mutable a$2.push(readonly props$1.a)
112 - If (readonly props$1.b) then:bb2 else:bb1
110 + Const mutate a$2 = Array []
111 + Call mutate a$2.push(read props$1.a)
112 + If (read props$1.b) then:bb2 else:bb1
113 bb2:
114 - Call mutable a$2.push(readonly props$1.c)
114 + Call mutate a$2.push(read props$1.c)
115 Goto bb1
116 bb1:
117 - Call mutable a$2.push(readonly props$1.d)
117 + Call mutate a$2.push(read props$1.d)
118 Return freeze a$2
119 ```
120
@@ -137,15 +137,15 @@ function Component$0(props$1) {
137
138 ```
139 bb0:
140 - Const mutable a$2 = Array []
141 - Call mutable a$2.push(readonly props$1.a)
142 - If (readonly props$1.b) then:bb2 else:bb1
140 + Const mutate a$2 = Array []
141 + Call mutate a$2.push(read props$1.a)
142 + If (read props$1.b) then:bb2 else:bb1
143 bb2:
144 - Call mutable a$2.push(readonly props$1.c)
145 - Const mutable $3 = null
146 - Return readonly $3
144 + Call mutate a$2.push(read props$1.c)
145 + Const mutate $3 = null
146 + Return read $3
147 bb1:
148 - Call mutable a$2.push(readonly props$1.d)
148 + Call mutate a$2.push(read props$1.d)
149 Return freeze a$2
150 ```
151
@@ -168,14 +168,14 @@ function Component$0(props$1) {
168
169 ```
170 bb0:
171 - Const mutable a$2 = Array []
172 - Call mutable a$2.push(readonly props$1.a)
173 - If (readonly props$1.b) then:bb2 else:bb1
171 + Const mutate a$2 = Array []
172 + Call mutate a$2.push(read props$1.a)
173 + If (read props$1.b) then:bb2 else:bb1
174 bb2:
175 - Call mutable a$2.push(readonly props$1.c)
175 + Call mutate a$2.push(read props$1.c)
176 Return freeze a$2
177 bb1:
178 - Call mutable a$2.push(readonly props$1.d)
178 + Call mutate a$2.push(read props$1.d)
179 Return freeze a$2
180 ```
181
@@ -198,14 +198,14 @@ function Component$0(props$1) {
198
199 ```
200 bb0:
201 - Const mutable a$2 = Array []
202 - Call mutable a$2.push(readonly props$1.a)
203 - If (readonly props$1.b) then:bb1 else:bb2
201 + Const mutate a$2 = Array []
202 + Call mutate a$2.push(read props$1.a)
203 + If (read props$1.b) then:bb1 else:bb2
204 bb2:
205 - Call mutable a$2.push(readonly props$1.c)
205 + Call mutate a$2.push(read props$1.c)
206 Goto bb1
207 bb1:
208 - Call mutable a$2.push(readonly props$1.d)
208 + Call mutate a$2.push(read props$1.d)
209 Return freeze a$2
210 ```
211
compiler/forget/src/__tests__/fixtures/hir/conditional-on-mutable.expect.md
+17 -17
@@ -67,20 +67,20 @@ function mayMutate() {}
67
68 ```
69 bb0:
70 - Const mutable a$2 = Array []
71 - Const mutable b$3 = Array []
72 - If (readonly b$3) then:bb2 else:bb1
70 + Const mutate a$2 = Array []
71 + Const mutate b$3 = Array []
72 + If (read b$3) then:bb2 else:bb1
73 bb2:
74 - Call mutable a$2.push(readonly props$1.p0)
74 + Call mutate a$2.push(read props$1.p0)
75 Goto bb1
76 bb1:
77 - If (readonly props$1.p1) then:bb4 else:bb3
77 + If (read props$1.p1) then:bb4 else:bb3
78 bb4:
79 - Call mutable b$3.push(readonly props$1.p2)
79 + Call mutate b$3.push(read props$1.p2)
80 Goto bb3
81 bb3:
82 - Const mutable $5 = JSX <readonly Foo$4 a={freeze a$2} b={freeze b$3} ></readonly Foo$4>
83 - Return readonly $5
82 + Const mutate $5 = JSX <read Foo$4 a={freeze a$2} b={freeze b$3} ></read Foo$4>
83 + Return read $5
84 ```
85
86 ## Code
@@ -105,21 +105,21 @@ function Component$0(props$1) {
105
106 ```
107 bb0:
108 - Const mutable a$2 = Array []
109 - Const mutable b$3 = Array []
110 - Const mutable $5 = Call mutable mayMutate$4(mutable b$3)
111 - If (readonly $5) then:bb2 else:bb1
108 + Const mutate a$2 = Array []
109 + Const mutate b$3 = Array []
110 + Const mutate $5 = Call mutate mayMutate$4(mutate b$3)
111 + If (read $5) then:bb2 else:bb1
112 bb2:
113 - Call mutable a$2.push(readonly props$1.p0)
113 + Call mutate a$2.push(read props$1.p0)
114 Goto bb1
115 bb1:
116 - If (readonly props$1.p1) then:bb4 else:bb3
116 + If (read props$1.p1) then:bb4 else:bb3
117 bb4:
118 - Call mutable b$3.push(readonly props$1.p2)
118 + Call mutate b$3.push(read props$1.p2)
119 Goto bb3
120 bb3:
121 - Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$3} ></readonly Foo$6>
122 - Return readonly $7
121 + Const mutate $7 = JSX <read Foo$6 a={freeze a$2} b={freeze b$3} ></read Foo$6>
122 + Return read $7
123 ```
124
125 ## Code
compiler/forget/src/__tests__/fixtures/hir/constructor.expect.md
+9 -9
@@ -34,15 +34,15 @@ function Foo$0() {
34
35 ```
36 bb0:
37 - Const mutable a$2 = Array []
38 - Const mutable b$3 = Object { }
39 - New mutable Foo$4(mutable a$2, mutable b$3)
40 - Const mutable $6 = "div"
41 - Let mutable _$5 = JSX <readonly $6 a={freeze a$2} ></readonly $6>
42 - New mutable Foo$4(mutable b$3)
43 - Const mutable $7 = "div"
44 - Const mutable $8 = JSX <readonly $7 a={readonly a$2} b={freeze b$3} ></readonly $7>
45 - Return readonly $8
37 + Const mutate a$2 = Array []
38 + Const mutate b$3 = Object { }
39 + New mutate Foo$4(mutate a$2, mutate b$3)
40 + Const mutate $6 = "div"
41 + Let mutate _$5 = JSX <read $6 a={freeze a$2} ></read $6>
42 + New mutate Foo$4(mutate b$3)
43 + Const mutate $7 = "div"
44 + Const mutate $8 = JSX <read $7 a={read a$2} b={freeze b$3} ></read $7>
45 + Return read $8
46 ```
47
48 ## Code
compiler/forget/src/__tests__/fixtures/hir/frozen-after-alias.expect.md
+4 -4
@@ -18,10 +18,10 @@ function foo(x) {}
18
19 ```
20 bb0:
21 - Const mutable a$1 = Array []
22 - Const mutable b$2 = readonly a$1
23 - Call readonly useFreeze$3(freeze a$1)
24 - Call mutable foo$4(readonly b$2)
21 + Const mutate a$1 = Array []
22 + Const mutate b$2 = read a$1
23 + Call read useFreeze$3(freeze a$1)
24 + Call mutate foo$4(read b$2)
25 Return
26 ```
27
compiler/forget/src/__tests__/fixtures/hir/hook-call.expect.md
+8 -8
@@ -53,14 +53,14 @@ function foo$0() {
53
54 ```
55 bb0:
56 - Const mutable x$2 = Array []
57 - Const mutable y$3 = Call readonly useFreeze$4(freeze x$2)
58 - Call mutable foo$5(readonly y$3, readonly x$2)
59 - Const mutable $6 = "\n "
60 - Const mutable $7 = "\n "
61 - Const mutable $8 = "\n "
62 - Const mutable $9 = JSX <readonly Component$0>{readonly $6}{readonly x$2}{readonly $7}{readonly y$3}{readonly $8}</readonly Component$0>
63 - Return readonly $9
56 + Const mutate x$2 = Array []
57 + Const mutate y$3 = Call read useFreeze$4(freeze x$2)
58 + Call mutate foo$5(read y$3, read x$2)
59 + Const mutate $6 = "\n "
60 + Const mutate $7 = "\n "
61 + Const mutate $8 = "\n "
62 + Const mutate $9 = JSX <read Component$0>{read $6}{read x$2}{read $7}{read y$3}{read $8}</read Component$0>
63 + Return read $9
64 ```
65
66 ## Code
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-arguments.expect.md
+5 -5
@@ -19,11 +19,11 @@ function call(x) {}
19
20 ```
21 bb0:
22 - Const mutable a$1 = Array []
23 - Call readonly useFreeze$2(freeze a$1)
24 - Call readonly useFreeze$2(readonly a$1)
25 - Call mutable call$3(readonly a$1)
26 - Return readonly a$1
22 + Const mutate a$1 = Array []
23 + Call read useFreeze$2(freeze a$1)
24 + Call read useFreeze$2(read a$1)
25 + Call mutate call$3(read a$1)
26 + Return read a$1
27 ```
28
29 ## Code
compiler/forget/src/__tests__/fixtures/hir/hooks-freeze-possibly-mutable-arguments.expect.md
+10 -10
@@ -26,21 +26,21 @@ function call(x) {}
26
27 ```
28 bb0:
29 - Const mutable cond$2 = readonly props$1.cond
30 - Const mutable x$3 = readonly props$1.x
31 - Let mutable a$4 = undefined
32 - If (readonly cond$2) then:bb2 else:bb3
29 + Const mutate cond$2 = read props$1.cond
30 + Const mutate x$3 = read props$1.x
31 + Let mutate a$4 = undefined
32 + If (read cond$2) then:bb2 else:bb3
33 bb2:
34 - Reassign mutable a$4 = readonly x$3
34 + Reassign mutate a$4 = read x$3
35 Goto bb1
36 bb3:
37 - Reassign mutable a$4 = Array []
37 + Reassign mutate a$4 = Array []
38 Goto bb1
39 bb1:
40 - Call readonly useFreeze$5(freeze a$4)
41 - Call readonly useFreeze$5(readonly a$4)
42 - Call mutable call$6(readonly a$4)
43 - Return readonly a$4
40 + Call read useFreeze$5(freeze a$4)
41 + Call read useFreeze$5(read a$4)
42 + Call mutate call$6(read a$4)
43 + Return read a$4
44 ```
45
46 ## Code
compiler/forget/src/__tests__/fixtures/hir/independent-across-if.expect.md
+7 -7
@@ -97,16 +97,16 @@ function Foo$0() {
97
98 ```
99 bb0:
100 - Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
101 - Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
102 - If (readonly props$1.c) then:bb2 else:bb1
100 + Const mutate a$2 = Call mutate compute$3(read props$1.a)
101 + Const mutate b$4 = Call mutate compute$3(read props$1.b)
102 + If (read props$1.c) then:bb2 else:bb1
103 bb2:
104 - Call mutable mutate$5(mutable a$2)
105 - Call mutable mutate$5(mutable b$4)
104 + Call mutate mutate$5(mutate a$2)
105 + Call mutate mutate$5(mutate b$4)
106 Goto bb1
107 bb1:
108 - Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
109 - Return readonly $7
108 + Const mutate $7 = JSX <read Foo$6 a={freeze a$2} b={freeze b$4} ></read Foo$6>
109 + Return read $7
110 ```
111
112 ## Code
compiler/forget/src/__tests__/fixtures/hir/independent.expect.md
+4 -4
@@ -28,10 +28,10 @@ function Foo() {}
28
29 ```
30 bb0:
31 - Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
32 - Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
33 - Const mutable $6 = JSX <readonly Foo$5 a={freeze a$2} b={freeze b$4} ></readonly Foo$5>
34 - Return readonly $6
31 + Const mutate a$2 = Call mutate compute$3(read props$1.a)
32 + Const mutate b$4 = Call mutate compute$3(read props$1.b)
33 + Const mutate $6 = JSX <read Foo$5 a={freeze a$2} b={freeze b$4} ></read Foo$5>
34 + Return read $6
35 ```
36
37 ## Code
compiler/forget/src/__tests__/fixtures/hir/interdependent-across-if.expect.md
+6 -6
@@ -76,15 +76,15 @@ function Foo$0() {
76
77 ```
78 bb0:
79 - Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
80 - Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
81 - If (readonly props$1.c) then:bb2 else:bb1
79 + Const mutate a$2 = Call mutate compute$3(read props$1.a)
80 + Const mutate b$4 = Call mutate compute$3(read props$1.b)
81 + If (read props$1.c) then:bb2 else:bb1
82 bb2:
83 - Call mutable foo$5(mutable a$2, mutable b$4)
83 + Call mutate foo$5(mutate a$2, mutate b$4)
84 Goto bb1
85 bb1:
86 - Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
87 - Return readonly $7
86 + Const mutate $7 = JSX <read Foo$6 a={freeze a$2} b={freeze b$4} ></read Foo$6>
87 + Return read $7
88 ```
89
90 ## Code
compiler/forget/src/__tests__/fixtures/hir/interdependent.expect.md
+5 -5
@@ -28,11 +28,11 @@ function Foo() {}
28
29 ```
30 bb0:
31 - Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
32 - Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
33 - Call mutable foo$5(mutable a$2, mutable b$4)
34 - Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
35 - Return readonly $7
31 + Const mutate a$2 = Call mutate compute$3(read props$1.a)
32 + Const mutate b$4 = Call mutate compute$3(read props$1.b)
33 + Call mutate foo$5(mutate a$2, mutate b$4)
34 + Const mutate $7 = JSX <read Foo$6 a={freeze a$2} b={freeze b$4} ></read Foo$6>
35 + Return read $7
36 ```
37
38 ## Code
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-loops.expect.md
+20 -20
@@ -73,34 +73,34 @@ function cond$0(x$1) {
73
74 ```
75 bb0:
76 - Let mutable a$2 = Object { }
77 - Let mutable b$3 = Object { }
78 - Let mutable c$4 = Object { }
79 - Let mutable d$5 = Object { }
76 + Let mutate a$2 = Object { }
77 + Let mutate b$3 = Object { }
78 + Let mutate c$4 = Object { }
79 + Let mutate d$5 = Object { }
80 Goto bb1
81 bb1:
82 - Const mutable $10 = true
83 - If (readonly $10) then:bb3 else:bb2
82 + Const mutate $10 = true
83 + If (read $10) then:bb3 else:bb2
84 bb3:
85 - Let mutable z$6 = readonly a$2
86 - Reassign mutable a$2 = readonly b$3
87 - Reassign mutable b$3 = readonly c$4
88 - Reassign mutable c$4 = readonly d$5
89 - Reassign mutable d$5 = readonly z$6
90 - Call mutable mutate$7(mutable a$2, mutable b$3)
91 - Const mutable $9 = Call mutable cond$8(mutable a$2)
92 - If (readonly $9) then:bb2 else:bb1
85 + Let mutate z$6 = read a$2
86 + Reassign mutate a$2 = read b$3
87 + Reassign mutate b$3 = read c$4
88 + Reassign mutate c$4 = read d$5
89 + Reassign mutate d$5 = read z$6
90 + Call mutate mutate$7(mutate a$2, mutate b$3)
91 + Const mutate $9 = Call mutate cond$8(mutate a$2)
92 + If (read $9) then:bb2 else:bb1
93 bb2:
94 - If (readonly a$2) then:bb7 else:bb7
94 + If (read a$2) then:bb7 else:bb7
95 bb7:
96 - If (readonly b$3) then:bb9 else:bb9
96 + If (read b$3) then:bb9 else:bb9
97 bb9:
98 - If (readonly c$4) then:bb11 else:bb11
98 + If (read c$4) then:bb11 else:bb11
99 bb11:
100 - If (readonly d$5) then:bb13 else:bb13
100 + If (read d$5) then:bb13 else:bb13
101 bb13:
102 - Const mutable $11 = null
103 - Call mutable mutate$7(mutable d$5, readonly $11)
102 + Const mutate $11 = null
103 + Call mutate mutate$7(mutate d$5, read $11)
104 Return
105 ```
106
compiler/forget/src/__tests__/fixtures/hir/mutable-lifetime-with-aliasing.expect.md
+14 -14
@@ -54,25 +54,25 @@ function mutate$0(x$1, y$2) {
54
55 ```
56 bb0:
57 - Const mutable a$2 = Object { }
58 - Const mutable b$3 = Array [readonly a$2]
59 - Const mutable c$4 = Object { }
60 - Const mutable d$5 = Object { c: readonly c$4 }
61 - Const mutable x$6 = Object { }
62 - Reassign mutable x$6.b = readonly b$3
63 - Const mutable y$7 = Call mutable mutate$8(mutable x$6, mutable d$5)
64 - If (readonly a$2) then:bb1 else:bb1
57 + Const mutate a$2 = Object { }
58 + Const mutate b$3 = Array [read a$2]
59 + Const mutate c$4 = Object { }
60 + Const mutate d$5 = Object { c: read c$4 }
61 + Const mutate x$6 = Object { }
62 + Reassign mutate x$6.b = read b$3
63 + Const mutate y$7 = Call mutate mutate$8(mutate x$6, mutate d$5)
64 + If (read a$2) then:bb1 else:bb1
65 bb1:
66 - If (readonly b$3) then:bb3 else:bb3
66 + If (read b$3) then:bb3 else:bb3
67 bb3:
68 - If (readonly c$4) then:bb5 else:bb5
68 + If (read c$4) then:bb5 else:bb5
69 bb5:
70 - If (readonly d$5) then:bb7 else:bb7
70 + If (read d$5) then:bb7 else:bb7
71 bb7:
72 - If (readonly y$7) then:bb9 else:bb9
72 + If (read y$7) then:bb9 else:bb9
73 bb9:
74 - Const mutable $9 = null
75 - Call mutable mutate$8(mutable x$6, readonly $9)
74 + Const mutate $9 = null
75 + Call mutate mutate$8(mutate x$6, read $9)
76 Return
77 ```
78
compiler/forget/src/__tests__/fixtures/hir/property-assignment.expect.md
+7 -7
@@ -17,13 +17,13 @@ function Component(props) {
17
18 ```
19 bb0:
20 - Const mutable x$2 = Object { }
21 - Const mutable y$3 = Array []
22 - Reassign mutable x$2.y = readonly y$3
23 - Const mutable child$4 = JSX <readonly Component$0 data={freeze y$3} ></readonly Component$0>
24 - Call mutable x$2.y.push(readonly props$1.p0)
25 - Const mutable $5 = JSX <readonly Component$0 data={freeze x$2} >{readonly child$4}</readonly Component$0>
26 - Return readonly $5
20 + Const mutate x$2 = Object { }
21 + Const mutate y$3 = Array []
22 + Reassign mutate x$2.y = read y$3
23 + Const mutate child$4 = JSX <read Component$0 data={freeze y$3} ></read Component$0>
24 + Call mutate x$2.y.push(read props$1.p0)
25 + Const mutate $5 = JSX <read Component$0 data={freeze x$2} >{read child$4}</read Component$0>
26 + Return read $5
27 ```
28
29 ## Code
compiler/forget/src/__tests__/fixtures/hir/reassignment-conditional.expect.md
+9 -9
@@ -23,18 +23,18 @@ function Component(props) {
23
24 ```
25 bb0:
26 - Let mutable x$2 = Array []
27 - Call mutable x$2.push(readonly props$1.p0)
28 - Let mutable y$3 = readonly x$2
29 - If (readonly props$1.p1) then:bb2 else:bb1
26 + Let mutate x$2 = Array []
27 + Call mutate x$2.push(read props$1.p0)
28 + Let mutate y$3 = read x$2
29 + If (read props$1.p1) then:bb2 else:bb1
30 bb2:
31 - Reassign mutable x$2 = Array []
31 + Reassign mutate x$2 = Array []
32 Goto bb1
33 bb1:
34 - Let mutable _$4 = JSX <readonly Component$0 x={freeze x$2} ></readonly Component$0>
35 - Call readonly y$3.push(readonly props$1.p2)
36 - Const mutable $5 = JSX <readonly Component$0 x={readonly x$2} y={readonly y$3} ></readonly Component$0>
37 - Return readonly $5
34 + Let mutate _$4 = JSX <read Component$0 x={freeze x$2} ></read Component$0>
35 + Call read y$3.push(read props$1.p2)
36 + Const mutate $5 = JSX <read Component$0 x={read x$2} y={read y$3} ></read Component$0>
37 + Return read $5
38 ```
39
40 ## Code
compiler/forget/src/__tests__/fixtures/hir/reassignment.expect.md
+8 -8
@@ -21,14 +21,14 @@ function Component(props) {
21
22 ```
23 bb0:
24 - Let mutable x$2 = Array []
25 - Call mutable x$2.push(readonly props$1.p0)
26 - Let mutable y$3 = readonly x$2
27 - Reassign mutable x$2 = Array []
28 - Let mutable _$4 = JSX <readonly Component$0 x={freeze x$2} ></readonly Component$0>
29 - Call mutable y$3.push(readonly props$1.p1)
30 - Const mutable $5 = JSX <readonly Component$0 x={readonly x$2} y={freeze y$3} ></readonly Component$0>
31 - Return readonly $5
24 + Let mutate x$2 = Array []
25 + Call mutate x$2.push(read props$1.p0)
26 + Let mutate y$3 = read x$2
27 + Reassign mutate x$2 = Array []
28 + Let mutate _$4 = JSX <read Component$0 x={freeze x$2} ></read Component$0>
29 + Call mutate y$3.push(read props$1.p1)
30 + Const mutate $5 = JSX <read Component$0 x={read x$2} y={freeze y$3} ></read Component$0>
31 + Return read $5
32 ```
33
34 ## Code
compiler/forget/src/__tests__/fixtures/hir/reverse-postorder.expect.md
+15 -15
@@ -36,36 +36,36 @@ function Component(props) {
36
37 ```
38 bb0:
39 - Let mutable x$2 = undefined
40 - If (readonly props$1.cond) then:bb2 else:bb10
39 + Let mutate x$2 = undefined
40 + If (read props$1.cond) then:bb2 else:bb10
41 bb2:
42 - Const mutable $3 = 2
43 - Const mutable $4 = 1
44 - Const mutable $5 = 0
42 + Const mutate $3 = 2
43 + Const mutate $4 = 1
44 + Const mutate $5 = 0
45 Switch (<unknown> props$1.test)
46 - Case readonly $5: bb8
47 - Case readonly $4: bb6
48 - Case readonly $3: bb4
46 + Case read $5: bb8
47 + Case read $4: bb6
48 + Case read $3: bb4
49 Default: bb4
50 bb8:
51 - Reassign mutable x$2 = readonly props$1.v0
51 + Reassign mutate x$2 = read props$1.v0
52 Goto bb1
53 bb6:
54 - Reassign mutable x$2 = readonly props$1.v1
54 + Reassign mutate x$2 = read props$1.v1
55 Goto bb1
56 bb4:
57 - Reassign mutable x$2 = readonly props$1.v2
57 + Reassign mutate x$2 = read props$1.v2
58 Goto bb1
59 bb10:
60 - If (readonly props$1.cond2) then:bb12 else:bb13
60 + If (read props$1.cond2) then:bb12 else:bb13
61 bb12:
62 - Reassign mutable x$2 = readonly props$1.b
62 + Reassign mutate x$2 = read props$1.b
63 Goto bb1
64 bb13:
65 - Reassign mutable x$2 = readonly props$1.c
65 + Reassign mutate x$2 = read props$1.c
66 Goto bb1
67 bb1:
68 - readonly x$2
68 + read x$2
69 Return
70 ```
71
compiler/forget/src/__tests__/fixtures/hir/simple.expect.md
+6 -6
@@ -15,15 +15,15 @@ function foo(x, y) {
15
16 ```
17 bb0:
18 - If (readonly x$1) then:bb2 else:bb1
18 + If (read x$1) then:bb2 else:bb1
19 bb2:
20 - Const mutable $3 = false
21 - Const mutable $4 = Call readonly foo$0(readonly $3, readonly y$2)
20 + Const mutate $3 = false
21 + Const mutate $4 = Call read foo$0(read $3, read y$2)
22 Return freeze $4
23 bb1:
24 - Const mutable $5 = 10
25 - Const mutable $6 = Binary readonly y$2 * readonly $5
26 - Const mutable $7 = Array [readonly $6]
24 + Const mutate $5 = 10
25 + Const mutate $6 = Binary read y$2 * read $5
26 + Const mutate $7 = Array [read $6]
27 Return freeze $7
28 ```
29
compiler/forget/src/__tests__/fixtures/hir/switch-non-final-default.expect.md
+15 -15
@@ -32,28 +32,28 @@ function Component(props) {
32
33 ```
34 bb0:
35 - Let mutable x$2 = Array []
36 - Let mutable y$3 = undefined
37 - Const mutable $4 = false
38 - Const mutable $5 = true
39 - Const mutable $6 = 1
35 + Let mutate x$2 = Array []
36 + Let mutate y$3 = undefined
37 + Const mutate $4 = false
38 + Const mutate $5 = true
39 + Const mutate $6 = 1
40 Switch (<unknown> props$1.p0)
41 - Case readonly $6: bb1
42 - Case readonly $5: bb6
41 + Case read $6: bb1
42 + Case read $5: bb6
43 Default: bb1
44 - Case readonly $4: bb2
44 + Case read $4: bb2
45 bb6:
46 - Call mutable x$2.push(readonly props$1.p2)
47 - Reassign mutable y$3 = Array []
46 + Call mutate x$2.push(read props$1.p2)
47 + Reassign mutate y$3 = Array []
48 Goto bb1
49 bb2:
50 - Reassign mutable y$3 = readonly x$2
50 + Reassign mutate y$3 = read x$2
51 Goto bb1
52 bb1:
53 - Const mutable child$7 = JSX <readonly Component$0 data={freeze x$2} ></readonly Component$0>
54 - Call readonly y$3.push(readonly props$1.p4)
55 - Const mutable $8 = JSX <readonly Component$0 data={freeze y$3} >{readonly child$7}</readonly Component$0>
56 - Return readonly $8
53 + Const mutate child$7 = JSX <read Component$0 data={freeze x$2} ></read Component$0>
54 + Call read y$3.push(read props$1.p4)
55 + Const mutate $8 = JSX <read Component$0 data={freeze y$3} >{read child$7}</read Component$0>
56 + Return read $8
57 ```
58
59 ## Code
compiler/forget/src/__tests__/fixtures/hir/switch.expect.md
+14 -14
@@ -28,27 +28,27 @@ function Component(props) {
28
29 ```
30 bb0:
31 - Let mutable x$2 = Array []
32 - Let mutable y$3 = undefined
33 - Const mutable $4 = false
34 - Const mutable $5 = true
31 + Let mutate x$2 = Array []
32 + Let mutate y$3 = undefined
33 + Const mutate $4 = false
34 + Const mutate $5 = true
35 Switch (<unknown> props$1.p0)
36 - Case readonly $5: bb4
37 - Case readonly $4: bb2
36 + Case read $5: bb4
37 + Case read $4: bb2
38 Default: bb1
39 bb4:
40 - Call mutable x$2.push(readonly props$1.p2)
41 - Call mutable x$2.push(readonly props$1.p3)
42 - Reassign mutable y$3 = Array []
40 + Call mutate x$2.push(read props$1.p2)
41 + Call mutate x$2.push(read props$1.p3)
42 + Reassign mutate y$3 = Array []
43 Goto bb2
44 bb2:
45 - Reassign mutable y$3 = readonly x$2
45 + Reassign mutate y$3 = read x$2
46 Goto bb1
47 bb1:
48 - Const mutable child$6 = JSX <readonly Component$0 data={freeze x$2} ></readonly Component$0>
49 - Call readonly y$3.push(readonly props$1.p4)
50 - Const mutable $7 = JSX <readonly Component$0 data={readonly y$3} >{readonly child$6}</readonly Component$0>
51 - Return readonly $7
48 + Const mutate child$6 = JSX <read Component$0 data={freeze x$2} ></read Component$0>
49 + Call read y$3.push(read props$1.p4)
50 + Const mutate $7 = JSX <read Component$0 data={read y$3} >{read child$6}</read Component$0>
51 + Return read $7
52 ```
53
54 ## Code