2 * This file is part of cparser.
3 * Copyright (C) 2007-2009 Matthias Braun <matze@braunis.de>
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.
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.
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
25 #include "write_fluffy.h"
26 #include "separator_t.h"
32 #include "adt/error.h"
35 static const scope_t *global_scope;
38 static void write_type(const type_t *type);
40 static const char *get_atomic_type_string(const atomic_type_kind_t type)
43 case ATOMIC_TYPE_VOID: return "void";
44 case ATOMIC_TYPE_CHAR: return "byte";
45 case ATOMIC_TYPE_SCHAR: return "byte";
46 case ATOMIC_TYPE_UCHAR: return "unsigned byte";
47 case ATOMIC_TYPE_SHORT: return "short";
48 case ATOMIC_TYPE_USHORT: return "unsigned short";
49 case ATOMIC_TYPE_INT: return "int";
50 case ATOMIC_TYPE_UINT: return "unsigned int";
51 case ATOMIC_TYPE_LONG: return "int";
52 case ATOMIC_TYPE_ULONG: return "unsigned int";
53 case ATOMIC_TYPE_LONGLONG: return "long";
54 case ATOMIC_TYPE_ULONGLONG: return "unsigned long";
55 case ATOMIC_TYPE_FLOAT: return "float";
56 case ATOMIC_TYPE_DOUBLE: return "double";
57 case ATOMIC_TYPE_LONG_DOUBLE: return "double";
58 case ATOMIC_TYPE_BOOL: return "bool";
59 default: panic("unsupported atomic type");
63 static void write_atomic_type(const atomic_type_t *type)
65 fprintf(out, "%s", get_atomic_type_string(type->akind));
68 static void write_pointer_type(const pointer_type_t *type)
70 write_type(type->points_to);
74 static entity_t *find_typedef(const type_t *type)
76 /* first: search for a matching typedef in the global type... */
77 entity_t *entity = global_scope->entities;
78 for ( ; entity != NULL; entity = entity->base.next) {
79 if (entity->kind != ENTITY_TYPEDEF)
81 if (entity->typedefe.type == type)
88 static void write_compound_type(const compound_type_t *type)
90 entity_t *entity = find_typedef((const type_t*) type);
92 fprintf(out, "%s", entity->base.symbol->string);
96 /* does the struct have a name? */
97 symbol_t *symbol = type->compound->base.symbol;
99 /* TODO: make sure we create a struct for it... */
100 fprintf(out, "%s", symbol->string);
103 /* TODO: create a struct and use its name here... */
104 fprintf(out, "/* TODO anonymous struct */byte");
107 static void write_enum_type(const enum_type_t *type)
109 entity_t *entity = find_typedef((const type_t*) type);
110 if (entity != NULL) {
111 fprintf(out, "%s", entity->base.symbol->string);
115 /* does the enum have a name? */
116 symbol_t *symbol = type->enume->base.symbol;
117 if (symbol != NULL) {
118 /* TODO: make sure we create an enum for it... */
119 fprintf(out, "%s", symbol->string);
122 /* TODO: create a struct and use its name here... */
123 fprintf(out, "/* TODO anonymous enum */byte");
126 static void write_function_type(const function_type_t *type)
128 fprintf(out, "(func(");
130 function_parameter_t *parameter = type->parameters;
131 separator_t sep = { "", ", " };
132 while(parameter != NULL) {
133 fputs(sep_next(&sep), out);
136 if(parameter->symbol != NULL) {
137 fprintf(out, "%s : ", parameter->symbol->string);
139 /* TODO make up some unused names (or allow _ in fluffy?) */
140 fprintf(out, "_ : ");
144 write_type(parameter->type);
146 parameter = parameter->next;
149 fprintf(out, ") : ");
150 write_type(type->return_type);
154 static void write_type(const type_t *type)
158 write_atomic_type(&type->atomic);
161 write_pointer_type(&type->pointer);
163 case TYPE_COMPOUND_UNION:
164 case TYPE_COMPOUND_STRUCT:
165 write_compound_type(&type->compound);
168 write_enum_type(&type->enumt);
171 write_function_type(&type->function);
176 fprintf(out, "/* TODO type */");
181 static void write_compound_entry(const entity_t *entity)
183 fprintf(out, "\t%s : ", entity->base.symbol->string);
184 write_type(entity->declaration.type);
188 static void write_compound(const symbol_t *symbol, const compound_type_t *type)
190 fprintf(out, "%s %s:\n",
191 type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
194 const entity_t *entity = type->compound->members.entities;
195 for ( ; entity != NULL; entity = entity->base.next) {
196 write_compound_entry(entity);
202 static void write_expression(const expression_t *expression);
204 static void write_unary_expression(const unary_expression_t *expression)
206 switch(expression->base.kind) {
207 case EXPR_UNARY_NEGATE:
214 panic("unimplemented unary expression");
216 write_expression(expression->value);
219 static void write_expression(const expression_t *expression)
221 switch(expression->kind) {
222 case EXPR_LITERAL_INTEGER:
223 fprintf(out, "%s", expression->literal.value.begin);
225 case EXPR_UNARY_CASES:
226 write_unary_expression((const unary_expression_t*) expression);
229 panic("not implemented expression");
233 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
235 fprintf(out, "enum %s:\n", symbol->string);
237 entity_t *entry = type->enume->base.next;
238 for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
239 entry = entry->base.next) {
240 fprintf(out, "\t%s", entry->base.symbol->string);
241 if(entry->enum_value.value != NULL) {
242 fprintf(out, " <- ");
243 write_expression(entry->enum_value.value);
247 fprintf(out, "typealias %s <- int\n", symbol->string);
251 static void write_variable(const entity_t *entity)
253 fprintf(out, "var %s : ", entity->base.symbol->string);
254 write_type(entity->declaration.type);
258 static void write_function(const entity_t *entity)
260 if (entity->function.body != NULL) {
261 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
262 entity->base.symbol->string);
265 fprintf(out, "func extern %s(", entity->base.symbol->string);
267 const function_type_t *function_type
268 = (const function_type_t*) entity->declaration.type;
270 entity_t *parameter = entity->function.parameters.entities;
271 separator_t sep = { "", ", " };
272 for( ; parameter != NULL; parameter = parameter->base.next) {
273 assert(parameter->kind == ENTITY_PARAMETER);
274 fputs(sep_next(&sep), out);
275 if(parameter->base.symbol != NULL) {
276 fprintf(out, "%s : ", parameter->base.symbol->string);
280 write_type(parameter->declaration.type);
282 if(function_type->variadic) {
283 fputs(sep_next(&sep), out);
288 const type_t *return_type = skip_typeref(function_type->return_type);
289 if (!is_type_void(return_type)) {
291 write_type(return_type);
296 void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
299 global_scope = &unit->scope;
302 fprintf(out, "/* WARNING: Automatically generated file */\n");
304 /* write structs,unions + enums */
305 entity_t *entity = unit->scope.entities;
306 for( ; entity != NULL; entity = entity->base.next) {
307 if (entity->kind != ENTITY_TYPEDEF)
310 type_t *type = entity->typedefe.type;
311 if (is_type_compound(type)) {
312 write_compound(entity->base.symbol, &type->compound);
313 } else if(type->kind == TYPE_ENUM) {
314 write_enum(entity->base.symbol, &type->enumt);
318 /* write global variables */
319 entity = unit->scope.entities;
320 for( ; entity != NULL; entity = entity->base.next) {
321 if (entity->kind != ENTITY_VARIABLE)
324 write_variable(entity);
327 /* write functions */
328 entity = unit->scope.entities;
329 for( ; entity != NULL; entity = entity->base.next) {
330 if (entity->kind != ENTITY_FUNCTION)
333 write_function(entity);