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