Older GCCs do not know -Wextra. Only use -W.
[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         method_parameter_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 0
116                 if(parameter->symbol != NULL) {
117                         fprintf(out, "%s : ", parameter->symbol->string);
118                 } else {
119                         /* TODO make up some unused names (or allow _ in fluffy?) */
120                         fprintf(out, "_ : ");
121                 }
122 #endif
123                 fputs("_ : ", out);
124                 write_type(parameter->type);
125
126                 parameter = parameter->next;
127         }
128
129         fprintf(out, ") : ");
130         write_type(type->result_type);
131         fprintf(out, ")");
132 }
133
134 static void write_type(const type_t *type)
135 {
136         switch(type->type) {
137         case TYPE_ATOMIC:
138                 write_atomic_type((const atomic_type_t*) type);
139                 return;
140         case TYPE_POINTER:
141                 write_pointer_type((const pointer_type_t*) type);
142                 return;
143         case TYPE_COMPOUND_UNION:
144         case TYPE_COMPOUND_STRUCT:
145                 write_compound_type((const compound_type_t*) type);
146                 return;
147         case TYPE_ENUM:
148                 write_enum_type((const enum_type_t*) type);
149                 return;
150         case TYPE_METHOD:
151                 write_method_type((const method_type_t*) type);
152                 return;
153         case TYPE_INVALID:
154                 panic("invalid type found");
155                 break;
156         default:
157                 fprintf(out, "/* TODO type */");
158                 break;
159         }
160 }
161
162 static void write_struct_entry(const declaration_t *declaration)
163 {
164         fprintf(out, "\t%s : ", declaration->symbol->string);
165         write_type(declaration->type);
166         fprintf(out, "\n");
167 }
168
169 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
170 {
171         fprintf(out, "struct %s:\n", symbol->string);
172
173         const declaration_t *declaration = type->context.declarations;
174         while(declaration != NULL) {
175                 write_struct_entry(declaration);
176                 declaration = declaration->next;
177         }
178
179         fprintf(out, "\n");
180 }
181
182 static void write_union(const symbol_t *symbol, const compound_type_t *type)
183 {
184         fprintf(out, "union %s:\n", symbol->string);
185
186         const declaration_t *declaration = type->context.declarations;
187         while(declaration != NULL) {
188                 write_struct_entry(declaration);
189                 declaration = declaration->next;
190         }
191
192         fprintf(out, "\n");
193 }
194
195 static void write_expression(const expression_t *expression);
196
197 static void write_unary_expression(const unary_expression_t *expression)
198 {
199         switch(expression->type) {
200         case UNEXPR_NEGATE:
201                 fputc('-', out);
202                 break;
203         case UNEXPR_NOT:
204                 fputc('!', out);
205                 break;
206         default:
207                 panic("unimeplemented unary expression found");
208         }
209         write_expression(expression->value);
210 }
211
212 static void write_expression(const expression_t *expression)
213 {
214         const const_t *constant;
215         /* TODO */
216         switch(expression->type) {
217         case EXPR_CONST:
218                 constant = (const const_t*) expression;
219                 fprintf(out, "%d", constant->value);
220                 break;
221         case EXPR_UNARY:
222                 write_unary_expression((const unary_expression_t*) expression);
223                 break;
224         default:
225                 panic("not implemented expression");
226         }
227 }
228
229 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
230 {
231         fprintf(out, "enum %s:\n", symbol->string);
232
233         declaration_t *entry = type->entries_begin;
234         for ( ; entry != type->entries_end->next; entry = entry->next) {
235                 fprintf(out, "\t%s", entry->symbol->string);
236                 if(entry->initializer != NULL) {
237                         fprintf(out, " <- ");
238                         write_expression(entry->initializer);
239                 }
240                 fputc('\n', out);
241         }
242         fprintf(out, "typealias %s <- int\n", symbol->string);
243         fprintf(out, "\n");
244 }
245
246 static void write_variable(const declaration_t *declaration)
247 {
248         fprintf(out, "var %s : ", declaration->symbol->string);
249         write_type(declaration->type);
250         /* TODO: initializers */
251         fprintf(out, "\n");
252 }
253
254 static void write_function(const declaration_t *declaration)
255 {
256         if(declaration->statement != NULL) {
257                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
258                         declaration->symbol->string);
259         }
260
261         fprintf(out, "func extern %s(",
262                 declaration->symbol->string);
263
264         const method_type_t *method_type = (const method_type_t*) declaration->type;
265
266         declaration_t *parameter = declaration->context.declarations;
267         int            first     = 1;
268         for( ; parameter != NULL; parameter = parameter->next) {
269                 if(!first) {
270                         fprintf(out, ", ");
271                 } else {
272                         first = 0;
273                 }
274                 if(parameter->symbol != NULL) {
275                         fprintf(out, "%s : ", parameter->symbol->string);
276                 } else {
277                         fputs("_ : ", out);
278                 }
279                 write_type(parameter->type);
280         }
281         if(method_type->variadic) {
282                 if(!first) {
283                         fprintf(out, ", ");
284                 } else {
285                         first = 0;
286                 }
287                 fputs("...", out);
288         }
289         fprintf(out, ")");
290
291         const type_t        *result_type = method_type->result_type;
292         if(result_type->type != TYPE_ATOMIC ||
293                         ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
294                 fprintf(out, " : ");
295                 write_type(result_type);
296         }
297         fputc('\n', out);
298 }
299
300 void write_fluffy_decls(const translation_unit_t *unit)
301 {
302 #if 0
303         out = fopen("out.fluffy", "w");
304         if(out == NULL) {
305                 fprintf(stderr, "Couldn't open out.fluffy: %s\n", strerror(errno));
306                 exit(1);
307         }
308 #endif
309         out            = stdout;
310         global_context = &unit->context;
311
312         fprintf(out, "/* WARNING: Automatically generated file */\n");
313
314         /* write structs,unions + enums */
315         declaration_t *declaration = unit->context.declarations;
316         for( ; declaration != NULL; declaration = declaration->next) {
317                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
318                 if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
319                         continue;
320                 }
321                 type_t *type = declaration->type;
322                 if(type->type == TYPE_COMPOUND_STRUCT) {
323                         write_struct(declaration->symbol, (compound_type_t*) type);
324                 } else if(type->type == TYPE_COMPOUND_UNION) {
325                         write_union(declaration->symbol, (compound_type_t*) type);
326                 } else if(type->type == TYPE_ENUM) {
327                         write_enum(declaration->symbol, (enum_type_t*) type);
328                 }
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                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
336                         continue;
337
338                 type_t *type = declaration->type;
339                 if(type->type == TYPE_METHOD)
340                         continue;
341
342                 write_variable(declaration);
343         }
344
345         /* write functions */
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_function(declaration);
357         }
358
359         //fclose(out);
360 }