should be a const expression
[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         default:
181                 fprintf(out, "/* TODO type */");
182                 break;
183         }
184 }
185
186 static void write_struct_entry(const declaration_t *declaration)
187 {
188         fprintf(out, "\t%s : ", declaration->symbol->string);
189         write_type(declaration->type);
190         fprintf(out, "\n");
191 }
192
193 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
194 {
195         fprintf(out, "struct %s:\n", symbol->string);
196
197         const declaration_t *declaration = type->declaration->scope.declarations;
198         while(declaration != NULL) {
199                 write_struct_entry(declaration);
200                 declaration = declaration->next;
201         }
202
203         fprintf(out, "\n");
204 }
205
206 static void write_union(const symbol_t *symbol, const compound_type_t *type)
207 {
208         fprintf(out, "union %s:\n", symbol->string);
209
210         const declaration_t *declaration = type->declaration->scope.declarations;
211         while(declaration != NULL) {
212                 write_struct_entry(declaration);
213                 declaration = declaration->next;
214         }
215
216         fprintf(out, "\n");
217 }
218
219 static void write_expression(const expression_t *expression);
220
221 static void write_unary_expression(const unary_expression_t *expression)
222 {
223         switch(expression->base.kind) {
224         case EXPR_UNARY_NEGATE:
225                 fputc('-', out);
226                 break;
227         case EXPR_UNARY_NOT:
228                 fputc('!', out);
229                 break;
230         default:
231                 panic("unimeplemented unary expression found");
232         }
233         write_expression(expression->value);
234 }
235
236 static void write_expression(const expression_t *expression)
237 {
238         const const_expression_t *constant;
239         /* TODO */
240         switch(expression->kind) {
241         case EXPR_CONST:
242                 constant = &expression->conste;
243                 if(is_type_integer(expression->base.type)) {
244                         fprintf(out, "%lld", constant->v.int_value);
245                 } else {
246                         fprintf(out, "%Lf", constant->v.float_value);
247                 }
248                 break;
249         EXPR_UNARY_CASES
250                 write_unary_expression((const unary_expression_t*) expression);
251                 break;
252         default:
253                 panic("not implemented expression");
254         }
255 }
256
257 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
258 {
259         fprintf(out, "enum %s:\n", symbol->string);
260
261         declaration_t *entry = type->declaration->next;
262         for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
263                         entry = entry->next) {
264                 fprintf(out, "\t%s", entry->symbol->string);
265                 if(entry->init.initializer != NULL) {
266                         fprintf(out, " <- ");
267                         write_expression(entry->init.enum_value);
268                 }
269                 fputc('\n', out);
270         }
271         fprintf(out, "typealias %s <- int\n", symbol->string);
272         fprintf(out, "\n");
273 }
274
275 static void write_variable(const declaration_t *declaration)
276 {
277         fprintf(out, "var %s : ", declaration->symbol->string);
278         write_type(declaration->type);
279         /* TODO: initializers */
280         fprintf(out, "\n");
281 }
282
283 static void write_function(const declaration_t *declaration)
284 {
285         if(declaration->init.statement != NULL) {
286                 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
287                         declaration->symbol->string);
288         }
289
290         fprintf(out, "func extern %s(",
291                 declaration->symbol->string);
292
293         const function_type_t *function_type
294                 = (const function_type_t*) declaration->type;
295
296         declaration_t *parameter = declaration->scope.declarations;
297         int            first     = 1;
298         for( ; parameter != NULL; parameter = parameter->next) {
299                 if(!first) {
300                         fprintf(out, ", ");
301                 } else {
302                         first = 0;
303                 }
304                 if(parameter->symbol != NULL) {
305                         fprintf(out, "%s : ", parameter->symbol->string);
306                 } else {
307                         fputs("_ : ", out);
308                 }
309                 write_type(parameter->type);
310         }
311         if(function_type->variadic) {
312                 if(!first) {
313                         fprintf(out, ", ");
314                 } else {
315                         first = 0;
316                 }
317                 fputs("...", out);
318         }
319         fprintf(out, ")");
320
321         const type_t *return_type = function_type->return_type;
322         if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
323                 fprintf(out, " : ");
324                 write_type(return_type);
325         }
326         fputc('\n', out);
327 }
328
329 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
330 {
331         out            = output;
332         global_scope = &unit->scope;
333
334         ast_set_output(out);
335         fprintf(out, "/* WARNING: Automatically generated file */\n");
336
337         /* write structs,unions + enums */
338         declaration_t *declaration = unit->scope.declarations;
339         for( ; declaration != NULL; declaration = declaration->next) {
340                 //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
341                 if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
342                         continue;
343                 }
344                 type_t *type = declaration->type;
345                 if(type->kind == TYPE_COMPOUND_STRUCT) {
346                         write_struct(declaration->symbol, &type->compound);
347                 } else if(type->kind == TYPE_COMPOUND_UNION) {
348                         write_union(declaration->symbol, &type->compound);
349                 } else if(type->kind == TYPE_ENUM) {
350                         write_enum(declaration->symbol, &type->enumt);
351                 }
352         }
353
354         /* write global variables */
355         declaration = unit->scope.declarations;
356         for( ; declaration != NULL; declaration = declaration->next) {
357                 if(declaration->namespc != NAMESPACE_NORMAL)
358                         continue;
359                 if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
360                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
361                         continue;
362
363                 type_t *type = declaration->type;
364                 if(type->kind == TYPE_FUNCTION)
365                         continue;
366
367                 write_variable(declaration);
368         }
369
370         /* write functions */
371         declaration = unit->scope.declarations;
372         for( ; declaration != NULL; declaration = declaration->next) {
373                 if(declaration->namespc != NAMESPACE_NORMAL)
374                         continue;
375                 if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
376                                 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
377                         continue;
378
379                 type_t *type = declaration->type;
380                 if(type->kind != TYPE_FUNCTION)
381                         continue;
382
383                 write_function(declaration);
384         }
385 }