@@ -6,7 +6,7 @@ import scala.collection.mutable
6
6
object Translator {
7
7
private val KindField = " kind"
8
8
private val RcField = " rc"
9
- private val SccField = " scc "
9
+ private val PrinterField = " print "
10
10
private val This = " this"
11
11
private val Black = " kBlack"
12
12
private val Gray = " kGray"
@@ -23,106 +23,112 @@ object Translator {
23
23
*/
24
24
private val CommonHeaderCode =
25
25
raw """ |#include <stdlib.h>
26
- |#include <stdio.h>
27
- |
28
- |enum Color { $Black, $Gray, $White };
29
- |
30
- |struct PCR {
31
- | void *obj;
32
- | int scc;
33
- | void (*markGray)(void *);
34
- | void (*scan)(void *);
35
- | void (*collectWhite)(void *);
36
- | struct PCR *next;
37
- |};
38
- |
39
- |struct $FreeCell {
40
- | int rc;
41
- | enum Color color;
42
- | struct $FreeCell *next;
43
- |};
44
- |
45
- |struct PCR *pcrs;
46
- |struct $FreeCell *freeList = NULL;
47
- |
48
- |void addPCR(
49
- | void *obj,
50
- | int scc,
51
- | void (*markGray)(void *),
52
- | void (*scan)(void *),
53
- | void (*collectWhite)(void *)
54
- |) {
55
- | printf("[addPCR] scc: %d\n", scc);
56
- | struct PCR **prev = &pcrs;
57
- | while (*prev != NULL && (*prev)->scc <= scc) {
58
- | if ((*prev)->obj == obj) return;
59
- | printf("[addPCR] prev scc: %d\n", (*prev)->scc);
60
- | prev = &(*prev)->next;
61
- | }
62
- | struct PCR *pcr = malloc(sizeof(struct PCR));
63
- | pcr->obj = obj;
64
- | pcr->scc = scc;
65
- | pcr->markGray = markGray;
66
- | pcr->scan = scan;
67
- | pcr->collectWhite = collectWhite;
68
- | pcr->next = (*prev == NULL) ? NULL : (*prev)->next;
69
- | *prev = pcr;
70
- |}
71
- |
72
- |void removePCR(void *obj) {
73
- | struct PCR *head = pcrs;
74
- | struct PCR **prev = &pcrs;
75
- | while (head != NULL) {
76
- | if (head->obj == obj) {
77
- | *prev = head->next;
78
- | free(head);
79
- | head = *prev;
80
- | break;
81
- | } else {
82
- | prev = &head->next;
83
- | head = head->next;
84
- | }
85
- | }
86
- |}
87
- |
88
- |void markGrayAllPCRs(struct PCR *head) {
89
- | if (head == NULL) return;
90
- | struct PCR *next = head->next;
91
- | head->markGray(head->obj);
92
- | markGrayAllPCRs(next);
93
- |}
94
- |
95
- |void scanAllPCRs(struct PCR *head) {
96
- | if (head == NULL) return;
97
- | struct PCR *next = head->next;
98
- | head->scan(head->obj);
99
- | scanAllPCRs(next);
100
- |}
101
- |
102
- |void collectWhiteAllPCRs(struct PCR *head) {
103
- | if (head == NULL) return;
104
- | struct PCR *next = head->next;
105
- | head->collectWhite(head->obj);
106
- | free(head);
107
- | collectWhiteAllPCRs(next);
108
- |}
109
- |
110
- |void collectFreeList() {
111
- | while (freeList != NULL) {
112
- | struct $FreeCell *next = freeList->next;
113
- | free(freeList);
114
- | freeList = next;
115
- | }
116
- |}
117
- |
118
- |void processAllPCRs() {
119
- | markGrayAllPCRs(pcrs);
120
- | scanAllPCRs(pcrs);
121
- | freeList = NULL;
122
- | collectWhiteAllPCRs(pcrs);
123
- | collectFreeList();
124
- |}
125
- | """ .stripMargin
26
+ |#include <stdio.h>
27
+ |
28
+ |enum Color { $Black, $Gray, $White };
29
+ |
30
+ |struct PCR {
31
+ | void *obj;
32
+ | int scc;
33
+ | void (*markGray)(void *);
34
+ | void (*scan)(void *);
35
+ | void (*collectWhite)(void *);
36
+ | struct PCR *next;
37
+ |};
38
+ |
39
+ |struct $FreeCell {
40
+ | int $RcField;
41
+ | enum Color $ColorField;
42
+ | void (* $PrinterField)();
43
+ | // Just to avoid the kind field being overwritten, so we can still print this
44
+ | int $KindField;
45
+ | struct $FreeCell *next;
46
+ |};
47
+ |
48
+ |struct PCR *pcrs;
49
+ |struct $FreeCell *freeList = NULL;
50
+ |
51
+ |void addPCR(
52
+ | void *obj,
53
+ | int scc,
54
+ | void (*markGray)(void *),
55
+ | void (*scan)(void *),
56
+ | void (*collectWhite)(void *)
57
+ |) {
58
+ | fprintf(stderr, "[addPCR] scc: %d\n", scc);
59
+ | struct PCR **prev = &pcrs;
60
+ | while (*prev != NULL && (*prev)->scc <= scc) {
61
+ | if ((*prev)->obj == obj) return;
62
+ | fprintf(stderr, "[addPCR] prev scc: %d\n", (*prev)->scc);
63
+ | prev = &(*prev)->next;
64
+ | }
65
+ | struct PCR *pcr = malloc(sizeof(struct PCR));
66
+ | pcr->obj = obj;
67
+ | pcr->scc = scc;
68
+ | pcr->markGray = markGray;
69
+ | pcr->scan = scan;
70
+ | pcr->collectWhite = collectWhite;
71
+ | pcr->next = (*prev == NULL) ? NULL : (*prev)->next;
72
+ | *prev = pcr;
73
+ |}
74
+ |
75
+ |void removePCR(void *obj) {
76
+ | struct PCR *head = pcrs;
77
+ | struct PCR **prev = &pcrs;
78
+ | while (head != NULL) {
79
+ | if (head->obj == obj) {
80
+ | *prev = head->next;
81
+ | free(head);
82
+ | head = *prev;
83
+ | break;
84
+ | } else {
85
+ | prev = &head->next;
86
+ | head = head->next;
87
+ | }
88
+ | }
89
+ |}
90
+ |
91
+ |void markGrayAllPCRs(struct PCR *head) {
92
+ | if (head == NULL) return;
93
+ | struct PCR *next = head->next;
94
+ | head->markGray(head->obj);
95
+ | markGrayAllPCRs(next);
96
+ |}
97
+ |
98
+ |void scanAllPCRs(struct PCR *head) {
99
+ | if (head == NULL) return;
100
+ | struct PCR *next = head->next;
101
+ | head->scan(head->obj);
102
+ | scanAllPCRs(next);
103
+ |}
104
+ |
105
+ |void collectWhiteAllPCRs(struct PCR *head) {
106
+ | if (head == NULL) return;
107
+ | struct PCR *next = head->next;
108
+ | head->collectWhite(head->obj);
109
+ | free(head);
110
+ | collectWhiteAllPCRs(next);
111
+ |}
112
+ |
113
+ |void collectFreeList() {
114
+ | while (freeList != NULL) {
115
+ | struct $FreeCell *next = freeList->next;
116
+ | free(freeList);
117
+ | freeList = next;
118
+ | }
119
+ |}
120
+ |
121
+ |void processAllPCRs() {
122
+ | markGrayAllPCRs(pcrs);
123
+ | scanAllPCRs(pcrs);
124
+ | if (freeList != NULL) {
125
+ | fprintf(stderr, "Free list should be null\n");
126
+ | exit(1);
127
+ | }
128
+ | collectWhiteAllPCRs(pcrs);
129
+ | collectFreeList();
130
+ |}
131
+ | """ .stripMargin
126
132
127
133
private val NoMangleFns = Set (" main" , " printf" )
128
134
@@ -131,7 +137,7 @@ object Translator {
131
137
given cycles : Cycles = Cycles .fromFile(file)
132
138
val helper = Helper (typer)
133
139
val (genDecls, genImpls) =
134
- List (Decrementer , MarkGray , Scan , ScanBlack , CollectWhite )
140
+ List (Decrementer , MarkGray , Scan , ScanBlack , CollectWhite , Printer )
135
141
.flatMap(gen => file.typeDefs.map(td => (gen.decl(td), gen.impl(td))))
136
142
.unzip
137
143
val (fnDecls, fnImpls) = file.fns.map(helper.fnToC).unzip
@@ -319,13 +325,44 @@ object Translator {
319
325
.mkString(" \n " )
320
326
}
321
327
}
322
- s """ |if ( $This-> $ColorField == $White) {
323
- | $This-> $ColorField = $Black;
324
- | $rec
325
- | struct $FreeCell *curr = freeList;
326
- | freeList = (void *) $This;
327
- | freeList->next = curr;
328
- |} """ .stripMargin
328
+ raw """ |if ( $This-> $ColorField == $White) {
329
+ | $This-> $ColorField = $Black;
330
+ | $rec
331
+ | fprintf(stderr, "Removing ${typ.name}\n");
332
+ | struct $FreeCell *curr = freeList;
333
+ | freeList = (void *) $This;
334
+ | freeList->next = curr;
335
+ |} """ .stripMargin
336
+ }
337
+ }
338
+
339
+ /** Print the object (no newline at end)
340
+ */
341
+ private object Printer extends GeneratedFn (" print" ) {
342
+ override def returnType = " void"
343
+
344
+ override def body (
345
+ typ : TypeDef
346
+ )(using bindings : Bindings , cycles : Cycles ): String = {
347
+ val cases = indent(1 ) {
348
+ switch(This , typ) {
349
+ case variant @ EnumCase (Spanned (ctorName, _), fields, _) =>
350
+ val printFields = fields
351
+ .map { case FieldDef (_, fieldName, fieldType, _) =>
352
+ val mangled = cFieldName(fieldName.value, typ, variant)
353
+ raw """ |printf(" ${fieldName.value}=");
354
+ | ${callPrint(s " $This-> $mangled" , bindings.types(fieldType.name))}
355
+ |printf(", "); """ .stripMargin
356
+ }
357
+ .mkString(" \n " )
358
+
359
+ s """ |printf(" $ctorName {");
360
+ | $printFields
361
+ |printf("}"); """ .stripMargin
362
+ }
363
+ }
364
+
365
+ s """ | $cases""" .stripMargin
329
366
}
330
367
}
331
368
@@ -358,6 +395,14 @@ object Translator {
358
395
s.split(" \n " ).map(line => " " * level + line).mkString(" \n " )
359
396
}
360
397
398
+ private def callPrint (expr : String , typ : Type ): String = {
399
+ typ match {
400
+ case td : TypeDef => s " ${Printer .name(td)}( $expr); "
401
+ case BuiltinType .Str => s " printf( \" %s \" , $expr); "
402
+ case BuiltinType .Int => s " printf( \" %d \" , $expr); "
403
+ }
404
+ }
405
+
361
406
private def incrRc (expr : String , typ : Type ) = {
362
407
if (typ.isInstanceOf [TypeDef ]) {
363
408
s " $expr-> $RcField ++; "
@@ -454,6 +499,7 @@ object Translator {
454
499
val struct = s """ |struct $name {
455
500
| int $RcField;
456
501
| enum Color $ColorField;
502
+ | void (* $PrinterField)();
457
503
| enum ${name}_kind $KindField;
458
504
| $commonFieldsToC
459
505
| union {
@@ -626,6 +672,7 @@ object Translator {
626
672
s """ | ${typeRefToC(typ.name)} $resVar = malloc(sizeof (struct ${typ.name}));
627
673
| $resVar-> $RcField = 0;
628
674
| $resVar-> $ColorField = $Black;
675
+ | $resVar-> $PrinterField = ${Printer .name(typ)};
629
676
| $resVar-> $KindField = ${tagName(ctorName.value)};
630
677
| $valueSetups""" .stripMargin
631
678
(setup, resVar, " " )
0 commit comments