add license comments
[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 "ast_t.h"
27 #include "type_t.h"
28 #include "type.h"
29 #include "adt/error.h"
30
31 static const scope_t *global_scope;
32 static FILE          *out;
33
34 static void write_type(const type_t *type);
35
36 static const char *get_atomic_type_string(const atomic_type_kind_t type)
37 {
38         switch(type) {
39         case ATOMIC_TYPE_VOID:        return "void";
40         case ATOMIC_TYPE_CHAR:        return "byte";
41         case ATOMIC_TYPE_SCHAR:       return "byte";
42         case ATOMIC_TYPE_UCHAR:       return "unsigned byte";
43         case ATOMIC_TYPE_SHORT:       return "short";
44         case ATOMIC_TYPE_USHORT:      return "unsigned short";
45         case ATOMIC_TYPE_INT:         return "int";
46         case ATOMIC_TYPE_UINT:        return "unsigned int";
47         case ATOMIC_TYPE_LONG:        return "int";
48         case ATOMIC_TYPE_ULONG:       return "unsigned int";
49         case ATOMIC_TYPE_LONGLONG:    return "long";
50         case ATOMIC_TYPE_ULONGLONG:   return "unsigned long";
51         case ATOMIC_TYPE_FLOAT:       return "float";
52         case ATOMIC_TYPE_DOUBLE:      return "double";
53         case ATOMIC_TYPE_LONG_DOUBLE: return "double";
54         case ATOMIC_TYPE_BOOL:        return "bool";
55         default:                      panic("unsupported atomic type");
56         }
57 }
58
59 static void write_atomic_type(const atomic_type_t *type)
60 {
61         fprintf(out, "%s", get_atomic_type_string(type->akind));
62 }
63
64 static void write_pointer_type(const pointer_type_t *type)
65 {
66         write_type(type->points_to);
67         fputc('*', out);
68 }
69
70 static declaration_t *find_typedef(const type_t *type)
71 {
72         /* first: search for a matching typedef in the global type... */
73         declaration_t *declaration = global_scope->declarations;
74         while(declaration != NULL) {
75                 if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
76                         declaration = declaration->next;
77                         continue;
78                 }
79                 if(declaration->type == type)
80                         break;
81                 declaration = declaration->next;
82         }
83
84         return declaration;
85 }
86
87 static void write_compound_type(const compound_type_t *type)
88 {
89         declaration_t *declaration = find_typedef((const type_t*) type);
90         if(declaration != NULL) {
91                 fprintf(out, "%s", declaration->symbol->string);
92                 return;
93         }
94
95         /* does the struct have a name? */
96         symbol_t *symbol = type->declaration->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         declaration_t *declaration = find_typedef((const type_t*) type);
109         if(declaration != NULL) {
110                 fprintf(out, "%s", declaration->symbol->string);
111                 return;
112         }
113
114         /* does the enum have a name? */
115         symbol_t *symbol = type->declaration->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                 break;
179         default:
180                 fprintf(out, "/* TODO type */");
181                 break;
182         }
183 }
184
185 static void write_struct_entry(const declaration_t *declaration)
186 {
187         fprintf(out, "\t%s : ", declaration->symbol->string);
188         write_type(declaration->type);
189         fprintf(out, "\n");
190 }
191
192 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
193 {
194         fprintf(out, "struct %s:\n", symbol->string);
195
196         const declaration_t *declaration = type->declaration->scope.declarations;
197         while(declaration != NULL) {
198                 write_struct_entry(declaration);
199                 declaration = declaration->next;
200         }
201
202         fprintf(out, "\n");
203 }
204
205 static void write_union(const symbol_t *symbol, const compound_type_t *type)
206 {
207         fprintf(out, "union %s:\n", symbol->string);
208
209         const declaration_t *declaration = type->declaration->scope.declarations;
210         while(declaration != NULL) {
211                 write_struct_entry(declaration);
212                 declaration = declaration->next;
213         }
214
215         fprintf(out, "\n");
216 }
217
218 static void write_expression(const expression_t *expression);
219
220 static void write_unary_expression(const unary_expression_t *expression)
221 {
222         switch(expression->base.kind) {
223         case EXPR_UNARY_NEGATE:
224                 fputc('-', out);
225                 break;
226         case EXPR_UNARY_NOT:
227                 fputc('!', out);
228                 break;
229         default:
230                 panic("unimeplemented unary expression found");
231         }
232         write_expression(expression->value);
233 }
234
235 static void write_expression(const expression_t *expression)
236 {
237         const const_expression_t *constant;
238         /* TODO */
239         switch(expression->kind) {
240         case EXPR_CONST:
241                 constant = &expression->conste;
242                 if(is_type_integer(expression->base.type)) {
243                         fprintf(out, "%lld", constant->v.int_value);
244                 } else {
245                         fprintf(out, "%Lf", constant->v.float_value);
246                 }
247                 break;
248         EXPR_UNARY_CASES
249                 write_unary_expression((const unary_expression_t*) expression);
250                 break;
251         default:
252                 panic("not implemented expression");
253         }
254 }
255
256 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
257 {
258         fprintf(out, "enum %s:\n", symbol->string);
259
260         declaration_t *entry = type->declaration->next;
261         for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
262                         entry = entry->next) {
263                 fprintf(out, "\t%s", entry->symbol->string);
264                 if(entry->init.initializer != NULL) {
265                         fprintf(out, " <- ");
266                         write_expression(entry->init.enum_value);
267                 }
268                 fputc('\n', out);
269         }
270         fprintf(out, "typealias %s <- int\n", symbol->string);
271         fprintf(out, "\n");
272 }
273
274 static void write_variable(const declaration_t *declaration)
275 {
276         fprintf(out, "var %s : ", declaration->symbol->string);
277         write_type(declaration->type);
278         /* TODO: initializers */
279         fprintf(out, "\n");
280 }
281
282 static void write_function(const declaration_t *declaration)
283 {
284         if(declaration->init.statement != NULL) {
285                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
286                         declaration->symbol->string);
287         }
288
289         fprintf(out, "func extern %s(",
290                 declaration->symbol->string);
291
292         const function_type_t *function_type
293                 = (const function_type_t*) declaration->type;
294
295         declaration_t *parameter = declaration->scope.declarations;
296         int            first     = 1;
297         for( ; parameter != NULL; parameter = parameter->next) {
298                 if(!first) {
299                         fprintf(out, ", ");
300                 } else {
301                         first = 0;
302                 }
303                 if(parameter->symbol != NULL) {
304                         fprintf(out, "%s : ", parameter->symbol->string);
305                 } else {
306                         fputs("_ : ", out);
307                 }
308                 write_type(parameter->type);
309         }
310         if(function_type->variadic) {
311                 if(!first) {
312                         fprintf(out, ", ");
313                 } else {
314                         first = 0;
315                 }
316                 fputs("...", out);
317         }
318         fprintf(out, ")");
319
320         const type_t *return_type = function_type->return_type;
321         if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
322                 fprintf(out, " : ");
323                 write_type(return_type);
324         }
325         fputc('\n', out);
326 }
327
328 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
329 {
330         out            = output;
331         global_scope = &unit->scope;
332
333         ast_set_output(out);
334         fprintf(out, "/* WARNING: Automatically generated file */\n");
335
336         /* write structs,unions + enums */
337         declaration_t *declaration = unit->scope.declarations;
338         for( ; declaration != NULL; declaration = declaration->next) {
339                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
340                 if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
341                         continue;
342                 }
343                 type_t *type = declaration->type;
344                 if(type->kind == TYPE_COMPOUND_STRUCT) {
345                         write_struct(declaration->symbol, &type->compound);
346                 } else if(type->kind == TYPE_COMPOUND_UNION) {
347                         write_union(declaration->symbol, &type->compound);
348                 } else if(type->kind == TYPE_ENUM) {
349                         write_enum(declaration->symbol, &type->enumt);
350                 }
351         }
352
353         /* write global variables */
354         declaration = unit->scope.declarations;
355         for( ; declaration != NULL; declaration = declaration->next) {
356                 if(declaration->namespc != NAMESPACE_NORMAL)
357                         continue;
358                 if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
359                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
360                         continue;
361
362                 type_t *type = declaration->type;
363                 if(type->kind == TYPE_FUNCTION)
364                         continue;
365
366                 write_variable(declaration);
367         }
368
369         /* write functions */
370         declaration = unit->scope.declarations;
371         for( ; declaration != NULL; declaration = declaration->next) {
372                 if(declaration->namespc != NAMESPACE_NORMAL)
373                         continue;
374                 if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
375                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
376                         continue;
377
378                 type_t *type = declaration->type;
379                 if(type->kind != TYPE_FUNCTION)
380                         continue;
381
382                 write_function(declaration);
383         }
384 }