ee1793bcb3c4cdcc03d5a9731c231183432335e4
[cparser] / write_fluffy.c
1 #include <config.h>
2
3 #include <errno.h>
4 #include <string.h>
5
6 #include "ast_t.h"
7 #include "type_t.h"
8 #include "adt/error.h"
9
10 static const context_t *global_context;
11 static FILE            *out;
12
13 static void write_type(const type_t *type);
14
15 static const char *get_atomic_type_string(const atomic_type_type_t type)
16 {
17         switch(type) {
18         case ATOMIC_TYPE_VOID:       return "void";
19         case ATOMIC_TYPE_CHAR:       return "byte";
20         case ATOMIC_TYPE_SCHAR:      return "byte";
21         case ATOMIC_TYPE_UCHAR:      return "unsigned byte";
22         case ATOMIC_TYPE_SHORT:      return "short";
23         case ATOMIC_TYPE_USHORT:     return "unsigned short";
24         case ATOMIC_TYPE_INT:        return "int";
25         case ATOMIC_TYPE_UINT:       return "unsigned int";
26         case ATOMIC_TYPE_LONG:       return "int";
27         case ATOMIC_TYPE_ULONG:      return "unsigned int";
28         case ATOMIC_TYPE_LONGLONG:   return "long";
29         case ATOMIC_TYPE_ULONGLONG:  return "unsigned long";
30         case ATOMIC_TYPE_FLOAT:      return "float";
31         case ATOMIC_TYPE_DOUBLE:     return "double";
32         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
33         case ATOMIC_TYPE_BOOL:       return "bool";
34         default:                     panic("unsupported atomic type");
35         }
36 }
37
38 static void write_atomic_type(const atomic_type_t *type)
39 {
40         fprintf(out, "%s", get_atomic_type_string(type->atype));
41 }
42
43 static void write_pointer_type(const pointer_type_t *type)
44 {
45         write_type(type->points_to);
46         fputc('*', out);
47 }
48
49 static declaration_t *find_typedef(const type_t *type)
50 {
51         /* first: search for a matching typedef in the global type... */
52         declaration_t *declaration = global_context->declarations;
53         while(declaration != NULL) {
54                 if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
55                         declaration = declaration->next;
56                         continue;
57                 }
58                 if(declaration->type == type)
59                         break;
60                 declaration = declaration->next;
61         }
62
63         return declaration;
64 }
65
66 static void write_compound_type(const compound_type_t *type)
67 {
68         declaration_t *declaration = find_typedef((const type_t*) type);
69         if(declaration != NULL) {
70                 fprintf(out, "%s", declaration->symbol->string);
71                 return;
72         }
73
74         /* does the struct have a name? */
75         if(type->symbol != NULL) {
76                 /* TODO: make sure we create a struct for it... */
77                 fprintf(out, "%s", type->symbol->string);
78                 return;
79         }
80         /* TODO: create a struct and use its name here... */
81         fprintf(out, "/* TODO anonymous struct */byte");
82 }
83
84 static void write_enum_type(const enum_type_t *type)
85 {
86         declaration_t *declaration = find_typedef((const type_t*) type);
87         if(declaration != NULL) {
88                 fprintf(out, "%s", declaration->symbol->string);
89                 return;
90         }
91
92         /* does the enum have a name? */
93         if(type->symbol != NULL) {
94                 /* TODO: make sure we create an enum for it... */
95                 fprintf(out, "%s", type->symbol->string);
96                 return;
97         }
98         /* TODO: create a struct and use its name here... */
99         fprintf(out, "/* TODO anonymous enum */byte");
100 }
101
102 static void write_method_type(const method_type_t *type)
103 {
104         fprintf(out, "(func(");
105
106         declaration_t *parameter = type->parameters;
107         int            first     = 1;
108         while(parameter != NULL) {
109                 if(!first) {
110                         fprintf(out, ", ");
111                 } else {
112                         first = 0;
113                 }
114
115                 if(parameter->symbol != NULL) {
116                         fprintf(out, "%s : ", parameter->symbol->string);
117                 } else {
118                         /* TODO make up some unused names (or allow _ in fluffy?) */
119                         fprintf(out, "_ : ");
120                 }
121                 write_type(parameter->type);
122
123                 parameter = parameter->next;
124         }
125
126         fprintf(out, ") : ");
127         write_type(type->result_type);
128         fprintf(out, ")");
129 }
130
131 static void write_type(const type_t *type)
132 {
133         switch(type->type) {
134         case TYPE_ATOMIC:
135                 write_atomic_type((const atomic_type_t*) type);
136                 return;
137         case TYPE_POINTER:
138                 write_pointer_type((const pointer_type_t*) type);
139                 return;
140         case TYPE_COMPOUND_UNION:
141         case TYPE_COMPOUND_STRUCT:
142                 write_compound_type((const compound_type_t*) type);
143                 return;
144         case TYPE_ENUM:
145                 write_enum_type((const enum_type_t*) type);
146                 return;
147         case TYPE_METHOD:
148                 write_method_type((const method_type_t*) type);
149                 return;
150         case TYPE_INVALID:
151                 panic("invalid type found");
152                 break;
153         default:
154                 fprintf(out, "/* TODO type */");
155                 break;
156         }
157 }
158
159 static void write_struct_entry(const declaration_t *declaration)
160 {
161         fprintf(out, "\t%s : ", declaration->symbol->string);
162         write_type(declaration->type);
163         fprintf(out, "\n");
164 }
165
166 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
167 {
168         fprintf(out, "struct %s:\n", symbol->string);
169
170         const declaration_t *declaration = type->context.declarations;
171         while(declaration != NULL) {
172                 write_struct_entry(declaration);
173                 declaration = declaration->next;
174         }
175
176         fprintf(out, "\n");
177 }
178
179 static void write_union(const symbol_t *symbol, const compound_type_t *type)
180 {
181         fprintf(out, "union %s:\n", symbol->string);
182
183         const declaration_t *declaration = type->context.declarations;
184         while(declaration != NULL) {
185                 write_struct_entry(declaration);
186                 declaration = declaration->next;
187         }
188
189         fprintf(out, "\n");
190 }
191
192 static void write_expression(const expression_t *expression);
193
194 static void write_unary_expression(const unary_expression_t *expression)
195 {
196         switch(expression->type) {
197         case UNEXPR_NEGATE:
198                 fputc('-', out);
199                 break;
200         case UNEXPR_NOT:
201                 fputc('!', out);
202                 break;
203         default:
204                 panic("unimeplemented unary expression found");
205         }
206         write_expression(expression->value);
207 }
208
209 static void write_expression(const expression_t *expression)
210 {
211         const const_t *constant;
212         /* TODO */
213         switch(expression->type) {
214         case EXPR_CONST:
215                 constant = (const const_t*) expression;
216                 fprintf(out, "%d", constant->value);
217                 break;
218         case EXPR_UNARY:
219                 write_unary_expression((const unary_expression_t*) expression);
220                 break;
221         default:
222                 panic("not implemented expression");
223         }
224 }
225
226 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
227 {
228         fprintf(out, "enum %s:\n", symbol->string);
229
230         const enum_entry_t *entry = type->entries;
231         for ( ; entry != NULL; entry = entry->next) {
232                 fprintf(out, "\t%s", entry->symbol->string);
233                 if(entry->value != NULL) {
234                         fprintf(out, " <- ");
235                         write_expression(entry->value);
236                 }
237                 fputc('\n', out);
238         }
239         fprintf(out, "typealias %s <- int\n", symbol->string);
240         fprintf(out, "\n");
241 }
242
243 static void write_variable(const declaration_t *declaration)
244 {
245         fprintf(out, "var %s : ", declaration->symbol->string);
246         write_type(declaration->type);
247         /* TODO: initializers */
248         fprintf(out, "\n");
249 }
250
251 static void write_function(const declaration_t *declaration)
252 {
253         if(declaration->statement != NULL) {
254                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
255                         declaration->symbol->string);
256         }
257
258         fprintf(out, "func extern %s(",
259                 declaration->symbol->string);
260
261         const method_type_t *method_type = (const method_type_t*) declaration->type;
262
263         declaration_t *parameter = method_type->parameters;
264         int            first     = 1;
265         for( ; parameter != NULL; parameter = parameter->next) {
266                 if(!first) {
267                         fprintf(out, ", ");
268                 } else {
269                         first = 0;
270                 }
271                 if(parameter->symbol != NULL) {
272                         fprintf(out, "%s : ", parameter->symbol->string);
273                 } else {
274                         fputs("_ : ", out);
275                 }
276                 write_type(parameter->type);
277         }
278         if(method_type->variadic) {
279                 if(!first) {
280                         fprintf(out, ", ");
281                 } else {
282                         first = 0;
283                 }
284                 fputs("...", out);
285         }
286         fprintf(out, ")");
287
288         const type_t        *result_type = method_type->result_type;
289         if(result_type->type != TYPE_ATOMIC ||
290                         ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
291                 fprintf(out, " : ");
292                 write_type(result_type);
293         }
294         fputc('\n', out);
295 }
296
297 void write_fluffy_decls(const translation_unit_t *unit)
298 {
299 #if 0
300         out = fopen("out.fluffy", "w");
301         if(out == NULL) {
302                 fprintf(stderr, "Couldn't open out.fluffy: %s\n", strerror(errno));
303                 exit(1);
304         }
305 #endif
306         out            = stdout;
307         global_context = &unit->context;
308
309         fprintf(out, "/* WARNING: Automatically generated file */\n");
310
311         /* write structs,unions + enums */
312         declaration_t *declaration = unit->context.declarations;
313         while(declaration != NULL) {
314                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
315                 if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
316                         declaration = declaration->next;
317                         continue;
318                 }
319                 type_t *type = declaration->type;
320                 if(type->type == TYPE_COMPOUND_STRUCT) {
321                         write_struct(declaration->symbol, (compound_type_t*) type);
322                 } else if(type->type == TYPE_COMPOUND_UNION) {
323                         write_union(declaration->symbol, (compound_type_t*) type);
324                 } else if(type->type == TYPE_ENUM) {
325                         write_enum(declaration->symbol, (enum_type_t*) type);
326                 }
327
328                 declaration = declaration->next;
329         }
330
331         /* write global variables */
332         declaration = unit->context.declarations;
333         for( ; declaration != NULL; declaration = declaration->next) {
334                 if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
335                         continue;
336
337                 type_t *type = declaration->type;
338                 if(type->type == TYPE_METHOD)
339                         continue;
340
341                 write_variable(declaration);
342         }
343
344         /* write functions */
345         declaration = unit->context.declarations;
346         for( ; declaration != NULL; declaration = declaration->next) {
347                 if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
348                         continue;
349
350                 type_t *type = declaration->type;
351                 if(type->type != TYPE_METHOD)
352                         continue;
353
354                 write_function(declaration);
355         }
356
357         //fclose(out);
358 }