The library for web and native user interfaces.
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
}