From be7f98d5841d16dc553eeb58f372be9cb6e3a05a Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Wed, 27 Sep 2023 14:04:02 -0400 Subject: [PATCH] Scaffolding for rest params Updates HIR to represent rest element function parameters. We don't construct these yet. --- .../babel-plugin-react-forget/src/HIR/HIR.ts | 4 ++-- .../src/Inference/InferReferenceEffects.ts | 24 ++++++++++++++----- .../ReactiveScopes/CodegenReactiveFunction.ts | 18 ++++++++++++-- .../InferReactiveIdentifiers.ts | 6 ++++- .../ReactiveScopes/PrintReactiveFunction.ts | 6 ++++- .../PropagateScopeDependencies.ts | 15 ++++++++---- .../ReactiveScopes/PruneNonEscapingScopes.ts | 6 ++++- .../src/ReactiveScopes/RenameVariables.ts | 6 ++++- .../src/SSA/EnterSSA.ts | 24 +++++++++++++++---- .../src/SSA/LeaveSSA.ts | 9 +++---- 10 files changed, 92 insertions(+), 26 deletions(-) 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 2d9772dd58..5821cf1f4d 100644 --- a/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts +++ b/compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts @@ -48,7 +48,7 @@ export type SourceLocation = t.SourceLocation | typeof GeneratedSource; export type ReactiveFunction = { loc: SourceLocation; id: string | null; - params: Array; + params: Array; generator: boolean; async: boolean; body: ReactiveBlock; @@ -232,7 +232,7 @@ export type HIRFunction = { loc: SourceLocation; id: string | null; env: Environment; - params: Array; + params: Array; context: Array; body: HIR; generator: boolean; 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 8cdabd16de..3d1cafae50 100644 --- a/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts @@ -110,13 +110,25 @@ export default function inferReferenceEffects( ? ValueKind.Mutable : ValueKind.Frozen; for (const param of fn.params) { - const value: InstructionValue = { - kind: "Primitive", - loc: param.loc, - value: undefined, - }; + let value: InstructionValue; + let place: Place; + if (param.kind === "Identifier") { + place = param; + value = { + kind: "Primitive", + loc: param.loc, + value: undefined, + }; + } else { + place = param.place; + value = { + kind: "Primitive", + loc: param.place.loc, + value: undefined, + }; + } initialState.initialize(value, paramKind); - initialState.define(param, value); + initialState.define(place, value); } // Map of blocks to the last (merged) incoming state that was processed 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 2bcaf28a2b..f4338ad1a8 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -54,10 +54,14 @@ export function codegenReactiveFunction( ): Result { const cx = new Context(fn.env, fn.id ?? "[[ anonymous ]]"); for (const param of fn.params) { - cx.temp.set(param.identifier.id, null); + if (param.kind === "Identifier") { + cx.temp.set(param.identifier.id, null); + } else { + cx.temp.set(param.place.identifier.id, null); + } } - const params = fn.params.map((param) => convertIdentifier(param.identifier)); + const params = fn.params.map((param) => convertParameter(param)); const body = codegenBlock(cx, fn.body); const statements = body.body; if (statements.length !== 0) { @@ -97,6 +101,16 @@ export function codegenReactiveFunction( }); } +function convertParameter( + param: Place | SpreadPattern +): t.Identifier | t.RestElement { + if (param.kind === "Identifier") { + return convertIdentifier(param.identifier); + } else { + return t.restElement(convertIdentifier(param.place.identifier)); + } +} + class Context { env: Environment; fnName: string; diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveIdentifiers.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveIdentifiers.ts index 49c7537d34..0d350523cf 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveIdentifiers.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveIdentifiers.ts @@ -188,7 +188,11 @@ export function inferReactiveIdentifiers( const visitor = new Visitor(); const state = new State(fn.env); for (const param of fn.params) { - state.reactivityMap.set(param.identifier.id, true); + if (param.kind === "Identifier") { + state.reactivityMap.set(param.identifier.id, true); + } else { + state.reactivityMap.set(param.place.identifier.id, true); + } } visitReactiveFunction(fn, visitor, state); diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts index a5ccaea307..14cf29f6f5 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts @@ -27,7 +27,11 @@ export function printReactiveFunction(fn: ReactiveFunction): string { writer.writeLine(`function ${fn.id !== null ? fn.id : ""}(`); writer.indented(() => { for (const param of fn.params) { - writer.writeLine(`${printPlace(param)},`); + if (param.kind === "Identifier") { + writer.writeLine(`${printPlace(param)},`); + } else { + writer.writeLine(`...${printPlace(param.place)},`); + } } }); writer.writeLine(") {"); diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 1f62408140..68ea6a1248 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -50,10 +50,17 @@ export function propagateScopeDependencies(fn: ReactiveFunction): void { const context = new Context(escapingTemporaries.usedOutsideDeclaringScope); for (const param of fn.params) { - context.declare(param.identifier, { - id: makeInstructionId(0), - scope: empty(), - }); + if (param.kind === "Identifier") { + context.declare(param.identifier, { + id: makeInstructionId(0), + scope: empty(), + }); + } else { + context.declare(param.place.identifier, { + id: makeInstructionId(0), + scope: empty(), + }); + } } visitReactiveFunction(fn, new PropagationVisitor(), context); } 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 40a2364704..76ab5f9e79 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -117,7 +117,11 @@ export function pruneNonEscapingScopes( // and which values are returned. const state = new State(fn.env); for (const param of fn.params) { - state.declare(param.identifier.id); + if (param.kind === "Identifier") { + state.declare(param.identifier.id); + } else { + state.declare(param.place.identifier.id); + } } visitReactiveFunction( fn, diff --git a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts index 3878f8ea95..152ed3d1c6 100644 --- a/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts +++ b/compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts @@ -34,7 +34,11 @@ export function renameVariables(fn: ReactiveFunction): void { const scopes = new Scopes(); scopes.enter(() => { for (const param of fn.params) { - scopes.visit(param.identifier); + if (param.kind === "Identifier") { + scopes.visit(param.identifier); + } else { + scopes.visit(param.place.identifier); + } } visitReactiveFunction(fn, new Visitor(), scopes); }); diff --git a/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts b/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts index d96ade703e..918d1faa36 100644 --- a/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts +++ b/compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts @@ -259,7 +259,16 @@ function enterSSAImpl( loc: func.loc, suggestions: null, }); - func.params = func.params.map((p) => builder.definePlace(p)); + func.params = func.params.map((param) => { + if (param.kind === "Identifier") { + return builder.definePlace(param); + } else { + return { + kind: "Spread", + place: builder.definePlace(param.place), + }; + } + }); } for (const instr of block.instructions) { @@ -282,9 +291,16 @@ function enterSSAImpl( loweredFunc.context = loweredFunc.context.map((p) => builder.getPlace(p) ); - loweredFunc.params = loweredFunc.params.map((p) => - builder.definePlace(p) - ); + loweredFunc.params = loweredFunc.params.map((param) => { + if (param.kind === "Identifier") { + return builder.definePlace(param); + } else { + return { + kind: "Spread", + place: builder.definePlace(param.place), + }; + } + }); enterSSAImpl(loweredFunc, builder, rootEntry); }); entry.preds.clear(); diff --git a/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts b/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts index bb8a49e762..39374b02da 100644 --- a/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts +++ b/compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts @@ -100,13 +100,14 @@ export function leaveSSA(fn: HIRFunction): void { > = new Map(); for (const param of fn.params) { - if (param.identifier.name !== null) { - declarations.set(param.identifier.name, { + let place: Place = param.kind === "Identifier" ? param : param.place; + if (place.identifier.name !== null) { + declarations.set(place.identifier.name, { lvalue: { kind: InstructionKind.Let, - place: param, + place, }, - place: param, + place, }); } }