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