improved support for enums
[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 void write_compound_type(const compound_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_t*) type)
59                         break;
60                 declaration = declaration->next;
61         }
62
63         if(declaration != NULL) {
64                 fprintf(out, "%s", declaration->symbol->string);
65                 return;
66         }
67
68         /* does the struct have a name? */
69         if(type->symbol != NULL) {
70                 /* TODO: make sure we create a struct for it... */
71                 fprintf(out, "%s", type->symbol->string);
72                 return;
73         }
74         /* TODO: create a struct and use its name here... */
75         fprintf(out, "/* TODO anonymous struct */byte");
76 }
77
78 static void write_method_type(const method_type_t *type)
79 {
80         fprintf(out, "(func(");
81
82         method_parameter_type_t *parameter_type = type->parameter_types;
83         int                      first          = 1;
84         while(parameter_type != NULL) {
85                 if(!first) {
86                         fprintf(out, ", ");
87                 } else {
88                         first = 0;
89                 }
90
91                 if(parameter_type->symbol != NULL) {
92                         fprintf(out, "%s : ", parameter_type->symbol->string);
93                 } else {
94                         /* TODO make up some unused names (or allow _ in fluffy?) */
95                         fprintf(out, "_ : ");
96                 }
97                 write_type(parameter_type->type);
98
99                 parameter_type = parameter_type->next;
100         }
101
102         fprintf(out, ") : ");
103         write_type(type->result_type);
104         fprintf(out, ")");
105 }
106
107 static void write_type(const type_t *type)
108 {
109         switch(type->type) {
110         case TYPE_ATOMIC:
111                 write_atomic_type((const atomic_type_t*) type);
112                 return;
113         case TYPE_POINTER:
114                 write_pointer_type((const pointer_type_t*) type);
115                 return;
116         case TYPE_COMPOUND_UNION:
117         case TYPE_COMPOUND_STRUCT:
118                 write_compound_type((const compound_type_t*) type);
119                 return;
120         case TYPE_METHOD:
121                 write_method_type((const method_type_t*) type);
122                 return;
123         case TYPE_INVALID:
124                 panic("invalid type found");
125                 break;
126         default:
127                 fprintf(out, "/* TODO type */");
128                 break;
129         }
130 }
131
132 static void write_struct_entry(const declaration_t *declaration)
133 {
134         fprintf(out, "\t%s : ", declaration->symbol->string);
135         write_type(declaration->type);
136         fprintf(out, "\n");
137 }
138
139 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
140 {
141         fprintf(out, "struct %s:\n", symbol->string);
142
143         const declaration_t *declaration = type->context.declarations;
144         while(declaration != NULL) {
145                 write_struct_entry(declaration);
146                 declaration = declaration->next;
147         }
148
149         fprintf(out, "\n");
150 }
151
152 static void write_union(const symbol_t *symbol, const compound_type_t *type)
153 {
154         fprintf(out, "union %s:\n", symbol->string);
155
156         const declaration_t *declaration = type->context.declarations;
157         while(declaration != NULL) {
158                 write_struct_entry(declaration);
159                 declaration = declaration->next;
160         }
161
162         fprintf(out, "\n");
163 }
164
165 static void write_expression(const expression_t *expression);
166
167 static void write_unary_expression(const unary_expression_t *expression)
168 {
169         switch(expression->type) {
170         case UNEXPR_NEGATE:
171                 fputc('-', out);
172                 break;
173         case UNEXPR_NOT:
174                 fputc('!', out);
175                 break;
176         default:
177                 panic("unimeplemented unary expression found");
178         }
179         write_expression(expression->value);
180 }
181
182 static void write_expression(const expression_t *expression)
183 {
184         const const_t *constant;
185         /* TODO */
186         switch(expression->type) {
187         case EXPR_CONST:
188                 constant = (const const_t*) expression;
189                 fprintf(out, "%d", constant->value);
190                 break;
191         case EXPR_UNARY:
192                 write_unary_expression((const unary_expression_t*) expression);
193                 break;
194         default:
195                 panic("not implemented expression");
196         }
197 }
198
199 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
200 {
201         fprintf(out, "enum %s:\n", symbol->string);
202
203         const enum_entry_t *entry = type->entries;
204         for ( ; entry != NULL; entry = entry->next) {
205                 fprintf(out, "\t%s", entry->symbol->string);
206                 if(entry->value != NULL) {
207                         fprintf(out, " <- ");
208                         write_expression(entry->value);
209                 }
210                 fputc('\n', out);
211         }
212         fprintf(out, "\n");
213 }
214
215 static void write_variable(const declaration_t *declaration)
216 {
217         fprintf(out, "var %s : ", declaration->symbol->string);
218         write_type(declaration->type);
219         /* TODO: initializers */
220         fprintf(out, "\n");
221 }
222
223 static void write_function(const declaration_t *declaration)
224 {
225         if(declaration->statement != NULL) {
226                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
227                         declaration->symbol->string);
228         }
229
230         fprintf(out, "func extern %s(",
231                 declaration->symbol->string);
232
233         declaration_t *parameter = declaration->context.declarations;
234         int            first     = 1;
235         for( ; parameter != NULL; parameter = parameter->next) {
236                 if(!first) {
237                         fprintf(out, ", ");
238                 } else {
239                         first = 0;
240                 }
241                 if(parameter->symbol != NULL) {
242                         fprintf(out, "%s : ", parameter->symbol->string);
243                 } else {
244                         fputs("_ : ", out);
245                 }
246                 write_type(parameter->type);
247         }
248         fprintf(out, ")");
249
250         const method_type_t *method_type = (const method_type_t*) declaration->type;
251         const type_t        *result_type = method_type->result_type;
252         if(result_type->type != TYPE_ATOMIC ||
253                         ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
254                 fprintf(out, " : ");
255                 write_type(result_type);
256         }
257         fputc('\n', out);
258 }
259
260 void write_fluffy_decls(const translation_unit_t *unit)
261 {
262 #if 0
263         out = fopen("out.fluffy", "w");
264         if(out == NULL) {
265                 fprintf(stderr, "Couldn't open out.fluffy: %s\n", strerror(errno));
266                 exit(1);
267         }
268 #endif
269         out            = stdout;
270         global_context = &unit->context;
271
272         fprintf(out, "/* WARNING: Automatically generated file */\n");
273
274         /* write structs,unions + enums */
275         declaration_t *declaration = unit->context.declarations;
276         while(declaration != NULL) {
277                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
278                 if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
279                         declaration = declaration->next;
280                         continue;
281                 }
282                 type_t *type = declaration->type;
283                 if(type->type == TYPE_COMPOUND_STRUCT) {
284                         write_struct(declaration->symbol, (compound_type_t*) type);
285                 } else if(type->type == TYPE_COMPOUND_UNION) {
286                         write_union(declaration->symbol, (compound_type_t*) type);
287                 } else if(type->type == TYPE_ENUM) {
288                         write_enum(declaration->symbol, (enum_type_t*) type);
289                 }
290
291                 declaration = declaration->next;
292         }
293
294         /* write global variables */
295         declaration = unit->context.declarations;
296         for( ; declaration != NULL; declaration = declaration->next) {
297                 if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
298                         continue;
299
300                 type_t *type = declaration->type;
301                 if(type->type == TYPE_METHOD)
302                         continue;
303
304                 write_variable(declaration);
305         }
306
307         /* write functions */
308         declaration = unit->context.declarations;
309         for( ; declaration != NULL; declaration = declaration->next) {
310                 if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
311                         continue;
312
313                 type_t *type = declaration->type;
314                 if(type->type != TYPE_METHOD)
315                         continue;
316
317                 write_function(declaration);
318         }
319
320         //fclose(out);
321 }