@samitouri / QOS-React-2 / commits / 2cb1c72305

Scaffolding for ExpressionStatement instruction kind

Adds an `ExpressionStatement` instruction variant to model values that are otherwise "unused" but which we don't want to remove. The next diff changes BuildHIR to use this where appropriate.

Joe Savona committed Apr 26, 2023 at 11:27 UTC 2cb1c723051378a3e94bec445f135a457d93f04f
9 files changed +35 -2
compiler/forget/src/HIR/HIR.ts
+8
@@ -702,6 +702,14 @@ export type InstructionValue =
702 value: Place; // the collection
703 loc: SourceLocation;
704 }
705 + // Represents a value that is unused but which we want to ensure is not dropped
706 + // Examples include logical or ternary expressions that appear as expression statements,
707 + // that appear only for their side effects
708 + | {
709 + kind: "ExpressionStatement";
710 + value: Place;
711 + loc: SourceLocation;
712 + }
713 /**
714 * Catch-all for statements such as type imports, nested class declarations, etc
715 * which are not directly represented, but included for completeness and to allow
compiler/forget/src/HIR/PrintHIR.ts
+4
@@ -474,6 +474,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
474 value = `NextIterableOf ${printPlace(instrValue.value)}`;
475 break;
476 }
477 + case "ExpressionStatement": {
478 + value = `ExpressionStatement ${printPlace(instrValue.value)}`;
479 + break;
480 + }
481 default: {
482 assertExhaustive(
483 instrValue,
compiler/forget/src/HIR/visitors.ts
+8
@@ -180,6 +180,10 @@ export function* eachInstructionValueOperand(
180 yield instrValue.value;
181 break;
182 }
183 + case "ExpressionStatement": {
184 + yield instrValue.value;
185 + break;
186 + }
187 case "RegExpLiteral":
188 case "LoadGlobal":
189 case "UnsupportedNode":
@@ -443,6 +447,10 @@ export function mapInstructionOperands(
447 instrValue.value = fn(instrValue.value);
448 break;
449 }
450 + case "ExpressionStatement": {
451 + instrValue.value = fn(instrValue.value);
452 + break;
453 + }
454 case "RegExpLiteral":
455 case "LoadGlobal":
456 case "UnsupportedNode":
compiler/forget/src/Inference/InferReferenceEffects.ts
+1
@@ -807,6 +807,7 @@ function inferBlock(
807 state.alias(lvalue, instrValue.value);
808 continue;
809 }
810 + case "ExpressionStatement":
811 case "TypeCastExpression": {
812 // A type cast expression has no effect at runtime, so it's equivalent to a raw
813 // identifier:
compiler/forget/src/Optimization/DeadCodeElimination.ts
+5
@@ -190,6 +190,11 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
190 }
191 return true;
192 }
193 + case "ExpressionStatement": {
194 + // We create ExpressionStatements specifically for expressions that would otherwise
195 + // be dropped but which we don't want to eliminate.
196 + return false;
197 + }
198 case "Await":
199 case "CallExpression":
200 case "ComputedDelete":
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+4
@@ -996,6 +996,10 @@ function codegenInstructionValue(
996 value = codegenPlace(cx, instrValue.value);
997 break;
998 }
999 + case "ExpressionStatement": {
1000 + value = codegenPlace(cx, instrValue.value);
1001 + break;
1002 + }
1003 case "DeclareLocal":
1004 case "Destructure":
1005 case "StoreLocal": {
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+2 -1
@@ -234,7 +234,8 @@ function mayAllocate(value: InstructionValue): boolean {
234 case "UnaryExpression":
235 case "TemplateLiteral":
236 case "Primitive":
237 - case "NextIterableOf": {
237 + case "NextIterableOf":
238 + case "ExpressionStatement": {
239 return false;
240 }
241 case "RegExpLiteral":
compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts
+2 -1
@@ -436,7 +436,8 @@ function computeMemoizationInputs(
436 }
437 case "Await":
438 case "TypeCastExpression":
439 - case "NextIterableOf": {
439 + case "NextIterableOf":
440 + case "ExpressionStatement": {
441 return {
442 // Indirection for the inner value, memoized if the value is
443 lvalues:
compiler/forget/src/TypeInference/InferTypes.ts
+1
@@ -210,6 +210,7 @@ function* generateInstructionTypes(
210 case "TemplateLiteral":
211 case "Await":
212 case "NextIterableOf":
213 + case "ExpressionStatement":
214 case "UnsupportedNode":
215 break;
216 default: