@samitouri / QOS-React-1 / commits / b96dd26be1

[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 {