Scaffolding for rest params
Updates HIR to represent rest element function parameters. We don't construct these yet.
Joe Savona committed
Sep 27, 2023 at 14:04 UTC
be7f98d5841d16dc553eeb58f372be9cb6e3a05a
10 files changed
+92
-26
compiler/packages/babel-plugin-react-forget/src/HIR/HIR.ts
+2
-2
@@ -48,7 +48,7 @@ export type SourceLocation = t.SourceLocation | typeof GeneratedSource;
48
export type ReactiveFunction = {
49
loc: SourceLocation;
50
id: string | null;
51
- params: Array<Place>;
51
+ params: Array<Place | SpreadPattern>;
52
generator: boolean;
53
async: boolean;
54
body: ReactiveBlock;
@@ -232,7 +232,7 @@ export type HIRFunction = {
232
loc: SourceLocation;
233
id: string | null;
234
env: Environment;
235
- params: Array<Place>;
235
+ params: Array<Place | SpreadPattern>;
236
context: Array<Place>;
237
body: HIR;
238
generator: boolean;
compiler/packages/babel-plugin-react-forget/src/Inference/InferReferenceEffects.ts
+18
-6
@@ -110,13 +110,25 @@ export default function inferReferenceEffects(
110
? ValueKind.Mutable
111
: ValueKind.Frozen;
112
for (const param of fn.params) {
113
- const value: InstructionValue = {
114
- kind: "Primitive",
115
- loc: param.loc,
116
- value: undefined,
117
- };
113
+ let value: InstructionValue;
114
+ let place: Place;
115
+ if (param.kind === "Identifier") {
116
+ place = param;
117
+ value = {
118
+ kind: "Primitive",
119
+ loc: param.loc,
120
+ value: undefined,
121
+ };
122
+ } else {
123
+ place = param.place;
124
+ value = {
125
+ kind: "Primitive",
126
+ loc: param.place.loc,
127
+ value: undefined,
128
+ };
129
+ }
130
initialState.initialize(value, paramKind);
119
- initialState.define(param, value);
131
+ initialState.define(place, value);
132
}
133
134
// Map of blocks to the last (merged) incoming state that was processed
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+16
-2
@@ -54,10 +54,14 @@ export function codegenReactiveFunction(
54
): Result<CodegenFunction, CompilerError> {
55
const cx = new Context(fn.env, fn.id ?? "[[ anonymous ]]");
56
for (const param of fn.params) {
57
- cx.temp.set(param.identifier.id, null);
57
+ if (param.kind === "Identifier") {
58
+ cx.temp.set(param.identifier.id, null);
59
+ } else {
60
+ cx.temp.set(param.place.identifier.id, null);
61
+ }
62
}
63
60
- const params = fn.params.map((param) => convertIdentifier(param.identifier));
64
+ const params = fn.params.map((param) => convertParameter(param));
65
const body = codegenBlock(cx, fn.body);
66
const statements = body.body;
67
if (statements.length !== 0) {
@@ -97,6 +101,16 @@ export function codegenReactiveFunction(
101
});
102
}
103
104
+function convertParameter(
105
+ param: Place | SpreadPattern
106
+): t.Identifier | t.RestElement {
107
+ if (param.kind === "Identifier") {
108
+ return convertIdentifier(param.identifier);
109
+ } else {
110
+ return t.restElement(convertIdentifier(param.place.identifier));
111
+ }
112
+}
113
+
114
class Context {
115
env: Environment;
116
fnName: string;
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/InferReactiveIdentifiers.ts
+5
-1
@@ -188,7 +188,11 @@ export function inferReactiveIdentifiers(
188
const visitor = new Visitor();
189
const state = new State(fn.env);
190
for (const param of fn.params) {
191
- state.reactivityMap.set(param.identifier.id, true);
191
+ if (param.kind === "Identifier") {
192
+ state.reactivityMap.set(param.identifier.id, true);
193
+ } else {
194
+ state.reactivityMap.set(param.place.identifier.id, true);
195
+ }
196
}
197
visitReactiveFunction(fn, visitor, state);
198
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts
+5
-1
@@ -27,7 +27,11 @@ export function printReactiveFunction(fn: ReactiveFunction): string {
27
writer.writeLine(`function ${fn.id !== null ? fn.id : "<unknown>"}(`);
28
writer.indented(() => {
29
for (const param of fn.params) {
30
- writer.writeLine(`${printPlace(param)},`);
30
+ if (param.kind === "Identifier") {
31
+ writer.writeLine(`${printPlace(param)},`);
32
+ } else {
33
+ writer.writeLine(`...${printPlace(param.place)},`);
34
+ }
35
}
36
});
37
writer.writeLine(") {");
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+11
-4
@@ -50,10 +50,17 @@ export function propagateScopeDependencies(fn: ReactiveFunction): void {
50
51
const context = new Context(escapingTemporaries.usedOutsideDeclaringScope);
52
for (const param of fn.params) {
53
- context.declare(param.identifier, {
54
- id: makeInstructionId(0),
55
- scope: empty(),
56
- });
53
+ if (param.kind === "Identifier") {
54
+ context.declare(param.identifier, {
55
+ id: makeInstructionId(0),
56
+ scope: empty(),
57
+ });
58
+ } else {
59
+ context.declare(param.place.identifier, {
60
+ id: makeInstructionId(0),
61
+ scope: empty(),
62
+ });
63
+ }
64
}
65
visitReactiveFunction(fn, new PropagationVisitor(), context);
66
}
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PruneNonEscapingScopes.ts
+5
-1
@@ -117,7 +117,11 @@ export function pruneNonEscapingScopes(
117
// and which values are returned.
118
const state = new State(fn.env);
119
for (const param of fn.params) {
120
- state.declare(param.identifier.id);
120
+ if (param.kind === "Identifier") {
121
+ state.declare(param.identifier.id);
122
+ } else {
123
+ state.declare(param.place.identifier.id);
124
+ }
125
}
126
visitReactiveFunction(
127
fn,
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/RenameVariables.ts
+5
-1
@@ -34,7 +34,11 @@ export function renameVariables(fn: ReactiveFunction): void {
34
const scopes = new Scopes();
35
scopes.enter(() => {
36
for (const param of fn.params) {
37
- scopes.visit(param.identifier);
37
+ if (param.kind === "Identifier") {
38
+ scopes.visit(param.identifier);
39
+ } else {
40
+ scopes.visit(param.place.identifier);
41
+ }
42
}
43
visitReactiveFunction(fn, new Visitor(), scopes);
44
});
compiler/packages/babel-plugin-react-forget/src/SSA/EnterSSA.ts
+20
-4
@@ -259,7 +259,16 @@ function enterSSAImpl(
259
loc: func.loc,
260
suggestions: null,
261
});
262
- func.params = func.params.map((p) => builder.definePlace(p));
262
+ func.params = func.params.map((param) => {
263
+ if (param.kind === "Identifier") {
264
+ return builder.definePlace(param);
265
+ } else {
266
+ return {
267
+ kind: "Spread",
268
+ place: builder.definePlace(param.place),
269
+ };
270
+ }
271
+ });
272
}
273
274
for (const instr of block.instructions) {
@@ -282,9 +291,16 @@ function enterSSAImpl(
291
loweredFunc.context = loweredFunc.context.map((p) =>
292
builder.getPlace(p)
293
);
285
- loweredFunc.params = loweredFunc.params.map((p) =>
286
- builder.definePlace(p)
287
- );
294
+ loweredFunc.params = loweredFunc.params.map((param) => {
295
+ if (param.kind === "Identifier") {
296
+ return builder.definePlace(param);
297
+ } else {
298
+ return {
299
+ kind: "Spread",
300
+ place: builder.definePlace(param.place),
301
+ };
302
+ }
303
+ });
304
enterSSAImpl(loweredFunc, builder, rootEntry);
305
});
306
entry.preds.clear();
compiler/packages/babel-plugin-react-forget/src/SSA/LeaveSSA.ts
+5
-4
@@ -100,13 +100,14 @@ export function leaveSSA(fn: HIRFunction): void {
100
> = new Map();
101
102
for (const param of fn.params) {
103
- if (param.identifier.name !== null) {
104
- declarations.set(param.identifier.name, {
103
+ let place: Place = param.kind === "Identifier" ? param : param.place;
104
+ if (place.identifier.name !== null) {
105
+ declarations.set(place.identifier.name, {
106
lvalue: {
107
kind: InstructionKind.Let,
107
- place: param,
108
+ place,
109
},
109
- place: param,
110
+ place,
111
});
112
}
113
}