Skip to content
← Back

src/syntax/process/printer/base.ghul

1
namespace Syntax.Process.Printer is
2
use IO.Std;
3
4
use Trees;
5
use Source;
6
7
class Base : StrictVisitor abstract is
8
_indent: int;
9
_depth: int;
10
_run_on: bool;
11
_indent_needed: bool;
12
_want_locations: bool;
13
_current_line: int;
14
_result: System.Text.StringBuilder;
15
16
init(want_locations: bool) is
17
super.init();
18
19
_want_locations = want_locations;
20
_depth = 0;
21
_indent = 2;
22
_result = System.Text.StringBuilder();
23
_current_line = 1;
24
si
25
26
result: string => _result.to_string();
27
28
write_line(value: string) is
29
write(value);
30
write_line();
31
si
32
33
write(value: string) is
34
write_indent();
35
_result.append(value);
36
si
37
38
write(c: char) is
39
write_indent();
40
_result.append(c);
41
si
42
43
write_line() is
44
_current_line = _current_line + 1;
45
_indent_needed = true;
46
_result.append('\n');
47
si
48
49
indent() is
50
_depth = _depth + 1;
51
si
52
53
outdent() is
54
_depth = _depth - 1;
55
si
56
57
write_indent() is
58
if _indent_needed then
59
let i mut = 0;
60
while i < _indent*_depth do
61
_result.append(' ');
62
i = i + 1;
63
od
64
_indent_needed = false;
65
fi
66
si
67
68
location(node: Node) is
69
location(node.location);
70
si
71
72
location(location: LOCATION) is
73
let new_line = location.start_line;
74
if new_line != _current_line then
75
_current_line = new_line;
76
if _want_locations then
77
write("#{_current_line} ");
78
fi
79
fi
80
si
81
82
write(node: Node) is
83
node.accept(self);
84
si
85
86
write_name(name: string) is
87
write(name);
88
si
89
90
visit(identifier: Identifiers.Identifier) is
91
location(identifier);
92
write_name(identifier.name);
93
si
94
95
visit(identifier: Identifiers.QUALIFIED) is
96
location(identifier);
97
identifier.qualifier.accept(self);
98
write('.');
99
write_name(identifier.name);
100
si
101
102
visit(modifier: Modifiers.Modifier) is
103
location(modifier);
104
write(modifier.name);
105
si
106
107
visit(modifiers: Modifiers.LIST) is
108
location(modifiers);
109
if let modifiers.access_modifier? then
110
access_modifier.accept(self);
111
write(' ');
112
fi
113
if let modifiers.storage_class? then
114
storage_class.accept(self);
115
write(' ');
116
fi
117
if modifiers.is_pure then
118
write("pure ");
119
fi
120
si
121
122
visit(variables: Variables.LIST) is
123
location(variables);
124
let first mut = true;
125
for v in variables do
126
if !first then
127
write(", ");
128
fi
129
v.accept(self);
130
first = false;
131
od
132
si
133
134
visit(definitions: Definitions.LIST) is
135
location(definitions);
136
for d in definitions do
137
d.accept(self);
138
139
// yuck...
140
if isa Variables.VARIABLE(d) then
141
let variable = d;
142
if let variable.name? /\ name.name.starts_with("$") then
143
write_line(";");
144
fi
145
fi
146
od
147
si
148
149
visit(`enum: Definitions.ENUM) is
150
location(`enum);
151
write("enum ");
152
`enum.name.accept(self);
153
write_line(" is");
154
indent();
155
let seen_any mut = false;
156
for member in `enum.members do
157
if seen_any then
158
write_line(",");
159
fi
160
member.accept(self);
161
seen_any = true;
162
od
163
write_line();
164
outdent();
165
write_line("si");
166
si
167
168
visit(member: Definitions.ENUM_MEMBER) is
169
location(member);
170
member.name.accept(self);
171
if member.initializer? then
172
write(" = ");
173
member.initializer!.accept(self);
174
fi
175
si
176
177
visit(functions: Definitions.FUNCTION_GROUP) is
178
write_line("function group ");
179
indent();
180
for f in functions.functions do
181
f.accept(self);
182
od
183
outdent();
184
si
185
186
visit(pragma: Pragmas.PRAGMA) is
187
write("@");
188
189
pragma.name.accept(self);
190
write("(");
191
192
pragma.arguments.accept(self);
193
write_line(")");
194
si
195
196
visit(pragma: Definitions.PRAGMA) is
197
pragma.definition.accept(self);
198
si
199
200
visit(type_expression: TypeExpressions.UNDEFINED) is
201
write("???");
202
si
203
204
visit(type_expression: TypeExpressions.INFER) is
205
write("infer");
206
si
207
208
visit(array: TypeExpressions.ARRAY_) is
209
array.element.accept(self);
210
write("[]");
211
si
212
213
visit(pointer: TypeExpressions.POINTER) is
214
pointer.element.accept(self);
215
write(" ptr");
216
si
217
218
visit(optional: TypeExpressions.OPTIONAL) is
219
optional.element.accept(self);
220
write("?");
221
si
222
223
visit(reference: TypeExpressions.REFERENCE) is
224
reference.element.accept(self);
225
write(" ref");
226
si
227
228
pre(member: TypeExpressions.MEMBER) -> bool => true;
229
visit(member: TypeExpressions.MEMBER) is
230
member.left.walk(self);
231
write('.');
232
member.name.walk(self);
233
si
234
235
visit(functions: TypeExpressions.FUNCTION_GROUP) is
236
write("function group ");
237
for f in functions.functions do
238
f.accept(self);
239
write(' ');
240
od
241
si
242
243
visit(named: TypeExpressions.NAMED) is
244
location(named);
245
named.name.accept(self);
246
si
247
248
visit(tuple: TypeExpressions.TUPLE) is
249
location(tuple);
250
write("(");
251
tuple.elements.accept(self);
252
write(")");
253
si
254
255
visit(element: TypeExpressions.NAMED_TUPLE_ELEMENT) is
256
location(element);
257
element.name.accept(self);
258
write(": ");
259
element.type_expression.accept(self);
260
si
261
262
visit(constraint: TypeExpressions.TYPE_PARAMETER_CONSTRAINT) is
263
location(constraint);
264
write(constraint.keyword);
265
si
266
267
visit(types: TypeExpressions.LIST) is
268
location(types);
269
let seen_any mut = false;
270
for t in types do
271
if seen_any then
272
write(',');
273
fi
274
t.accept(self);
275
seen_any = true;
276
od
277
si
278
279
visit(`none: Expressions.Literals.NONE) is
280
location(`none);
281
write("none");
282
si
283
284
visit(identifier: Expressions.IDENTIFIER) is
285
location(identifier);
286
identifier.identifier.accept(self);
287
si
288
289
visit(`super: Expressions.SUPER) is
290
location(`super);
291
write("super");
292
si
293
294
visit(`new: Expressions.NEW) is
295
location(`new);
296
write("");
297
if `new.type_expression? then
298
`new.type_expression.accept(self);
299
fi
300
write('(');
301
`new.arguments.accept(self);
302
write(')');
303
si
304
305
visit(`cast: Expressions.CAST) is
306
location(`cast);
307
write("cast ");
308
`cast.type_expression.accept(self);
309
write('(');
310
`cast.right.accept(self);
311
write(')');
312
si
313
314
visit(`isa: Expressions.ISA) is
315
location(`isa);
316
write("isa ");
317
`isa.type_expression.accept(self);
318
write('(');
319
`isa.right.accept(self);
320
write(')');
321
si
322
323
visit(`typeof: Expressions.TYPEOF) is
324
location(`typeof);
325
write("typeof ");
326
`typeof.type_expression.accept(self);
327
si
328
329
visit(`default: Expressions.DEFAULT) is
330
location(`default);
331
write("_");
332
333
let type_expression = `default.type_expression;
334
335
if type_expression? then
336
write('[');
337
type_expression.accept(self);
338
write(']');
339
fi
340
si
341
342
visit(tuple: Expressions.TUPLE) is
343
location(tuple);
344
write('(');
345
tuple.elements.accept(self);
346
write(')');
347
si
348
349
visit(call: Expressions.CALL) is
350
location(call);
351
if call.is_thread_first /\ call.arguments.count >= 1 then
352
call.arguments.expressions[0].accept(self);
353
write(" |> ");
354
call.function.accept(self);
355
write('(');
356
let seen mut = false;
357
for i in 1..call.arguments.count do
358
if seen then
359
write(',');
360
fi
361
call.arguments.expressions[i].accept(self);
362
seen = true;
363
od
364
if call.arguments.has_trailing_comma then
365
write(',');
366
fi
367
write(')');
368
else
369
call.function.accept(self);
370
write('(');
371
call.arguments.accept(self);
372
write(')');
373
fi
374
si
375
376
visit(member: Expressions.MEMBER) is
377
location(member);
378
member.left.accept(self);
379
if member.is_coalesce then
380
write("?.");
381
else
382
write('.');
383
fi
384
member.identifier.accept(self);
385
si
386
387
visit(explicit_specialization: Trees.Expressions.EXPLICIT_SPECIALIZATION) is
388
location(explicit_specialization);
389
explicit_specialization.left.accept(self);
390
write("`[");
391
explicit_specialization.types.accept(self);
392
write("]");
393
si
394
395
visit(index: Expressions.INDEX) is
396
location(index);
397
index.left.accept(self);
398
write('[');
399
index.index.accept(self);
400
write(']');
401
si
402
403
visit(unary: Expressions.UNARY) is
404
location(unary);
405
unary.operation.accept(self);
406
write(' ');
407
unary.right.accept(self);
408
si
409
410
visit(binary: Expressions.BINARY) is
411
location(binary);
412
binary.left.accept(self);
413
write(' ');
414
415
if binary.actual_operation? then
416
write(binary.actual_operation);
417
else
418
binary.operation.accept(self);
419
fi
420
421
write(' ');
422
binary.right.accept(self);
423
si
424
425
visit(expressions: Expressions.LIST) is
426
location(expressions);
427
let seen_any mut = false;
428
for e in expressions do
429
if seen_any then
430
write(',');
431
fi
432
e.accept(self);
433
seen_any = true;
434
od
435
436
if expressions.has_trailing_comma then
437
write(',');
438
fi
439
si
440
441
visit(literal: Expressions.Literals.Literal) is
442
location(literal);
443
write(literal.value_string);
444
si
445
446
write_escape_char(c: char) is
447
let ci = cast int(c);
448
if ci < 32 then
449
write("\\{string.format("X", ci)}");
450
elif ci == 34 then
451
write("\\");
452
write(cast char(34));
453
elif ci == 39 then
454
write("'");
455
elif ci == 92 then
456
write("\\\\");
457
else
458
write(c);
459
fi
460
si
461
462
visit(`string: Expressions.Literals.STRING) is
463
location(`string);
464
write(cast char(34));
465
for c in `string.value_string do
466
write_escape_char(c);
467
od
468
write(cast char(34));
469
si
470
471
visit(interpolation: Expressions.STRING_INTERPOLATION) is
472
location(interpolation);
473
474
let in_expression mut = false;
475
476
write("\"");
477
for e in interpolation.values do
478
if in_expression then
479
write("{{");
480
481
e.expression.accept(self);
482
483
if e.format? then
484
write(":{e.format}");
485
fi
486
487
if in_expression then
488
write("}}");
489
fi
490
else
491
// TODO: no quotes around string literals
492
e.expression.accept(self);
493
fi
494
495
in_expression = !in_expression;
496
od
497
write("\"");
498
si
499
500
visit(integer: Expressions.Literals.INTEGER) is
501
location(integer);
502
write(integer.value_string);
503
si
504
505
visit(float: Expressions.Literals.FLOAT) is
506
location(float);
507
write(float.value_string);
508
si
509
510
visit(character: Expressions.Literals.CHARACTER) is
511
location(character);
512
write("'");
513
write_escape_char(character.value_string.get_chars(0));
514
write("'");
515
si
516
517
visit(boolean: Expressions.Literals.BOOLEAN) is
518
location(boolean);
519
write(boolean.value_string);
520
si
521
522
visit(left: Trees.Expressions.SIMPLE_LEFT_EXPRESSION) is
523
left.expression.accept(self);
524
si
525
526
visit(destructure_left: Trees.Expressions.DESTRUCTURING_LEFT_EXPRESSION) is
527
let seen_any mut = false;
528
write("(");
529
for e in destructure_left.elements do
530
if seen_any then
531
write(", ");
532
fi
533
534
e.accept(self);
535
536
seen_any = true;
537
od
538
write(")");
539
si
540
541
visit(list: Statements.LIST) is
542
location(list);
543
for s in list do
544
s.accept(self);
545
od
546
si
547
548
visit(assign: Statements.ASSIGNMENT) is
549
location(assign);
550
assign.left.accept(self);
551
write(" = ");
552
assign.right.accept(self);
553
write_line(";");
554
si
555
556
visit(expression: Statements.EXPRESSION) is
557
location(expression);
558
expression.expression.accept(self);
559
write_line(";");
560
si
561
562
visit(r: Statements.RETURN) is
563
location(r);
564
write("return");
565
if r.expression? then
566
write(' ');
567
r.expression!.accept(self);
568
fi
569
write_line(";");
570
si
571
572
visit(t: Statements.THROW) is
573
location(t);
574
write("throw");
575
if t.expression? then
576
write(' ');
577
t.expression!.accept(self);
578
fi
579
write_line(";");
580
si
581
582
visit(y: Statements.YIELD) is
583
location(y);
584
write("yield");
585
write(' ');
586
y.expression.accept(self);
587
write_line(";");
588
si
589
590
visit(t: Statements.ASSERT) is
591
location(t);
592
write("assert");
593
write(' ');
594
t.expression.accept(self);
595
596
if t.message? then
597
write(" else ");
598
t.message!.accept(self);
599
fi
600
601
write_line(";");
602
si
603
604
visit(i: Statements.IF) is
605
location(i);
606
let is_first mut = true;
607
let seen_else mut = false;
608
609
610
for b in i.branches do
611
location(b);
612
613
if seen_else then
614
IoC.CONTAINER.instance.logger.error(b.location, "broken if statement");
615
fi
616
617
assert !seen_else;
618
619
if let b.condition? then
620
if is_first then
621
write("if ");
622
else
623
write("elif ");
624
fi
625
condition.accept(self);
626
write_line(" then");
627
else
628
seen_else = true;
629
write_line("else");
630
fi
631
indent();
632
b.body.accept(self);
633
outdent();
634
is_first = false;
635
od
636
write_line("fi");
637
si
638
639
visit(`case: Statements.CASE) is
640
location(`case);
641
write("case ");
642
`case.expression.accept(self);
643
write_line();
644
for m in `case.matches do
645
m.accept(self);
646
od
647
write_line("esac");
648
si
649
650
visit(match: Statements.CASE_MATCH) is
651
location(match);
652
if let match.expressions? then
653
write("when ");
654
expressions.accept(self);
655
write_line(":");
656
else
657
write_line("default");
658
fi
659
indent();
660
match.statements.accept(self);
661
outdent();
662
si
663
664
visit(`try: Statements.TRY) is
665
location(`try);
666
write_line("try");
667
indent();
668
`try.body.accept(self);
669
outdent();
670
for c in `try.catches do
671
c.accept(self);
672
od
673
let `finally = `try.`finally;
674
675
if `finally? then
676
write_line("finally");
677
indent();
678
`finally.accept(self);
679
outdent();
680
fi
681
write_line("yrt");
682
si
683
684
visit(`catch: Statements.CATCH) is
685
location(`catch);
686
write("catch ");
687
688
if let `catch.variable? then
689
variable.accept(self);
690
fi
691
write_line();
692
indent();
693
`catch.body.accept(self);
694
outdent();
695
si
696
697
visit(`do: Statements.DO) is
698
location(`do);
699
if let `do.binding? then
700
write("while let ");
701
binding.accept(self);
702
write(" ");
703
elif let `do.condition? then
704
write("while ");
705
condition.accept(self);
706
write(" ");
707
fi
708
write_line("do");
709
indent();
710
`do.body.accept(self);
711
outdent();
712
write_line("od");
713
si
714
715
visit(labelled: Statements.LABELLED) is
716
location(labelled);
717
labelled.label.accept(self);
718
write(": ");
719
labelled.statement.accept(self);
720
si
721
722
visit(`break: Statements.BREAK) is
723
location(`break);
724
write("break");
725
let label = `break.label;
726
727
if label? then
728
write(' ');
729
label.accept(self);
730
fi
731
write_line(";");
732
si
733
734
visit(`continue: Statements.CONTINUE) is
735
location(`continue);
736
write("continue");
737
let label = `continue.label;
738
739
if label? then
740
write(' ');
741
label.accept(self);
742
fi
743
write_line(";");
744
si
745
746
visit(pragma: Statements.PRAGMA) is
747
if let pragma.statement? then
748
statement.accept(self);
749
fi
750
si
751
752
visit(block: Bodies.NULL) is
753
write_line(";");
754
si
755
si
756
si