Skip to content

Commit 74f9d14

Browse files
committed
Add a print method
1 parent 9041d47 commit 74f9d14

10 files changed

+494
-136
lines changed

src/main/scala/fred/Translator.scala

+156-109
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import scala.collection.mutable
66
object Translator {
77
private val KindField = "kind"
88
private val RcField = "rc"
9-
private val SccField = "scc"
9+
private val PrinterField = "print"
1010
private val This = "this"
1111
private val Black = "kBlack"
1212
private val Gray = "kGray"
@@ -23,106 +23,112 @@ object Translator {
2323
*/
2424
private val CommonHeaderCode =
2525
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
126132

127133
private val NoMangleFns = Set("main", "printf")
128134

@@ -131,7 +137,7 @@ object Translator {
131137
given cycles: Cycles = Cycles.fromFile(file)
132138
val helper = Helper(typer)
133139
val (genDecls, genImpls) =
134-
List(Decrementer, MarkGray, Scan, ScanBlack, CollectWhite)
140+
List(Decrementer, MarkGray, Scan, ScanBlack, CollectWhite, Printer)
135141
.flatMap(gen => file.typeDefs.map(td => (gen.decl(td), gen.impl(td))))
136142
.unzip
137143
val (fnDecls, fnImpls) = file.fns.map(helper.fnToC).unzip
@@ -319,13 +325,44 @@ object Translator {
319325
.mkString("\n")
320326
}
321327
}
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
329366
}
330367
}
331368

@@ -358,6 +395,14 @@ object Translator {
358395
s.split("\n").map(line => " " * level + line).mkString("\n")
359396
}
360397

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+
361406
private def incrRc(expr: String, typ: Type) = {
362407
if (typ.isInstanceOf[TypeDef]) {
363408
s"$expr->$RcField ++;"
@@ -454,6 +499,7 @@ object Translator {
454499
val struct = s"""|struct $name {
455500
| int $RcField;
456501
| enum Color $ColorField;
502+
| void (*$PrinterField)();
457503
| enum ${name}_kind $KindField;
458504
|$commonFieldsToC
459505
| union {
@@ -626,6 +672,7 @@ object Translator {
626672
s"""|${typeRefToC(typ.name)} $resVar = malloc(sizeof (struct ${typ.name}));
627673
|$resVar->$RcField = 0;
628674
|$resVar->$ColorField = $Black;
675+
|$resVar->$PrinterField = ${Printer.name(typ)};
629676
|$resVar->$KindField = ${tagName(ctorName.value)};
630677
|$valueSetups""".stripMargin
631678
(setup, resVar, "")

0 commit comments

Comments
 (0)