@samitouri / QOS-React-2 / commits / 36d1fa2569

[storelocal] Instruction lvalue is just a Place

Joe Savona committed Mar 2, 2023 at 14:19 UTC 36d1fa2569dd544d2e1b69215feceaf3c25747f3
30 files changed +143 -217
compiler/forget/src/HIR/BuildHIR.ts
+35 -56
@@ -614,7 +614,7 @@ function lowerStatement(
614 value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource);
615 builder.push({
616 id: makeInstructionId(0),
617 - lvalue: { place: { ...value }, kind: InstructionKind.Const },
617 + lvalue: { ...value },
618 value: {
619 kind: "Primitive",
620 value: undefined,
@@ -647,7 +647,7 @@ function lowerStatement(
647 );
648 builder.push({
649 id: makeInstructionId(0),
650 - lvalue: { kind: InstructionKind.Const, place },
650 + lvalue: place,
651 value,
652 loc: stmt.node.loc ?? GeneratedSource,
653 });
@@ -746,13 +746,10 @@ function lowerStatement(
746 });
747 builder.push({
748 id: makeInstructionId(0),
749 - lvalue: {
750 - place: buildTemporaryPlace(
751 - builder,
752 - stmtPath.node.loc ?? GeneratedSource
753 - ),
754 - kind: InstructionKind.Const,
755 - },
749 + lvalue: buildTemporaryPlace(
750 + builder,
751 + stmtPath.node.loc ?? GeneratedSource
752 + ),
753 loc: stmtPath.node.loc ?? GeneratedSource,
754 value: {
755 kind: "UnsupportedNode",
@@ -1043,7 +1040,7 @@ function lowerExpression(
1040 const consequentBlock = builder.enter("value", (_blockId) => {
1041 builder.push({
1042 id: makeInstructionId(0),
1046 - lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1043 + lvalue: { ...place },
1044 value: lowerExpression(builder, expr.get("consequent")),
1045 loc: exprLoc,
1046 });
@@ -1058,7 +1055,7 @@ function lowerExpression(
1055 const alternateBlock = builder.enter("value", (_blockId) => {
1056 builder.push({
1057 id: makeInstructionId(0),
1061 - lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1058 + lvalue: { ...place },
1059 value: lowerExpression(builder, expr.get("alternate")),
1060 loc: exprLoc,
1061 });
@@ -1106,7 +1103,7 @@ function lowerExpression(
1103 const consequent = builder.enter("value", () => {
1104 builder.push({
1105 id: makeInstructionId(0),
1109 - lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1106 + lvalue: { ...place },
1107 value: {
1108 kind: "LoadLocal",
1109 place: { ...leftPlace },
@@ -1124,7 +1121,7 @@ function lowerExpression(
1121 const alternate = builder.enter("value", () => {
1122 builder.push({
1123 id: makeInstructionId(0),
1127 - lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1124 + lvalue: { ...place },
1125 value: lowerExpression(builder, expr.get("right")),
1126 loc: exprLoc,
1127 });
@@ -1148,7 +1145,7 @@ function lowerExpression(
1145 );
1146 builder.push({
1147 id: makeInstructionId(0),
1151 - lvalue: { kind: InstructionKind.Reassign, place: { ...leftPlace } },
1148 + lvalue: { ...leftPlace },
1149 value: lowerExpression(builder, expr.get("left")),
1150 loc: exprLoc,
1151 });
@@ -1225,8 +1222,7 @@ function lowerExpression(
1222 builder.push({
1223 id: makeInstructionId(0),
1224 lvalue: {
1228 - place: { ...binaryPlace },
1229 - kind: InstructionKind.Const,
1225 + ...binaryPlace,
1226 },
1227 value: {
1228 kind: "BinaryExpression",
@@ -1240,7 +1236,7 @@ function lowerExpression(
1236 const result = buildTemporaryPlace(builder, exprLoc);
1237 builder.push({
1238 id: makeInstructionId(0),
1243 - lvalue: { place: { ...result }, kind: InstructionKind.Const },
1239 + lvalue: { ...result },
1240 value: {
1241 kind: "StoreLocal",
1242 lvalue: {
@@ -1270,8 +1266,7 @@ function lowerExpression(
1266 builder.push({
1267 id: makeInstructionId(0),
1268 lvalue: {
1273 - place: { ...previousValuePlace },
1274 - kind: InstructionKind.Const,
1269 + ...previousValuePlace,
1270 },
1271 value,
1272 loc: leftExpr.node.loc ?? GeneratedSource,
@@ -1281,8 +1276,7 @@ function lowerExpression(
1276 builder.push({
1277 id: makeInstructionId(0),
1278 lvalue: {
1284 - place: { ...newValuePlace },
1285 - kind: InstructionKind.Const,
1279 + ...newValuePlace,
1280 },
1281 value: {
1282 kind: "BinaryExpression",
@@ -1332,7 +1326,7 @@ function lowerExpression(
1326 const place: Place = buildTemporaryPlace(builder, exprLoc);
1327 builder.push({
1328 id: makeInstructionId(0),
1335 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1329 + lvalue: { ...place },
1330 value,
1331 loc: exprLoc,
1332 });
@@ -1581,7 +1575,7 @@ function lowerExpression(
1575 );
1576 builder.push({
1577 id: makeInstructionId(0),
1584 - lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const },
1578 + lvalue: { ...primitiveTemp },
1579 value: {
1580 kind: "Primitive",
1581 value: 1,
@@ -1599,7 +1593,7 @@ function lowerExpression(
1593 );
1594 builder.push({
1595 id: makeInstructionId(0),
1602 - lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1596 + lvalue: { ...temp },
1597 value: {
1598 kind: "BinaryExpression",
1599 operator: expr.node.operator === "++" ? "+" : "-",
@@ -1611,16 +1605,10 @@ function lowerExpression(
1605 });
1606 builder.push({
1607 id: makeInstructionId(0),
1614 - lvalue: {
1615 - place: buildTemporaryPlace(builder, exprLoc),
1616 - kind: InstructionKind.Const,
1617 - },
1608 + lvalue: buildTemporaryPlace(builder, exprLoc),
1609 value: {
1610 kind: "StoreLocal",
1620 - lvalue: {
1621 - place: { ...identifier },
1622 - kind: InstructionKind.Reassign,
1623 - },
1611 + lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign },
1612 value: { ...temp },
1613 loc: exprLoc,
1614 },
@@ -1723,7 +1711,7 @@ function lowerJsxElementName(
1711 loc: exprLoc,
1712 },
1713 loc: exprLoc,
1726 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1714 + lvalue: { ...place },
1715 });
1716 return { ...place };
1717 }
@@ -1740,9 +1728,9 @@ function lowerJsxElementName(
1728 loc: exprLoc,
1729 },
1730 loc: exprLoc,
1743 - lvalue: { place, kind: InstructionKind.Const },
1731 + lvalue: { ...place },
1732 });
1745 - return { ...place };
1733 + return place;
1734 }
1735 }
1736
@@ -1777,7 +1765,7 @@ function lowerJsxElement(
1765 loc: exprLoc,
1766 },
1767 loc: exprLoc,
1780 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1768 + lvalue: { ...place },
1769 });
1770 return { ...place };
1771 }
@@ -1792,7 +1780,7 @@ function lowerJsxElement(
1780 loc: exprLoc,
1781 },
1782 loc: exprLoc,
1795 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1783 + lvalue: { ...place },
1784 });
1785 return place;
1786 } else {
@@ -1812,7 +1800,7 @@ function lowerJsxElement(
1800 loc: exprLoc,
1801 },
1802 loc: exprLoc,
1815 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1803 + lvalue: { ...place },
1804 });
1805 return place;
1806 }
@@ -1832,7 +1820,7 @@ function lowerExpressionToTemporary(
1820 id: makeInstructionId(0),
1821 value: value,
1822 loc: exprLoc,
1835 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1823 + lvalue: { ...place },
1824 });
1825 return place;
1826 }
@@ -1851,7 +1839,7 @@ function lowerExpressionToPlace(
1839 id: makeInstructionId(0),
1840 value: value,
1841 loc: exprLoc,
1854 - lvalue: { place: { ...place }, kind: InstructionKind.Const },
1842 + lvalue: { ...place },
1843 });
1844 return place;
1845 }
@@ -1869,10 +1857,7 @@ function lowerExpressionToVoid(
1857 id: makeInstructionId(0),
1858 value: instr,
1859 loc: exprLoc,
1872 - lvalue: {
1873 - place: buildTemporaryPlace(builder, exprLoc),
1874 - kind: InstructionKind.Const,
1875 - },
1860 + lvalue: buildTemporaryPlace(builder, exprLoc),
1861 });
1862 }
1863
@@ -1899,10 +1884,7 @@ function lowerIdentifier(
1884 id: makeInstructionId(0),
1885 value,
1886 loc: place.loc,
1902 - lvalue: {
1903 - place: { ...place },
1904 - kind: InstructionKind.Const,
1905 - },
1887 + lvalue: { ...place },
1888 });
1889 return place;
1890 }
@@ -1972,13 +1954,10 @@ function lowerAssignment(
1954 };
1955 builder.push({
1956 id: makeInstructionId(0),
1975 - lvalue: { place: { ...temporary }, kind },
1957 + lvalue: { ...temporary },
1958 value: {
1959 kind: "StoreLocal",
1978 - lvalue: {
1979 - place: { ...place },
1980 - kind,
1981 - },
1960 + lvalue: { place: { ...place }, kind },
1961 value,
1962 loc,
1963 },
@@ -2050,7 +2029,7 @@ function lowerAssignment(
2029 );
2030 builder.push({
2031 id: makeInstructionId(0),
2053 - lvalue: { place: { ...property }, kind: InstructionKind.Const },
2032 + lvalue: { ...property },
2033 value: {
2034 kind: "Primitive",
2035 value: i,
@@ -2061,7 +2040,7 @@ function lowerAssignment(
2040 const propertyPlace = buildTemporaryPlace(builder, property.loc);
2041 builder.push({
2042 id: makeInstructionId(0),
2064 - lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2043 + lvalue: { ...propertyPlace },
2044 value: {
2045 kind: "ComputedLoad",
2046 loc,
@@ -2123,7 +2102,7 @@ function lowerAssignment(
2102 );
2103 builder.push({
2104 id: makeInstructionId(0),
2126 - lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2105 + lvalue: { ...propertyPlace },
2106 value: {
2107 kind: "PropertyLoad",
2108 loc,
compiler/forget/src/HIR/HIR.ts
+2 -2
@@ -81,7 +81,7 @@ export type ReactiveTerminalStatement<
81
82 export type ReactiveInstruction = {
83 id: InstructionId;
84 - lvalue: LValue | null;
84 + lvalue: Place | null;
85 value: ReactiveValue;
86 loc: SourceLocation;
87 };
@@ -365,7 +365,7 @@ export type TernaryTerminal = {
365 */
366 export type Instruction = {
367 id: InstructionId;
368 - lvalue: LValue;
368 + lvalue: Place;
369 value: InstructionValue;
370 loc: SourceLocation;
371 };
compiler/forget/src/HIR/MergeConsecutiveBlocks.ts
+4 -8
@@ -12,7 +12,6 @@ import {
12 GeneratedSource,
13 HIRFunction,
14 Instruction,
15 - InstructionKind,
15 } from "./HIR";
16
17 /**
@@ -60,13 +59,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
59 const instr: Instruction = {
60 id: predecessor.terminal.id,
61 lvalue: {
63 - place: {
64 - kind: "Identifier",
65 - identifier: phi.id,
66 - effect: Effect.Mutate,
67 - loc: GeneratedSource,
68 - },
69 - kind: InstructionKind.Const,
62 + kind: "Identifier",
63 + identifier: phi.id,
64 + effect: Effect.Mutate,
65 + loc: GeneratedSource,
66 },
67 value: {
68 kind: "LoadLocal",
compiler/forget/src/HIR/PrintHIR.ts
+1 -1
@@ -106,7 +106,7 @@ export function printInstruction(instr: ReactiveInstruction): string {
106 const value = printInstructionValue(instr.value);
107
108 if (instr.lvalue !== null) {
109 - return `${id} ${printLValue(instr.lvalue)} = ${value}`;
109 + return `${id} ${printPlace(instr.lvalue)} = ${value}`;
110 } else {
111 return `${id} ${value}`;
112 }
compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts
+4 -8
@@ -29,17 +29,13 @@ export function validateConsistentIdentifiers(fn: HIRFunction): void {
29 }
30 }
31 for (const instr of block.instructions) {
32 - if (instr.lvalue.place.identifier.name !== null) {
32 + if (instr.lvalue.identifier.name !== null) {
33 CompilerError.invariant(
34 - `Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`,
35 - instr.lvalue.place.loc
34 + `Expected all lvalues to be temporaries, found '${instr.lvalue.identifier.name}'`,
35 + instr.lvalue.loc
36 );
37 }
38 - validate(
39 - identifiers,
40 - instr.lvalue.place.identifier,
41 - instr.lvalue.place.loc
42 - );
38 + validate(identifiers, instr.lvalue.identifier, instr.lvalue.loc);
39 for (const operand of eachInstructionValueOperand(instr.value)) {
40 validate(identifiers, operand.identifier, operand.loc);
41 }
compiler/forget/src/HIR/visitors.ts
+1 -1
@@ -594,7 +594,7 @@ export function* eachBlockOperand(block: BasicBlock): Iterable<Place> {
594 for (const instr of block.instructions) {
595 yield* eachInstructionOperand(instr);
596 if (instr.lvalue != null) {
597 - yield instr.lvalue.place;
597 + yield instr.lvalue;
598 }
599 }
600 yield* eachTerminalOperand(block.terminal);
compiler/forget/src/Inference/AnalyseFunctions.ts
+3 -3
@@ -56,15 +56,15 @@ export default function analyseFunctions(func: HIRFunction) {
56 }
57 case "PropertyLoad": {
58 state.declareProperty(
59 - instr.lvalue.place,
59 + instr.lvalue,
60 instr.value.object,
61 instr.value.property
62 );
63 break;
64 }
65 case "LoadLocal": {
66 - if (instr.lvalue.place.identifier.name === null) {
67 - state.declareTemporary(instr.lvalue.place, instr.value.place);
66 + if (instr.lvalue.identifier.name === null) {
67 + state.declareTemporary(instr.lvalue, instr.value.place);
68 }
69 break;
70 }
compiler/forget/src/Inference/InferAlias.ts
+1 -1
@@ -49,5 +49,5 @@ function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
49 return;
50 }
51
52 - aliases.union([lvalue.place.identifier, alias.identifier]);
52 + aliases.union([lvalue.identifier, alias.identifier]);
53 }
compiler/forget/src/Inference/InferAliasForStores.ts
+2 -2
@@ -21,7 +21,7 @@ export function inferAliasForStores(
21 for (const [_, block] of func.body.blocks) {
22 for (const instr of block.instructions) {
23 const { value, lvalue } = instr;
24 - if (lvalue.place.effect !== Effect.Store) {
24 + if (lvalue.effect !== Effect.Store) {
25 continue;
26 }
27 if (value.kind === "StoreLocal") {
@@ -32,7 +32,7 @@ export function inferAliasForStores(
32 operand.effect === Effect.Capture ||
33 operand.effect === Effect.Store
34 ) {
35 - maybeAlias(aliases, lvalue.place, operand, instr.id);
35 + maybeAlias(aliases, lvalue, operand, instr.id);
36 }
37 }
38 }
compiler/forget/src/Inference/InferMutableLifetimes.ts
+1 -1
@@ -129,7 +129,7 @@ export function inferMutableLifetimes(
129 }
130 }
131
132 - const lvalueId = instr.lvalue.place.identifier;
132 + const lvalueId = instr.lvalue.identifier;
133
134 // lvalue start being mutable when they're initially assigned a
135 // value.
compiler/forget/src/Inference/InferReferenceEffects.ts
+22 -22
@@ -655,8 +655,8 @@ function inferBlock(
655 );
656 }
657 state.initialize(instrValue, ValueKind.Mutable);
658 - state.define(instr.lvalue.place, instrValue);
659 - instr.lvalue.place.effect = Effect.Store;
658 + state.define(instr.lvalue, instrValue);
659 + instr.lvalue.effect = Effect.Store;
660 continue;
661 }
662 case "PropertyCall": {
@@ -676,8 +676,8 @@ function inferBlock(
676 state.reference(arg, Effect.Mutate);
677 }
678 state.initialize(instrValue, ValueKind.Mutable);
679 - state.define(instr.lvalue.place, instrValue);
680 - instr.lvalue.place.effect = Effect.Mutate;
679 + state.define(instr.lvalue, instrValue);
680 + instr.lvalue.effect = Effect.Mutate;
681 continue;
682 }
683 case "ComputedCall": {
@@ -698,8 +698,8 @@ function inferBlock(
698 state.reference(arg, Effect.Mutate);
699 }
700 state.initialize(instrValue, ValueKind.Mutable);
701 - state.define(instr.lvalue.place, instrValue);
702 - instr.lvalue.place.effect = Effect.Mutate;
701 + state.define(instr.lvalue, instrValue);
702 + instr.lvalue.effect = Effect.Mutate;
703 continue;
704 }
705 case "PropertyStore": {
@@ -711,8 +711,8 @@ function inferBlock(
711 state.reference(instrValue.object, Effect.Store);
712
713 const lvalue = instr.lvalue;
714 - state.alias(lvalue.place, instrValue.value);
715 - lvalue.place.effect = Effect.Store;
714 + state.alias(lvalue, instrValue.value);
715 + lvalue.effect = Effect.Store;
716 continue;
717 }
718 case "PropertyLoad": {
@@ -729,9 +729,9 @@ function inferBlock(
729
730 state.reference(instrValue.object, Effect.Read);
731 const lvalue = instr.lvalue;
732 - lvalue.place.effect = Effect.Mutate;
732 + lvalue.effect = Effect.Mutate;
733 state.initialize(instrValue, state.kind(instrValue.object));
734 - state.define(lvalue.place, instrValue);
734 + state.define(lvalue, instrValue);
735 continue;
736 }
737 case "ComputedStore": {
@@ -744,8 +744,8 @@ function inferBlock(
744 state.reference(instrValue.object, Effect.Store);
745
746 const lvalue = instr.lvalue;
747 - state.alias(lvalue.place, instrValue.value);
748 - lvalue.place.effect = Effect.Store;
747 + state.alias(lvalue, instrValue.value);
748 + lvalue.effect = Effect.Store;
749 continue;
750 }
751 case "ComputedLoad": {
@@ -763,9 +763,9 @@ function inferBlock(
763 state.reference(instrValue.object, Effect.Read);
764 state.reference(instrValue.property, Effect.Read);
765 const lvalue = instr.lvalue;
766 - lvalue.place.effect = Effect.Mutate;
766 + lvalue.effect = Effect.Mutate;
767 state.initialize(instrValue, state.kind(instrValue.object));
768 - state.define(lvalue.place, instrValue);
768 + state.define(lvalue, instrValue);
769 continue;
770 }
771 case "TypeCastExpression": {
@@ -778,16 +778,16 @@ function inferBlock(
778 state.initialize(instrValue, state.kind(instrValue.value));
779 state.reference(instrValue.value, Effect.Read);
780 const lvalue = instr.lvalue;
781 - lvalue.place.effect = Effect.Mutate;
782 - state.alias(lvalue.place, instrValue.value);
781 + lvalue.effect = Effect.Mutate;
782 + state.alias(lvalue, instrValue.value);
783 continue;
784 }
785 case "LoadLocal": {
786 state.reference(instrValue.place, Effect.Capture);
787 const lvalue = instr.lvalue;
788 - lvalue.place.effect = Effect.Mutate;
788 + lvalue.effect = Effect.Mutate;
789 // direct aliasing: `a = b`;
790 - state.alias(lvalue.place, instrValue.place);
790 + state.alias(lvalue, instrValue.place);
791 continue;
792 }
793 case "StoreLocal": {
@@ -799,8 +799,8 @@ function inferBlock(
799 state.reference(instrValue.value, effect);
800
801 const lvalue = instr.lvalue;
802 - state.alias(lvalue.place, instrValue.value);
803 - lvalue.place.effect = Effect.Store;
802 + state.alias(lvalue, instrValue.value);
803 + lvalue.effect = Effect.Store;
804 state.alias(instrValue.lvalue.place, instrValue.value);
805 instrValue.lvalue.place.effect = Effect.Store;
806 continue;
@@ -820,8 +820,8 @@ function inferBlock(
820 }
821
822 state.initialize(instrValue, valueKind);
823 - state.define(instr.lvalue.place, instrValue);
824 - instr.lvalue.place.effect = lvalueEffect;
823 + state.define(instr.lvalue, instrValue);
824 + instr.lvalue.effect = lvalueEffect;
825 }
826
827 const effect =
compiler/forget/src/Optimization/ConstantPropagation.ts
+1 -1
@@ -105,7 +105,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
105 const value = evaluateInstruction(constants, instr);
106 if (value !== null) {
107 instr.value = value;
108 - constants.set(instr.lvalue.place.identifier.id, value);
108 + constants.set(instr.lvalue.identifier.id, value);
109 }
110 }
111
compiler/forget/src/Optimization/DeadCodeElimination.ts
+3 -3
@@ -39,14 +39,14 @@ export function deadCodeElimination(fn: HIRFunction): void {
39 for (let i = block.instructions.length - 1; i >= 0; i--) {
40 const instr = block.instructions[i]!;
41 if (
42 - !used.has(instr.lvalue.place.identifier) &&
42 + !used.has(instr.lvalue.identifier) &&
43 pruneableValue(instr.value, used) &&
44 // Can't prune the last value of a value block, that's its value!
45 !(block.kind !== "block" && i === block.instructions.length - 1)
46 ) {
47 continue;
48 }
49 - used.add(instr.lvalue.place.identifier);
49 + used.add(instr.lvalue.identifier);
50 for (const operand of eachInstructionValueOperand(instr.value)) {
51 used.add(operand.identifier);
52 }
@@ -67,7 +67,7 @@ export function deadCodeElimination(fn: HIRFunction): void {
67 }
68 }
69 retainWhere(block.instructions, (instr) =>
70 - used.has(instr.lvalue.place.identifier)
70 + used.has(instr.lvalue.identifier)
71 );
72 }
73 }
compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts
+2 -7
@@ -7,7 +7,6 @@
7
8 import {
9 InstructionId,
10 - LValue,
10 Place,
11 ReactiveBlock,
12 ReactiveFunction,
@@ -74,12 +73,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
73 state.visitScope(scope);
74 }
75 }
77 - override visitLValue(
78 - id: InstructionId,
79 - lvalue: LValue,
80 - state: Context
81 - ): void {
82 - const scope = getPlaceScope(id, lvalue.place);
76 + override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
77 + const scope = getPlaceScope(id, lvalue);
78 if (scope !== null) {
79 state.visitScope(scope);
80 }
compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts
+1 -1
@@ -188,7 +188,7 @@ export function getInstructionScope({
188 "Expected lvalues to not be null when assigning scopes. " +
189 "Pruning lvalues too early can result in missing scope information."
190 );
191 - const lvalueScope = getPlaceScope(id, lvalue.place);
191 + const lvalueScope = getPlaceScope(id, lvalue);
192 if (lvalueScope !== null) {
193 return lvalueScope;
194 }
compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts
+5 -6
@@ -18,7 +18,6 @@ import {
18 } from "../HIR";
19 import {
20 HIRFunction,
21 - InstructionKind,
21 ReactiveBreakTerminal,
22 ReactiveContinueTerminal,
23 ReactiveFunction,
@@ -471,7 +470,7 @@ class Driver {
470 kind: "instruction",
471 instruction: {
472 id: terminal.id,
474 - lvalue: { kind: InstructionKind.Const, place },
473 + lvalue: place,
474 value,
475 loc: terminal.loc,
476 },
@@ -544,7 +543,7 @@ class Driver {
543 const instr = defaultBlock.instructions[0]!;
544 return {
545 block: defaultBlock.id,
547 - place: instr.lvalue!.place,
546 + place: instr.lvalue!,
547 value: instr.value,
548 id: instr.id,
549 };
@@ -559,7 +558,7 @@ class Driver {
558 };
559 return {
560 block: defaultBlock.id,
562 - place: instr.lvalue!.place,
561 + place: instr.lvalue!,
562 value: sequence,
563 id: instr.id,
564 };
@@ -578,7 +577,7 @@ class Driver {
577 {
578 id: init.id,
579 loc,
581 - lvalue: { kind: InstructionKind.Const, place: init.place },
580 + lvalue: init.place,
581 value: init.value,
582 },
583 ],
@@ -621,7 +620,7 @@ class Driver {
620 {
621 id: test.id,
622 loc: terminal.loc,
624 - lvalue: { kind: InstructionKind.Const, place: test.place },
623 + lvalue: test.place,
624 value: test.value,
625 },
626 ],
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+17 -28
@@ -488,38 +488,27 @@ function codegenInstruction(
488 if (instr.lvalue === null) {
489 return t.expressionStatement(value);
490 }
491 - if (instr.lvalue.place.identifier.name === null) {
491 + if (instr.lvalue.identifier.name === null) {
492 // temporary
493 - cx.temp.set(instr.lvalue.place.identifier.id, value);
493 + cx.temp.set(instr.lvalue.identifier.id, value);
494 return t.emptyStatement();
495 } else {
496 - if (instr.lvalue.kind !== InstructionKind.Const) {
497 - CompilerError.invariant(
498 - `Expected all instruction lvalues to be const declarations`,
499 - instr.lvalue.place.loc
500 - );
501 - }
502 - const kind = cx.hasDeclared(instr.lvalue.place.identifier)
496 + const kind = cx.hasDeclared(instr.lvalue.identifier)
497 ? InstructionKind.Reassign
504 - : instr.lvalue.kind;
505 - switch (kind) {
506 - case InstructionKind.Const: {
507 - return createVariableDeclaration(instr.loc, "const", [
508 - t.variableDeclarator(codegenLVal(instr.lvalue), value),
509 - ]);
510 - }
511 - case InstructionKind.Reassign: {
512 - return createExpressionStatement(
513 - instr.loc,
514 - t.assignmentExpression("=", codegenLVal(instr.lvalue), value)
515 - );
516 - }
517 - default: {
518 - assertExhaustive(
519 - kind,
520 - `Unexpected instruction kind '${instr.lvalue.kind}'`
521 - );
522 - }
498 + : InstructionKind.Const;
499 + if (cx.hasDeclared(instr.lvalue.identifier)) {
500 + return createExpressionStatement(
501 + instr.loc,
502 + t.assignmentExpression(
503 + "=",
504 + convertIdentifier(instr.lvalue.identifier),
505 + value
506 + )
507 + );
508 + } else {
509 + return createVariableDeclaration(instr.loc, "const", [
510 + t.variableDeclarator(convertIdentifier(instr.lvalue.identifier), value),
511 + ]);
512 }
513 }
514 }
compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts
+2 -2
@@ -63,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
63 // allow treating safe hooks as non-reactive.
64 hasReactiveInput = true;
65 }
66 - state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput);
66 + state.reactivityMap.set(lval.identifier.id, hasReactiveInput);
67
68 if (hasReactiveInput) {
69 // all mutating effects must also be marked as reactive
@@ -98,7 +98,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
98 if (instr.lvalue !== null) {
99 if (instr.value.kind === "LoadLocal") {
100 state.temporaries.set(
101 - instr.lvalue.place.identifier.id,
101 + instr.lvalue.identifier.id,
102 instr.value.place.identifier.id
103 );
104 }
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+2 -2
@@ -98,9 +98,9 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
98
99 for (const instr of block.instructions) {
100 const operands: Array<Identifier> = [];
101 - const range = instr.lvalue.place.identifier.mutableRange;
101 + const range = instr.lvalue.identifier.mutableRange;
102 if (range.end > range.start + 1 || mayAllocate(instr.value)) {
103 - operands.push(instr.lvalue!.place.identifier);
103 + operands.push(instr.lvalue!.identifier);
104 }
105 if (instr.value.kind === "StoreLocal") {
106 if (
compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts
+2 -7
@@ -7,7 +7,6 @@
7
8 import {
9 InstructionId,
10 - LValue,
10 makeInstructionId,
11 Place,
12 ReactiveBlock,
@@ -113,12 +112,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
112 override visitPlace(id: InstructionId, place: Place, state: Context): void {
113 state.visitPlace(id, place);
114 }
116 - override visitLValue(
117 - id: InstructionId,
118 - lvalue: LValue,
119 - state: Context
120 - ): void {
121 - state.visitPlace(id, lvalue.place);
115 + override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
116 + state.visitPlace(id, lvalue);
117 }
118 override visitBlock(block: ReactiveBlock, state: Context): void {
119 state.enter(() => {
compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts
+3 -2
@@ -17,7 +17,6 @@ import {
17 import {
18 printIdentifier,
19 printInstructionValue,
20 - printLValue,
20 printPlace,
21 } from "../HIR/PrintHIR";
22 import { assertExhaustive } from "../Utils/utils";
@@ -85,7 +84,9 @@ function printReactiveInstruction(
84 const id = `[${instruction.id}]`;
85
86 if (instruction.lvalue !== null) {
88 - writer.write(`${id} ${printLValue(instruction.lvalue)} = `);
87 + writer.write(
88 + `${id} ${printIdentifier(instruction.lvalue.identifier)} = `
89 + );
90 printReactiveValue(writer, instruction.value);
91 writer.newline();
92 } else {
compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts
+2 -2
@@ -56,10 +56,10 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
56 this.traverseInstruction(instruction, state);
57 if (
58 instruction.lvalue !== null &&
59 - instruction.lvalue.place.identifier.name === null &&
59 + instruction.lvalue.identifier.name === null &&
60 instruction.value.kind !== "LoadLocal"
61 ) {
62 - state.temporaries.set(instruction.lvalue.place.identifier, 0);
62 + state.temporaries.set(instruction.lvalue.identifier, 0);
63 }
64 }
65 }
compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+5 -6
@@ -11,7 +11,6 @@ import {
11 IdentifierId,
12 InstructionId,
13 InstructionKind,
14 - LValue,
14 makeInstructionId,
15 Place,
16 ReactiveBlock,
@@ -680,20 +679,20 @@ function visitInstructionValue(
679 context: Context,
680 id: InstructionId,
681 value: ReactiveValue,
683 - lvalue: LValue | null
682 + lvalue: Place | null
683 ): void {
684 if (value.kind === "LoadLocal" && lvalue !== null) {
685 if (
686 value.place.identifier.name !== null &&
688 - lvalue.place.identifier.name === null
687 + lvalue.identifier.name === null
688 ) {
690 - context.declareTemporary(lvalue.place, value.place);
689 + context.declareTemporary(lvalue, value.place);
690 } else {
691 context.visitOperand(value.place);
692 }
693 } else if (value.kind === "PropertyLoad") {
694 if (lvalue !== null) {
696 - context.declareProperty(lvalue.place, value.object, value.property);
695 + context.declareProperty(lvalue, value.object, value.property);
696 } else {
697 context.visitProperty(value.object, value.property);
698 }
@@ -717,7 +716,7 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void {
716 if (lvalue == null) {
717 return;
718 }
720 - context.declare(lvalue.place.identifier, {
719 + context.declare(lvalue.identifier, {
720 id: instr.id,
721 scope: context.currentScope,
722 });
compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts
+2 -4
@@ -8,7 +8,6 @@
8 import {
9 Identifier,
10 InstructionId,
11 - InstructionKind,
11 Place,
12 ReactiveFunction,
13 ReactiveInstruction,
@@ -40,10 +39,9 @@ class Visitor extends ReactiveFunctionVisitor<LValues> {
39 this.traverseInstruction(instruction, state);
40 if (
41 instruction.lvalue !== null &&
43 - instruction.lvalue.kind === InstructionKind.Const &&
44 - instruction.lvalue.place.identifier.name === null
42 + instruction.lvalue.identifier.name === null
43 ) {
46 - state.set(instruction.lvalue.place.identifier, instruction);
44 + state.set(instruction.lvalue.identifier, instruction);
45 }
46 }
47 }
compiler/forget/src/ReactiveScopes/RenameVariables.ts
+1 -1
@@ -60,7 +60,7 @@ class Visitor extends ReactiveFunctionVisitor<Scopes> {
60 state.visit(operand.identifier);
61 }
62 if (instruction.lvalue !== null) {
63 - state.visit(instruction.lvalue.place.identifier);
63 + state.visit(instruction.lvalue.identifier);
64 }
65 }
66 override visitScope(scope: ReactiveScopeBlock, state: Scopes): void {
compiler/forget/src/ReactiveScopes/visitors.ts
+1 -2
@@ -7,7 +7,6 @@
7
8 import {
9 InstructionId,
10 - LValue,
10 Place,
11 ReactiveBlock,
12 ReactiveFunction,
@@ -31,7 +30,7 @@ export function visitReactiveFunction<TState>(
30
31 export class ReactiveFunctionVisitor<TState = void> {
32 visitID(_id: InstructionId, _state: TState): void {}
34 - visitLValue(_id: InstructionId, _lvalue: LValue, _state: TState): void {}
33 + visitLValue(_id: InstructionId, _lvalue: Place, _state: TState): void {}
34 visitPlace(_id: InstructionId, _place: Place, _state: TState): void {}
35
36 visitValue(id: InstructionId, value: ReactiveValue, state: TState): void {
compiler/forget/src/SSA/EliminateRedundantPhi.ts
+1 -1
@@ -82,7 +82,7 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
82 for (const place of eachInstructionOperand(instr)) {
83 rewritePlace(place, rewrites);
84 }
85 - rewritePlace(instr.lvalue.place, rewrites);
85 + rewritePlace(instr.lvalue, rewrites);
86 }
87
88 // Rewrite all terminal operands
compiler/forget/src/SSA/EnterSSA.ts
+2 -5
@@ -7,7 +7,6 @@ import {
7 HIRFunction,
8 Identifier,
9 IdentifierId,
10 - InstructionKind,
10 makeInstructionId,
11 makeType,
12 Phi,
@@ -215,7 +214,6 @@ export default function enterSSA(func: HIRFunction): void {
214 if (instr.value.kind === "StoreLocal") {
215 const oldPlace = instr.value.lvalue.place;
216 const newPlace = builder.definePlace(oldPlace);
218 - instr.lvalue.kind = InstructionKind.Const;
217 instr.value.lvalue.place = newPlace;
218
219 instr.value.value = builder.getPlace(instr.value.value);
@@ -223,10 +221,9 @@ export default function enterSSA(func: HIRFunction): void {
221 mapInstructionOperands(instr, (place) => builder.getPlace(place));
222 }
223
226 - const oldPlace = instr.lvalue.place;
224 + const oldPlace = instr.lvalue;
225 const newPlace = builder.definePlace(oldPlace);
228 - instr.lvalue.kind = InstructionKind.Const;
229 - instr.lvalue.place = newPlace;
226 + instr.lvalue = newPlace;
227 }
228
229 mapTerminalOperands(block.terminal, (place) => builder.getPlace(place));
compiler/forget/src/SSA/LeaveSSA.ts
+13 -30
@@ -112,17 +112,6 @@ export function leaveSSA(fn: HIRFunction): void {
112 // `let` or `reassign` where possible.
113 const { lvalue, value } = instr;
114 if (
115 - lvalue.kind === InstructionKind.Const &&
116 - rewrites.has(lvalue.place.identifier)
117 - ) {
118 - // For rewrites, the declaration of the canonical identifier has to be `let`,
119 - // all other assignments are reassignments (which we annotate for codegen
120 - // purposes).
121 - lvalue.kind =
122 - rewrites.get(lvalue.place.identifier) === lvalue.place.identifier
123 - ? InstructionKind.Let
124 - : InstructionKind.Reassign;
125 - } else if (
115 value.kind === "StoreLocal" &&
116 value.lvalue.place.identifier.name != null
117 ) {
@@ -147,7 +136,7 @@ export function leaveSSA(fn: HIRFunction): void {
136 ? InstructionKind.Let
137 : InstructionKind.Reassign;
138 }
150 - rewritePlace(lvalue.place, rewrites, declarations);
139 + rewritePlace(lvalue, rewrites, declarations);
140 for (const operand of eachInstructionValueOperand(instr.value)) {
141 rewritePlace(operand, rewrites, declarations);
142 }
@@ -260,10 +249,7 @@ export function leaveSSA(fn: HIRFunction): void {
249 };
250 block.instructions.push({
251 id: block.terminal.id,
263 - lvalue: {
264 - place: { ...initValue, effect: Effect.Mutate },
265 - kind: InstructionKind.Const,
266 - },
252 + lvalue: { ...initValue, effect: Effect.Mutate },
253 value: {
254 kind: "Primitive",
255 // TODO: consider leaving the variable uninitialized rather than explicitly undefined.
@@ -295,22 +281,19 @@ export function leaveSSA(fn: HIRFunction): void {
281 // the if) to the phi, so it's safe to reuse the terminal's id.
282 id: block.terminal.id,
283 lvalue: {
298 - place: {
299 - kind: "Identifier",
300 - identifier: {
301 - id: fn.env.nextIdentifierId,
302 - mutableRange: {
303 - start: block.terminal.id,
304 - end: makeInstructionId(block.terminal.id + 1),
305 - },
306 - name: null,
307 - scope: null,
308 - type: phi.id.type,
284 + kind: "Identifier",
285 + identifier: {
286 + id: fn.env.nextIdentifierId,
287 + mutableRange: {
288 + start: block.terminal.id,
289 + end: makeInstructionId(block.terminal.id + 1),
290 },
310 - effect: Effect.Mutate,
311 - loc: GeneratedSource,
291 + name: null,
292 + scope: null,
293 + type: phi.id.type,
294 },
313 - kind: InstructionKind.Const,
295 + effect: Effect.Mutate,
296 + loc: GeneratedSource,
297 },
298 value: {
299 kind: "StoreLocal",
compiler/forget/src/TypeInference/InferTypes.ts
+2 -2
@@ -54,7 +54,7 @@ function apply(func: HIRFunction, unifier: Unifier) {
54 place.identifier.type = unifier.get(place.identifier.type);
55 }
56 const { lvalue } = instr;
57 - lvalue.place.identifier.type = unifier.get(lvalue.place.identifier.type);
57 + lvalue.identifier.type = unifier.get(lvalue.identifier.type);
58 }
59 }
60 }
@@ -93,7 +93,7 @@ function* generateInstructionTypes(
93 instr: Instruction
94 ): Generator<TypeEquation, void, undefined> {
95 const { lvalue, value } = instr;
96 - const left = lvalue.place.identifier.type;
96 + const left = lvalue.identifier.type;
97
98 switch (value.kind) {
99 case "JSXText":