[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