[qol] Improve printing of ReactiveFunction
This is a (hopefully) better approach at printing ReactiveFunction. The nesting wasn't always clear in the previous version, this should help. See playground to experiment.
Joe Savona committed
Oct 3, 2023 at 16:56 UTC
b96dd26be17b571bf1aa06d51db1dd47545d8d1c
1 file changed
+105
-58
compiler/packages/babel-plugin-react-forget/src/ReactiveScopes/PrintReactiveFunction.ts
+105
-58
@@ -35,12 +35,12 @@ export function printReactiveFunction(fn: ReactiveFunction): string {
35
}
36
});
37
writer.writeLine(") {");
38
- printReactiveInstructions(writer, fn.body);
38
+ writeReactiveInstructions(writer, fn.body);
39
writer.writeLine("}");
40
return writer.complete();
41
}
42
43
-export function printReactiveBlock(
43
+export function writeReactiveBlock(
44
writer: Writer,
45
block: ReactiveScopeBlock
46
): void {
@@ -57,7 +57,7 @@ export function printReactiveBlock(
57
(reassign) => printIdentifier(reassign)
58
)}] {`
59
);
60
- printReactiveInstructions(writer, block.instructions);
60
+ writeReactiveInstructions(writer, block.instructions);
61
writer.writeLine("}");
62
}
63
@@ -68,18 +68,18 @@ function printDependency(dependency: ReactiveScopeDependency): string {
68
return `${identifier}${dependency.path.map((prop) => `.${prop}`).join("")}`;
69
}
70
71
-export function printReactiveInstructions(
71
+export function writeReactiveInstructions(
72
writer: Writer,
73
instructions: Array<ReactiveStatement>
74
): void {
75
writer.indented(() => {
76
for (const instr of instructions) {
77
- printReactiveInstruction(writer, instr);
77
+ writeReactiveInstruction(writer, instr);
78
}
79
});
80
}
81
82
-function printReactiveInstruction(
82
+function writeReactiveInstruction(
83
writer: Writer,
84
instr: ReactiveStatement
85
): void {
@@ -90,21 +90,21 @@ function printReactiveInstruction(
90
91
if (instruction.lvalue !== null) {
92
writer.write(`${id} ${printPlace(instruction.lvalue)} = `);
93
- printReactiveValue(writer, instruction.value);
93
+ writeReactiveValue(writer, instruction.value);
94
writer.newline();
95
} else {
96
writer.write(`${id} `);
97
- printReactiveValue(writer, instruction.value);
97
+ writeReactiveValue(writer, instruction.value);
98
writer.newline();
99
}
100
break;
101
}
102
case "scope": {
103
- printReactiveBlock(writer, instr);
103
+ writeReactiveBlock(writer, instr);
104
break;
105
}
106
case "terminal": {
107
- printTerminal(writer, instr.terminal);
107
+ writeTerminal(writer, instr.terminal);
108
break;
109
}
110
default: {
@@ -116,61 +116,83 @@ function printReactiveInstruction(
116
}
117
}
118
119
-function printReactiveValue(writer: Writer, value: ReactiveValue): void {
119
+export function printReactiveValue(value: ReactiveValue): string {
120
+ const writer = new Writer();
121
+ writeReactiveValue(writer, value);
122
+ return writer.complete();
123
+}
124
+
125
+function writeReactiveValue(writer: Writer, value: ReactiveValue): void {
126
switch (value.kind) {
127
case "ConditionalExpression": {
122
- writer.append(`Ternary `);
123
- printReactiveValue(writer, value.test);
124
- writer.newline();
128
+ writer.writeLine(`Ternary `);
129
writer.indented(() => {
126
- writer.write(`? `);
127
- printReactiveValue(writer, value.consequent);
128
- writer.newline();
129
- writer.write(`: `);
130
- printReactiveValue(writer, value.alternate);
131
- writer.newline();
130
+ writeReactiveValue(writer, value.test);
131
+ writer.writeLine(`? `);
132
+ writer.indented(() => {
133
+ writeReactiveValue(writer, value.consequent);
134
+ });
135
+ writer.writeLine(`: `);
136
+ writer.indented(() => {
137
+ writeReactiveValue(writer, value.alternate);
138
+ });
139
});
140
+ writer.newline();
141
break;
142
}
143
case "LogicalExpression": {
136
- writer.append(`Logical ${value.operator} `);
137
- printReactiveValue(writer, value.left);
144
+ writer.writeLine(`Logical`);
145
+ writer.indented(() => {
146
+ writeReactiveValue(writer, value.left);
147
+ writer.write(`${value.operator} `);
148
+ writeReactiveValue(writer, value.right);
149
+ });
150
writer.newline();
139
- printReactiveValue(writer, value.right);
151
break;
152
}
153
case "SequenceExpression": {
154
+ writer.writeLine(`Sequence`);
155
writer.indented(() => {
144
- writer.newline();
145
- writer.writeLine(`Sequence`);
156
writer.indented(() => {
157
value.instructions.forEach((instr) =>
148
- printReactiveInstruction(writer, {
158
+ writeReactiveInstruction(writer, {
159
kind: "instruction",
160
instruction: instr,
161
})
162
);
163
writer.write(`[${value.id}] `);
154
- printReactiveValue(writer, value.value);
164
+ writeReactiveValue(writer, value.value);
165
});
166
});
167
+ writer.newline();
168
break;
169
}
170
case "OptionalExpression": {
171
writer.append(`OptionalExpression optional=${value.optional}`);
172
writer.newline();
173
writer.indented(() => {
163
- printReactiveValue(writer, value.value);
174
+ writeReactiveValue(writer, value.value);
175
});
176
+ writer.newline();
177
break;
178
}
179
default: {
168
- writer.append(printInstructionValue(value));
180
+ const printed = printInstructionValue(value);
181
+ const lines = printed.split("\n");
182
+ if (lines.length === 1) {
183
+ writer.writeLine(printed);
184
+ } else {
185
+ writer.indented(() => {
186
+ for (const line of lines) {
187
+ writer.writeLine(line);
188
+ }
189
+ });
190
+ }
191
}
192
}
193
}
194
173
-function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
195
+function writeTerminal(writer: Writer, terminal: ReactiveTerminal): void {
196
switch (terminal.kind) {
197
case "break": {
198
const id = terminal.id !== null ? `[${terminal.id}]` : [];
@@ -194,27 +216,31 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
216
}
217
case "do-while": {
218
writer.writeLine(`[${terminal.id}] do-while {`);
197
- printReactiveInstructions(writer, terminal.loop);
219
+ writeReactiveInstructions(writer, terminal.loop);
220
writer.writeLine("} (");
199
- printReactiveValue(writer, terminal.test);
221
+ writer.indented(() => {
222
+ writeReactiveValue(writer, terminal.test);
223
+ });
224
writer.writeLine(")");
225
break;
226
}
227
case "while": {
228
writer.writeLine(`[${terminal.id}] while (`);
205
- printReactiveValue(writer, terminal.test);
229
+ writer.indented(() => {
230
+ writeReactiveValue(writer, terminal.test);
231
+ });
232
writer.writeLine(") {");
207
- printReactiveInstructions(writer, terminal.loop);
233
+ writeReactiveInstructions(writer, terminal.loop);
234
writer.writeLine("}");
235
break;
236
}
237
case "if": {
238
const { test, consequent, alternate } = terminal;
239
writer.writeLine(`[${terminal.id}] if (${printPlace(test)}) {`);
214
- printReactiveInstructions(writer, consequent);
240
+ writeReactiveInstructions(writer, consequent);
241
if (alternate !== null) {
242
writer.writeLine("} else {");
217
- printReactiveInstructions(writer, alternate);
243
+ writeReactiveInstructions(writer, alternate);
244
}
245
writer.writeLine("}");
246
break;
@@ -236,7 +262,7 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
262
loc: case_.test?.loc ?? null,
263
suggestions: null,
264
});
239
- printReactiveInstructions(writer, block);
265
+ writeReactiveInstructions(writer, block);
266
});
267
writer.writeLine("}");
268
}
@@ -246,31 +272,37 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
272
}
273
case "for": {
274
writer.writeLine(`[${terminal.id}] for (`);
249
- printReactiveValue(writer, terminal.init);
250
- writer.writeLine(";");
251
- printReactiveValue(writer, terminal.test);
252
- writer.writeLine(";");
253
- if (terminal.update !== null) {
254
- printReactiveValue(writer, terminal.update);
255
- }
275
+ writer.indented(() => {
276
+ writeReactiveValue(writer, terminal.init);
277
+ writer.writeLine(";");
278
+ writeReactiveValue(writer, terminal.test);
279
+ writer.writeLine(";");
280
+ if (terminal.update !== null) {
281
+ writeReactiveValue(writer, terminal.update);
282
+ }
283
+ });
284
writer.writeLine(") {");
257
- printReactiveInstructions(writer, terminal.loop);
285
+ writeReactiveInstructions(writer, terminal.loop);
286
writer.writeLine("}");
287
break;
288
}
289
case "for-of": {
290
writer.writeLine(`[${terminal.id}] for-of (`);
263
- printReactiveValue(writer, terminal.init);
291
+ writer.indented(() => {
292
+ writeReactiveValue(writer, terminal.init);
293
+ });
294
writer.writeLine(") {");
265
- printReactiveInstructions(writer, terminal.loop);
295
+ writeReactiveInstructions(writer, terminal.loop);
296
writer.writeLine("}");
297
break;
298
}
299
case "for-in": {
300
writer.writeLine(`[${terminal.id}] for-in (`);
271
- printReactiveValue(writer, terminal.init);
301
+ writer.indented(() => {
302
+ writeReactiveValue(writer, terminal.init);
303
+ });
304
writer.writeLine(") {");
273
- printReactiveInstructions(writer, terminal.loop);
305
+ writeReactiveInstructions(writer, terminal.loop);
306
writer.writeLine("}");
307
break;
308
}
@@ -284,15 +316,15 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
316
}
317
case "label": {
318
writer.writeLine("{");
287
- printReactiveInstructions(writer, terminal.block);
319
+ writeReactiveInstructions(writer, terminal.block);
320
writer.writeLine("}");
321
break;
322
}
323
case "try": {
324
writer.writeLine(`[${terminal.id}] try {`);
293
- printReactiveInstructions(writer, terminal.block);
325
+ writeReactiveInstructions(writer, terminal.block);
326
writer.writeLine(`} catch {`);
295
- printReactiveInstructions(writer, terminal.handler);
327
+ writeReactiveInstructions(writer, terminal.handler);
328
writer.writeLine("}");
329
break;
330
}
@@ -303,30 +335,45 @@ function printTerminal(writer: Writer, terminal: ReactiveTerminal): void {
335
336
export class Writer {
337
#out: Array<string> = [];
338
+ #line: string;
339
#depth: number;
340
341
constructor({ depth }: { depth: number } = { depth: 0 }) {
309
- this.#depth = depth;
342
+ this.#depth = Math.max(depth, 0);
343
+ this.#line = "";
344
}
345
346
complete(): string {
313
- return this.#out.join("");
347
+ const line = this.#line.trimEnd();
348
+ if (line.length > 0) {
349
+ this.#out.push(line);
350
+ }
351
+ return this.#out.join("\n");
352
}
353
354
append(s: string): void {
317
- this.#out.push(s);
355
+ this.write(s);
356
}
357
358
newline(): void {
321
- this.#out.push("\n");
359
+ const line = this.#line.trimEnd();
360
+ if (line.length > 0) {
361
+ this.#out.push(line);
362
+ }
363
+ this.#line = "";
364
}
365
366
write(s: string): void {
325
- this.#out.push(" ".repeat(this.#depth) + s);
367
+ if (this.#line.length === 0 && this.#depth > 0) {
368
+ // indent before writing
369
+ this.#line = " ".repeat(this.#depth);
370
+ }
371
+ this.#line += s;
372
}
373
374
writeLine(s: string): void {
329
- this.#out.push(" ".repeat(this.#depth) + s + "\n");
375
+ this.write(s);
376
+ this.newline();
377
}
378
379
indented(f: () => void): void {