ast2firm: Implement casting from complex to real types.
[cparser] / wrappergen / write_fluffy.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2012 Matthias Braun <matze@braunis.de>
4  */
5 #include <config.h>
6
7 #include <errno.h>
8 #include <string.h>
9
10 #include "write_fluffy.h"
11 #include "separator_t.h"
12 #include "symbol_t.h"
13 #include "ast_t.h"
14 #include "type_t.h"
15 #include "entity_t.h"
16 #include "type.h"
17 #include "adt/error.h"
18 #include "printer.h"
19
20 static const scope_t *global_scope;
21 static FILE          *out;
22
23 static void write_type(const type_t *type);
24
25 static const char *get_atomic_type_string(const atomic_type_kind_t type)
26 {
27         switch(type) {
28         case ATOMIC_TYPE_VOID:        return "void";
29         case ATOMIC_TYPE_CHAR:        return "byte";
30         case ATOMIC_TYPE_SCHAR:       return "byte";
31         case ATOMIC_TYPE_UCHAR:       return "unsigned byte";
32         case ATOMIC_TYPE_SHORT:       return "short";
33         case ATOMIC_TYPE_USHORT:      return "unsigned short";
34         case ATOMIC_TYPE_INT:         return "int";
35         case ATOMIC_TYPE_UINT:        return "unsigned int";
36         case ATOMIC_TYPE_LONG:        return "int";
37         case ATOMIC_TYPE_ULONG:       return "unsigned int";
38         case ATOMIC_TYPE_LONGLONG:    return "long";
39         case ATOMIC_TYPE_ULONGLONG:   return "unsigned long";
40         case ATOMIC_TYPE_FLOAT:       return "float";
41         case ATOMIC_TYPE_DOUBLE:      return "double";
42         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
43         case ATOMIC_TYPE_BOOL:        return "bool";
44         default:                      panic("unsupported atomic type");
45         }
46 }
47
48 static void write_atomic_type(const atomic_type_t *type)
49 {
50         fprintf(out, "%s", get_atomic_type_string(type->akind));
51 }
52
53 static void write_pointer_type(const pointer_type_t *type)
54 {
55         write_type(type->points_to);
56         fputc('*', out);
57 }
58
59 static entity_t *find_typedef(const type_t *type)
60 {
61         /* first: search for a matching typedef in the global type... */
62         entity_t *entity = global_scope->entities;
63         for ( ; entity != NULL; entity = entity->base.next) {
64                 if (entity->kind != ENTITY_TYPEDEF)
65                         continue;
66                 if (entity->typedefe.type == type)
67                         break;
68         }
69
70         return entity;
71 }
72
73 static void write_compound_type(const compound_type_t *type)
74 {
75         entity_t *entity = find_typedef((const type_t*) type);
76         if(entity != NULL) {
77                 fprintf(out, "%s", entity->base.symbol->string);
78                 return;
79         }
80
81         /* does the struct have a name? */
82         symbol_t *symbol = type->compound->base.symbol;
83         if(symbol != NULL) {
84                 /* TODO: make sure we create a struct for it... */
85                 fprintf(out, "%s", symbol->string);
86                 return;
87         }
88         /* TODO: create a struct and use its name here... */
89         fprintf(out, "/* TODO anonymous struct */byte");
90 }
91
92 static void write_enum_type(const enum_type_t *type)
93 {
94         entity_t *entity = find_typedef((const type_t*) type);
95         if (entity != NULL) {
96                 fprintf(out, "%s", entity->base.symbol->string);
97                 return;
98         }
99
100         /* does the enum have a name? */
101         symbol_t *symbol = type->enume->base.symbol;
102         if (symbol != NULL) {
103                 /* TODO: make sure we create an enum for it... */
104                 fprintf(out, "%s", symbol->string);
105                 return;
106         }
107         /* TODO: create a struct and use its name here... */
108         fprintf(out, "/* TODO anonymous enum */byte");
109 }
110
111 static void write_function_type(const function_type_t *type)
112 {
113         fprintf(out, "(func(");
114
115         function_parameter_t *parameter = type->parameters;
116         separator_t           sep       = { "", ", " };
117         while(parameter != NULL) {
118                 fputs(sep_next(&sep), out);
119
120 #if 0
121                 if(parameter->symbol != NULL) {
122                         fprintf(out, "%s : ", parameter->symbol->string);
123                 } else {
124                         /* TODO make up some unused names (or allow _ in fluffy?) */
125                         fprintf(out, "_ : ");
126                 }
127 #endif
128                 fputs("_ : ", out);
129                 write_type(parameter->type);
130
131                 parameter = parameter->next;
132         }
133
134         fprintf(out, ") : ");
135         write_type(type->return_type);
136         fprintf(out, ")");
137 }
138
139 static void write_type(const type_t *type)
140 {
141         switch(type->kind) {
142         case TYPE_ATOMIC:
143                 write_atomic_type(&type->atomic);
144                 return;
145         case TYPE_POINTER:
146                 write_pointer_type(&type->pointer);
147                 return;
148         case TYPE_COMPOUND_UNION:
149         case TYPE_COMPOUND_STRUCT:
150                 write_compound_type(&type->compound);
151                 return;
152         case TYPE_ENUM:
153                 write_enum_type(&type->enumt);
154                 return;
155         case TYPE_FUNCTION:
156                 write_function_type(&type->function);
157                 return;
158         case TYPE_COMPLEX:
159         case TYPE_IMAGINARY:
160         default:
161                 fprintf(out, "/* TODO type */");
162                 break;
163         }
164 }
165
166 static void write_compound_entry(const entity_t *entity)
167 {
168         fprintf(out, "\t%s : ", entity->base.symbol->string);
169         write_type(entity->declaration.type);
170         fprintf(out, "\n");
171 }
172
173 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
174 {
175         fprintf(out, "%s %s:\n",
176                 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
177                         symbol->string);
178
179         const entity_t *entity = type->compound->members.entities;
180         for ( ; entity != NULL; entity = entity->base.next) {
181                 write_compound_entry(entity);
182         }
183
184         fprintf(out, "\n");
185 }
186
187 static void write_expression(const expression_t *expression);
188
189 static void write_unary_expression(const unary_expression_t *expression)
190 {
191         switch(expression->base.kind) {
192         case EXPR_UNARY_NEGATE:
193                 fputc('-', out);
194                 break;
195         case EXPR_UNARY_NOT:
196                 fputc('!', out);
197                 break;
198         default:
199                 panic("unimplemented unary expression");
200         }
201         write_expression(expression->value);
202 }
203
204 static void write_expression(const expression_t *expression)
205 {
206         switch(expression->kind) {
207         case EXPR_LITERAL_INTEGER:
208                 fprintf(out, "%s", expression->literal.value.begin);
209                 break;
210         case EXPR_UNARY_CASES:
211                 write_unary_expression((const unary_expression_t*) expression);
212                 break;
213         default:
214                 panic("not implemented expression");
215         }
216 }
217
218 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
219 {
220         fprintf(out, "enum %s:\n", symbol->string);
221
222         entity_t *entry = type->enume->base.next;
223         for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
224                         entry = entry->base.next) {
225                 fprintf(out, "\t%s", entry->base.symbol->string);
226                 if(entry->enum_value.value != NULL) {
227                         fprintf(out, " <- ");
228                         write_expression(entry->enum_value.value);
229                 }
230                 fputc('\n', out);
231         }
232         fprintf(out, "typealias %s <- int\n", symbol->string);
233         fprintf(out, "\n");
234 }
235
236 static void write_variable(const entity_t *entity)
237 {
238         fprintf(out, "var %s : ", entity->base.symbol->string);
239         write_type(entity->declaration.type);
240         fprintf(out, "\n");
241 }
242
243 static void write_function(const entity_t *entity)
244 {
245         if (entity->function.body != NULL) {
246                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
247                         entity->base.symbol->string);
248         }
249
250         fprintf(out, "func extern %s(", entity->base.symbol->string);
251
252         const function_type_t *function_type
253                 = (const function_type_t*) entity->declaration.type;
254
255         entity_t   *parameter = entity->function.parameters.entities;
256         separator_t sep       = { "", ", " };
257         for( ; parameter != NULL; parameter = parameter->base.next) {
258                 assert(parameter->kind == ENTITY_PARAMETER);
259                 fputs(sep_next(&sep), out);
260                 if(parameter->base.symbol != NULL) {
261                         fprintf(out, "%s : ", parameter->base.symbol->string);
262                 } else {
263                         fputs("_ : ", out);
264                 }
265                 write_type(parameter->declaration.type);
266         }
267         if(function_type->variadic) {
268                 fputs(sep_next(&sep), out);
269                 fputs("...", out);
270         }
271         fprintf(out, ")");
272
273         const type_t *return_type = skip_typeref(function_type->return_type);
274         if (!is_type_void(return_type)) {
275                 fprintf(out, " : ");
276                 write_type(return_type);
277         }
278         fputc('\n', out);
279 }
280
281 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
282 {
283         out            = output;
284         global_scope = &unit->scope;
285
286         print_to_file(out);
287         fprintf(out, "/* WARNING: Automatically generated file */\n");
288
289         /* write structs,unions + enums */
290         entity_t *entity = unit->scope.entities;
291         for( ; entity != NULL; entity = entity->base.next) {
292                 if (entity->kind != ENTITY_TYPEDEF)
293                         continue;
294
295                 type_t *type = entity->typedefe.type;
296                 if (is_type_compound(type)) {
297                         write_compound(entity->base.symbol, &type->compound);
298                 } else if(type->kind == TYPE_ENUM) {
299                         write_enum(entity->base.symbol, &type->enumt);
300                 }
301         }
302
303         /* write global variables */
304         entity = unit->scope.entities;
305         for( ; entity != NULL; entity = entity->base.next) {
306                 if (entity->kind != ENTITY_VARIABLE)
307                         continue;
308
309                 write_variable(entity);
310         }
311
312         /* write functions */
313         entity = unit->scope.entities;
314         for( ; entity != NULL; entity = entity->base.next) {
315                 if (entity->kind != ENTITY_FUNCTION)
316                         continue;
317
318                 write_function(entity);
319         }
320 }