63dbe9abe9768510c47edae17bfc5d78fc873318
[cparser] / write_fluffy.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18  * 02111-1307, USA.
19  */
20 #include <config.h>
21
22 #include <errno.h>
23 #include <string.h>
24
25 #include "write_fluffy.h"
26 #include "symbol_t.h"
27 #include "ast_t.h"
28 #include "type_t.h"
29 #include "entity_t.h"
30 #include "type.h"
31 #include "adt/error.h"
32
33 static const scope_t *global_scope;
34 static FILE          *out;
35
36 static void write_type(const type_t *type);
37
38 static const char *get_atomic_type_string(const atomic_type_kind_t type)
39 {
40         switch(type) {
41         case ATOMIC_TYPE_VOID:        return "void";
42         case ATOMIC_TYPE_CHAR:        return "byte";
43         case ATOMIC_TYPE_SCHAR:       return "byte";
44         case ATOMIC_TYPE_UCHAR:       return "unsigned byte";
45         case ATOMIC_TYPE_SHORT:       return "short";
46         case ATOMIC_TYPE_USHORT:      return "unsigned short";
47         case ATOMIC_TYPE_INT:         return "int";
48         case ATOMIC_TYPE_UINT:        return "unsigned int";
49         case ATOMIC_TYPE_LONG:        return "int";
50         case ATOMIC_TYPE_ULONG:       return "unsigned int";
51         case ATOMIC_TYPE_LONGLONG:    return "long";
52         case ATOMIC_TYPE_ULONGLONG:   return "unsigned long";
53         case ATOMIC_TYPE_FLOAT:       return "float";
54         case ATOMIC_TYPE_DOUBLE:      return "double";
55         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
56         case ATOMIC_TYPE_BOOL:        return "bool";
57         default:                      panic("unsupported atomic type");
58         }
59 }
60
61 static void write_atomic_type(const atomic_type_t *type)
62 {
63         fprintf(out, "%s", get_atomic_type_string(type->akind));
64 }
65
66 static void write_pointer_type(const pointer_type_t *type)
67 {
68         write_type(type->points_to);
69         fputc('*', out);
70 }
71
72 static entity_t *find_typedef(const type_t *type)
73 {
74         /* first: search for a matching typedef in the global type... */
75         entity_t *entity = global_scope->entities;
76         for ( ; entity != NULL; entity = entity->base.next) {
77                 if (entity->kind != ENTITY_TYPEDEF)
78                         continue;
79                 if (entity->typedefe.type == type)
80                         break;
81         }
82
83         return entity;
84 }
85
86 static void write_compound_type(const compound_type_t *type)
87 {
88         entity_t *entity = find_typedef((const type_t*) type);
89         if(entity != NULL) {
90                 fprintf(out, "%s", entity->base.symbol->string);
91                 return;
92         }
93
94         /* does the struct have a name? */
95         symbol_t *symbol = type->compound->base.symbol;
96         if(symbol != NULL) {
97                 /* TODO: make sure we create a struct for it... */
98                 fprintf(out, "%s", symbol->string);
99                 return;
100         }
101         /* TODO: create a struct and use its name here... */
102         fprintf(out, "/* TODO anonymous struct */byte");
103 }
104
105 static void write_enum_type(const enum_type_t *type)
106 {
107         entity_t *entity = find_typedef((const type_t*) type);
108         if (entity != NULL) {
109                 fprintf(out, "%s", entity->base.symbol->string);
110                 return;
111         }
112
113         /* does the enum have a name? */
114         symbol_t *symbol = type->enume->base.symbol;
115         if (symbol != NULL) {
116                 /* TODO: make sure we create an enum for it... */
117                 fprintf(out, "%s", symbol->string);
118                 return;
119         }
120         /* TODO: create a struct and use its name here... */
121         fprintf(out, "/* TODO anonymous enum */byte");
122 }
123
124 static void write_function_type(const function_type_t *type)
125 {
126         fprintf(out, "(func(");
127
128         function_parameter_t *parameter = type->parameters;
129         int                   first     = 1;
130         while(parameter != NULL) {
131                 if(!first) {
132                         fprintf(out, ", ");
133                 } else {
134                         first = 0;
135                 }
136
137 #if 0
138                 if(parameter->symbol != NULL) {
139                         fprintf(out, "%s : ", parameter->symbol->string);
140                 } else {
141                         /* TODO make up some unused names (or allow _ in fluffy?) */
142                         fprintf(out, "_ : ");
143                 }
144 #endif
145                 fputs("_ : ", out);
146                 write_type(parameter->type);
147
148                 parameter = parameter->next;
149         }
150
151         fprintf(out, ") : ");
152         write_type(type->return_type);
153         fprintf(out, ")");
154 }
155
156 static void write_type(const type_t *type)
157 {
158         switch(type->kind) {
159         case TYPE_ATOMIC:
160                 write_atomic_type(&type->atomic);
161                 return;
162         case TYPE_POINTER:
163                 write_pointer_type(&type->pointer);
164                 return;
165         case TYPE_COMPOUND_UNION:
166         case TYPE_COMPOUND_STRUCT:
167                 write_compound_type(&type->compound);
168                 return;
169         case TYPE_ENUM:
170                 write_enum_type(&type->enumt);
171                 return;
172         case TYPE_FUNCTION:
173                 write_function_type(&type->function);
174                 return;
175         case TYPE_INVALID:
176                 panic("invalid type found");
177                 break;
178         case TYPE_COMPLEX:
179         case TYPE_IMAGINARY:
180         default:
181                 fprintf(out, "/* TODO type */");
182                 break;
183         }
184 }
185
186 static void write_compound_entry(const entity_t *entity)
187 {
188         fprintf(out, "\t%s : ", entity->base.symbol->string);
189         write_type(entity->declaration.type);
190         fprintf(out, "\n");
191 }
192
193 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
194 {
195         fprintf(out, "%s %s:\n",
196                 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
197                         symbol->string);
198
199         const entity_t *entity = type->compound->members.entities;
200         for ( ; entity != NULL; entity = entity->base.next) {
201                 write_compound_entry(entity);
202         }
203
204         fprintf(out, "\n");
205 }
206
207 static void write_expression(const expression_t *expression);
208
209 static void write_unary_expression(const unary_expression_t *expression)
210 {
211         switch(expression->base.kind) {
212         case EXPR_UNARY_NEGATE:
213                 fputc('-', out);
214                 break;
215         case EXPR_UNARY_NOT:
216                 fputc('!', out);
217                 break;
218         default:
219                 panic("unimeplemented unary expression found");
220         }
221         write_expression(expression->value);
222 }
223
224 static void write_expression(const expression_t *expression)
225 {
226         const const_expression_t *constant;
227         /* TODO */
228         switch(expression->kind) {
229         case EXPR_CONST:
230                 constant = &expression->conste;
231                 if(is_type_integer(expression->base.type)) {
232                         fprintf(out, "%lld", constant->v.int_value);
233                 } else {
234                         fprintf(out, "%Lf", constant->v.float_value);
235                 }
236                 break;
237         EXPR_UNARY_CASES
238                 write_unary_expression((const unary_expression_t*) expression);
239                 break;
240         default:
241                 panic("not implemented expression");
242         }
243 }
244
245 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
246 {
247         fprintf(out, "enum %s:\n", symbol->string);
248
249         entity_t *entry = type->enume->base.next;
250         for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
251                         entry = entry->base.next) {
252                 fprintf(out, "\t%s", entry->base.symbol->string);
253                 if(entry->enum_value.value != NULL) {
254                         fprintf(out, " <- ");
255                         write_expression(entry->enum_value.value);
256                 }
257                 fputc('\n', out);
258         }
259         fprintf(out, "typealias %s <- int\n", symbol->string);
260         fprintf(out, "\n");
261 }
262
263 static void write_variable(const entity_t *entity)
264 {
265         fprintf(out, "var %s : ", entity->base.symbol->string);
266         write_type(entity->declaration.type);
267         fprintf(out, "\n");
268 }
269
270 static void write_function(const entity_t *entity)
271 {
272         if (entity->function.statement != NULL) {
273                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
274                         entity->base.symbol->string);
275         }
276
277         fprintf(out, "func extern %s(", entity->base.symbol->string);
278
279         const function_type_t *function_type
280                 = (const function_type_t*) entity->declaration.type;
281
282         entity_t *parameter = entity->function.parameters.entities;
283         int       first     = 1;
284         for( ; parameter != NULL; parameter = parameter->base.next) {
285                 assert(parameter->kind == ENTITY_VARIABLE);
286                 if(!first) {
287                         fprintf(out, ", ");
288                 } else {
289                         first = 0;
290                 }
291                 if(parameter->base.symbol != NULL) {
292                         fprintf(out, "%s : ", parameter->base.symbol->string);
293                 } else {
294                         fputs("_ : ", out);
295                 }
296                 write_type(parameter->declaration.type);
297         }
298         if(function_type->variadic) {
299                 if(!first) {
300                         fprintf(out, ", ");
301                 } else {
302                         first = 0;
303                 }
304                 fputs("...", out);
305         }
306         fprintf(out, ")");
307
308         const type_t *return_type = function_type->return_type;
309         if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
310                 fprintf(out, " : ");
311                 write_type(return_type);
312         }
313         fputc('\n', out);
314 }
315
316 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
317 {
318         out            = output;
319         global_scope = &unit->scope;
320
321         ast_set_output(out);
322         type_set_output(out);
323         fprintf(out, "/* WARNING: Automatically generated file */\n");
324
325         /* write structs,unions + enums */
326         entity_t *entity = unit->scope.entities;
327         for( ; entity != NULL; entity = entity->base.next) {
328                 if (entity->kind != ENTITY_TYPEDEF)
329                         continue;
330
331                 type_t *type = entity->typedefe.type;
332                 if(type->kind == TYPE_COMPOUND_STRUCT
333                                 || type->kind == TYPE_COMPOUND_UNION) {
334                         write_compound(entity->base.symbol, &type->compound);
335                 } else if(type->kind == TYPE_ENUM) {
336                         write_enum(entity->base.symbol, &type->enumt);
337                 }
338         }
339
340         /* write global variables */
341         entity = unit->scope.entities;
342         for( ; entity != NULL; entity = entity->base.next) {
343                 if (entity->kind != ENTITY_VARIABLE)
344                         continue;
345
346                 write_variable(entity);
347         }
348
349         /* write functions */
350         entity = unit->scope.entities;
351         for( ; entity != NULL; entity = entity->base.next) {
352                 if (entity->kind != ENTITY_FUNCTION)
353                         continue;
354
355                 write_function(entity);
356         }
357 }