diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts index 3ef1830af3..c4d7b78204 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts @@ -897,6 +897,7 @@ export type InstructionValue = loc: SourceLocation; } | LoadGlobal + | StoreGlobal | FunctionExpression | { kind: "TaggedTemplateExpression"; @@ -1030,6 +1031,13 @@ export type LoadGlobal = { loc: SourceLocation; }; +export type StoreGlobal = { + kind: "StoreGlobal"; + name: string; + value: Place; + loc: SourceLocation; +}; + export type BuiltinTag = { kind: "BuiltinTag"; name: string; diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts index 917386919e..ceaf05e698 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/PrintHIR.ts @@ -571,7 +571,13 @@ export function printInstructionValue(instrValue: ReactiveValue): string { break; } case "LoadGlobal": { - value = `Global ${instrValue.name}`; + value = `LoadGlobal ${instrValue.name}`; + break; + } + case "StoreGlobal": { + value = `StoreGlobal ${instrValue.name} = ${printPlace( + instrValue.value + )}`; break; } case "OptionalExpression": { diff --git a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts index 43796ff365..11ce4db691 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/visitors.ts @@ -93,6 +93,10 @@ export function* eachInstructionValueOperand( yield instrValue.value; break; } + case "StoreGlobal": { + yield instrValue.value; + break; + } case "Destructure": { yield instrValue.value; break; @@ -421,6 +425,10 @@ export function mapInstructionValueOperands( instrValue.value = fn(instrValue.value); break; } + case "StoreGlobal": { + instrValue.value = fn(instrValue.value); + break; + } case "Destructure": { instrValue.value = fn(instrValue.value); break; diff --git a/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts b/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts index 6f058e678d..b779e0a284 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts @@ -1572,6 +1572,17 @@ function inferBlock( lvalue.effect = Effect.Store; continue; } + case "StoreGlobal": { + state.reference( + instrValue.value, + functionEffects, + Effect.Capture, + ValueReason.Other + ); + const lvalue = instr.lvalue; + lvalue.effect = Effect.Store; + continue; + } case "Destructure": { let effect: Effect = Effect.Capture; for (const place of eachPatternOperand(instrValue.lvalue.pattern)) { diff --git a/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts b/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts index cc0e5a12ca..feb46c973e 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Optimization/DeadCodeElimination.ts @@ -310,7 +310,8 @@ function pruneableValue(value: InstructionValue, state: State): boolean { case "ComputedStore": case "PropertyDelete": case "MethodCall": - case "PropertyStore": { + case "PropertyStore": + case "StoreGlobal": { /* * Mutating instructions are not safe to prune. * TODO: we could be more precise and make this conditional on whether diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts index 6aed512d84..e33c054c3c 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -1813,6 +1813,14 @@ function codegenInstructionValue( ); break; } + case "StoreGlobal": { + value = t.assignmentExpression( + "=", + t.identifier(instrValue.name), + codegenPlaceToExpression(cx, instrValue.value) + ); + break; + } case "ReactiveFunctionValue": case "StartMemoize": case "FinishMemoize": diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index 6942eea99e..22b767b725 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -195,7 +195,8 @@ function mayAllocate(env: Environment, instruction: Instruction): boolean { case "FinishMemoize": case "UnaryExpression": case "BinaryExpression": - case "PropertyLoad": { + case "PropertyLoad": + case "StoreGlobal": { return false; } case "CallExpression": diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts index ed25ce77d0..3d3e3cd25e 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -571,6 +571,17 @@ function computeMemoizationInputs( rvalues: [value.value], }; } + case "StoreGlobal": { + const lvalues = []; + if (lvalue !== null) { + lvalues.push({ place: lvalue, level: MemoizationLevel.Unmemoized }); + } + + return { + lvalues, + rvalues: [value.value], + }; + } case "Destructure": { // Indirection for the inner value, memoized if the value is const lvalues = []; diff --git a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts index 627332d50d..f1ba094840 100644 --- a/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/TypeInference/InferTypes.ts @@ -174,6 +174,11 @@ function* generateInstructionTypes( break; } + case "StoreGlobal": { + yield equation(left, value.value.identifier.type); + break; + } + case "BinaryExpression": { if (isPrimitiveBinaryOp(value.operator)) { yield equation(value.left.identifier.type, { kind: "Primitive" });