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