- Rework the way literals are handled, these are now kept as strings until
[cparser] / wrappergen / write_fluffy.c
1 /*
2  * This file is part of cparser.
3  * Copyright (C) 2007-2009 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 #include "printer.h"
33
34 static const scope_t *global_scope;
35 static FILE          *out;
36
37 static void write_type(const type_t *type);
38
39 static const char *get_atomic_type_string(const atomic_type_kind_t type)
40 {
41         switch(type) {
42         case ATOMIC_TYPE_VOID:        return "void";
43         case ATOMIC_TYPE_CHAR:        return "byte";
44         case ATOMIC_TYPE_SCHAR:       return "byte";
45         case ATOMIC_TYPE_UCHAR:       return "unsigned byte";
46         case ATOMIC_TYPE_SHORT:       return "short";
47         case ATOMIC_TYPE_USHORT:      return "unsigned short";
48         case ATOMIC_TYPE_INT:         return "int";
49         case ATOMIC_TYPE_UINT:        return "unsigned int";
50         case ATOMIC_TYPE_LONG:        return "int";
51         case ATOMIC_TYPE_ULONG:       return "unsigned int";
52         case ATOMIC_TYPE_LONGLONG:    return "long";
53         case ATOMIC_TYPE_ULONGLONG:   return "unsigned long";
54         case ATOMIC_TYPE_FLOAT:       return "float";
55         case ATOMIC_TYPE_DOUBLE:      return "double";
56         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
57         case ATOMIC_TYPE_BOOL:        return "bool";
58         default:                      panic("unsupported atomic type");
59         }
60 }
61
62 static void write_atomic_type(const atomic_type_t *type)
63 {
64         fprintf(out, "%s", get_atomic_type_string(type->akind));
65 }
66
67 static void write_pointer_type(const pointer_type_t *type)
68 {
69         write_type(type->points_to);
70         fputc('*', out);
71 }
72
73 static entity_t *find_typedef(const type_t *type)
74 {
75         /* first: search for a matching typedef in the global type... */
76         entity_t *entity = global_scope->entities;
77         for ( ; entity != NULL; entity = entity->base.next) {
78                 if (entity->kind != ENTITY_TYPEDEF)
79                         continue;
80                 if (entity->typedefe.type == type)
81                         break;
82         }
83
84         return entity;
85 }
86
87 static void write_compound_type(const compound_type_t *type)
88 {
89         entity_t *entity = find_typedef((const type_t*) type);
90         if(entity != NULL) {
91                 fprintf(out, "%s", entity->base.symbol->string);
92                 return;
93         }
94
95         /* does the struct have a name? */
96         symbol_t *symbol = type->compound->base.symbol;
97         if(symbol != NULL) {
98                 /* TODO: make sure we create a struct 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 struct */byte");
104 }
105
106 static void write_enum_type(const enum_type_t *type)
107 {
108         entity_t *entity = find_typedef((const type_t*) type);
109         if (entity != NULL) {
110                 fprintf(out, "%s", entity->base.symbol->string);
111                 return;
112         }
113
114         /* does the enum have a name? */
115         symbol_t *symbol = type->enume->base.symbol;
116         if (symbol != NULL) {
117                 /* TODO: make sure we create an enum for it... */
118                 fprintf(out, "%s", symbol->string);
119                 return;
120         }
121         /* TODO: create a struct and use its name here... */
122         fprintf(out, "/* TODO anonymous enum */byte");
123 }
124
125 static void write_function_type(const function_type_t *type)
126 {
127         fprintf(out, "(func(");
128
129         function_parameter_t *parameter = type->parameters;
130         int                   first     = 1;
131         while(parameter != NULL) {
132                 if(!first) {
133                         fprintf(out, ", ");
134                 } else {
135                         first = 0;
136                 }
137
138 #if 0
139                 if(parameter->symbol != NULL) {
140                         fprintf(out, "%s : ", parameter->symbol->string);
141                 } else {
142                         /* TODO make up some unused names (or allow _ in fluffy?) */
143                         fprintf(out, "_ : ");
144                 }
145 #endif
146                 fputs("_ : ", out);
147                 write_type(parameter->type);
148
149                 parameter = parameter->next;
150         }
151
152         fprintf(out, ") : ");
153         write_type(type->return_type);
154         fprintf(out, ")");
155 }
156
157 static void write_type(const type_t *type)
158 {
159         switch(type->kind) {
160         case TYPE_ATOMIC:
161                 write_atomic_type(&type->atomic);
162                 return;
163         case TYPE_POINTER:
164                 write_pointer_type(&type->pointer);
165                 return;
166         case TYPE_COMPOUND_UNION:
167         case TYPE_COMPOUND_STRUCT:
168                 write_compound_type(&type->compound);
169                 return;
170         case TYPE_ENUM:
171                 write_enum_type(&type->enumt);
172                 return;
173         case TYPE_FUNCTION:
174                 write_function_type(&type->function);
175                 return;
176         case TYPE_INVALID:
177                 panic("invalid type found");
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         switch(expression->kind) {
227         case EXPR_LITERAL_INTEGER:
228                 fprintf(out, "%s", expression->literal.value.begin);
229                 break;
230         EXPR_UNARY_CASES
231                 write_unary_expression((const unary_expression_t*) expression);
232                 break;
233         default:
234                 panic("not implemented expression");
235         }
236 }
237
238 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
239 {
240         fprintf(out, "enum %s:\n", symbol->string);
241
242         entity_t *entry = type->enume->base.next;
243         for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
244                         entry = entry->base.next) {
245                 fprintf(out, "\t%s", entry->base.symbol->string);
246                 if(entry->enum_value.value != NULL) {
247                         fprintf(out, " <- ");
248                         write_expression(entry->enum_value.value);
249                 }
250                 fputc('\n', out);
251         }
252         fprintf(out, "typealias %s <- int\n", symbol->string);
253         fprintf(out, "\n");
254 }
255
256 static void write_variable(const entity_t *entity)
257 {
258         fprintf(out, "var %s : ", entity->base.symbol->string);
259         write_type(entity->declaration.type);
260         fprintf(out, "\n");
261 }
262
263 static void write_function(const entity_t *entity)
264 {
265         if (entity->function.statement != NULL) {
266                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
267                         entity->base.symbol->string);
268         }
269
270         fprintf(out, "func extern %s(", entity->base.symbol->string);
271
272         const function_type_t *function_type
273                 = (const function_type_t*) entity->declaration.type;
274
275         entity_t *parameter = entity->function.parameters.entities;
276         int       first     = 1;
277         for( ; parameter != NULL; parameter = parameter->base.next) {
278                 assert(parameter->kind == ENTITY_PARAMETER);
279                 if(!first) {
280                         fprintf(out, ", ");
281                 } else {
282                         first = 0;
283                 }
284                 if(parameter->base.symbol != NULL) {
285                         fprintf(out, "%s : ", parameter->base.symbol->string);
286                 } else {
287                         fputs("_ : ", out);
288                 }
289                 write_type(parameter->declaration.type);
290         }
291         if(function_type->variadic) {
292                 if(!first) {
293                         fprintf(out, ", ");
294                 } else {
295                         first = 0;
296                 }
297                 fputs("...", out);
298         }
299         fprintf(out, ")");
300
301         const type_t *return_type = skip_typeref(function_type->return_type);
302         if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
303                 fprintf(out, " : ");
304                 write_type(return_type);
305         }
306         fputc('\n', out);
307 }
308
309 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
310 {
311         out            = output;
312         global_scope = &unit->scope;
313
314         print_to_file(out);
315         fprintf(out, "/* WARNING: Automatically generated file */\n");
316
317         /* write structs,unions + enums */
318         entity_t *entity = unit->scope.entities;
319         for( ; entity != NULL; entity = entity->base.next) {
320                 if (entity->kind != ENTITY_TYPEDEF)
321                         continue;
322
323                 type_t *type = entity->typedefe.type;
324                 if(type->kind == TYPE_COMPOUND_STRUCT
325                                 || type->kind == TYPE_COMPOUND_UNION) {
326                         write_compound(entity->base.symbol, &type->compound);
327                 } else if(type->kind == TYPE_ENUM) {
328                         write_enum(entity->base.symbol, &type->enumt);
329                 }
330         }
331
332         /* write global variables */
333         entity = unit->scope.entities;
334         for( ; entity != NULL; entity = entity->base.next) {
335                 if (entity->kind != ENTITY_VARIABLE)
336                         continue;
337
338                 write_variable(entity);
339         }
340
341         /* write functions */
342         entity = unit->scope.entities;
343         for( ; entity != NULL; entity = entity->base.next) {
344                 if (entity->kind != ENTITY_FUNCTION)
345                         continue;
346
347                 write_function(entity);
348         }
349 }