2 * This file is part of cparser.
3 * Copyright (C) 2007-2008 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_caml.h"
30 #include "adt/error.h"
32 static const scope_t *global_scope;
35 static void write_type(const type_t *type);
37 static const char *get_atomic_type_string(const atomic_type_kind_t type)
40 case ATOMIC_TYPE_VOID: return "unit";
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");
60 static void write_atomic_type(const atomic_type_t *type)
62 fprintf(out, "%s", get_atomic_type_string(type->akind));
65 static void write_pointer_type(const pointer_type_t *type)
67 type_t *points_to = type->points_to;
68 if (points_to->kind == TYPE_ATOMIC &&
69 is_type_atomic(points_to, ATOMIC_TYPE_CHAR)) {
74 write_type(type->points_to);
78 static declaration_t *find_typedef(const type_t *type)
80 /* first: search for a matching typedef in the global type... */
81 declaration_t *declaration = global_scope->declarations;
82 while(declaration != NULL) {
83 if (! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
84 declaration = declaration->next;
87 if (declaration->type == type)
89 declaration = declaration->next;
95 static void write_compound_type(const compound_type_t *type)
97 declaration_t *declaration = find_typedef((const type_t*) type);
98 if (declaration != NULL) {
99 fprintf(out, "%s", declaration->symbol->string);
103 /* does the struct have a name? */
104 symbol_t *symbol = type->declaration->symbol;
105 if (symbol != NULL) {
106 /* TODO: make sure we create a struct for it... */
107 fprintf(out, "%s", symbol->string);
110 /* TODO: create a struct and use its name here... */
111 fprintf(out, "/* TODO anonymous struct */byte");
114 static void write_enum_type(const enum_type_t *type)
116 declaration_t *declaration = find_typedef((const type_t*) type);
117 if (declaration != NULL) {
118 fprintf(out, "%s", declaration->symbol->string);
122 /* does the enum have a name? */
123 symbol_t *symbol = type->declaration->symbol;
124 if (symbol != NULL) {
125 /* TODO: make sure we create an enum for it... */
126 fprintf(out, "%s", symbol->string);
129 /* TODO: create a struct and use its name here... */
130 fprintf(out, "/* TODO anonymous enum */byte");
133 static void write_function_type(const function_type_t *type)
135 fprintf(out, "(func(");
137 function_parameter_t *parameter = type->parameters;
139 while(parameter != NULL) {
147 if (parameter->symbol != NULL) {
148 fprintf(out, "%s : ", parameter->symbol->string);
150 /* TODO make up some unused names (or allow _ in fluffy?) */
151 fprintf(out, "_ : ");
155 write_type(parameter->type);
157 parameter = parameter->next;
160 fprintf(out, ") : ");
161 write_type(type->return_type);
165 static void write_type(const type_t *type)
169 write_atomic_type(&type->atomic);
172 write_pointer_type(&type->pointer);
174 case TYPE_COMPOUND_UNION:
175 case TYPE_COMPOUND_STRUCT:
176 write_compound_type(&type->compound);
179 write_enum_type(&type->enumt);
182 write_function_type(&type->function);
185 panic("invalid type found");
190 fprintf(out, "/* TODO type */");
196 static void write_struct_entry(const declaration_t *declaration)
198 fprintf(out, "\t%s : ", declaration->symbol->string);
199 write_type(declaration->type);
203 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
205 fprintf(out, "struct %s:\n", symbol->string);
207 const declaration_t *declaration = type->declaration->scope.declarations;
208 while(declaration != NULL) {
209 write_struct_entry(declaration);
210 declaration = declaration->next;
216 static void write_union(const symbol_t *symbol, const compound_type_t *type)
218 fprintf(out, "union %s:\n", symbol->string);
220 const declaration_t *declaration = type->declaration->scope.declarations;
221 while(declaration != NULL) {
222 write_struct_entry(declaration);
223 declaration = declaration->next;
229 static void write_expression(const expression_t *expression);
231 static void write_unary_expression(const unary_expression_t *expression)
233 switch(expression->base.kind) {
234 case EXPR_UNARY_NEGATE:
241 panic("unimeplemented unary expression found");
243 write_expression(expression->value);
246 static void write_expression(const expression_t *expression)
248 const const_expression_t *constant;
250 switch(expression->kind) {
252 constant = &expression->conste;
253 if (is_type_integer(expression->base.type)) {
254 fprintf(out, "%lld", constant->v.int_value);
256 fprintf(out, "%Lf", constant->v.float_value);
260 write_unary_expression((const unary_expression_t*) expression);
263 panic("not implemented expression");
267 static void write_enum(const symbol_t *symbol, const enum_type_t *type)
269 fprintf(out, "enum %s:\n", symbol->string);
271 declaration_t *entry = type->declaration->next;
272 for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
273 entry = entry->next) {
274 fprintf(out, "\t%s", entry->symbol->string);
275 if (entry->init.initializer != NULL) {
276 fprintf(out, " <- ");
277 write_expression(entry->init.enum_value);
281 fprintf(out, "typealias %s <- int\n", symbol->string);
285 static void write_variable(const declaration_t *declaration)
287 fprintf(out, "var %s : ", declaration->symbol->string);
288 write_type(declaration->type);
289 /* TODO: initializers */
294 static void write_function(const declaration_t *declaration)
296 if (declaration->init.statement != NULL) {
297 fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
298 declaration->symbol->string);
301 fprintf(out, "external %s: ", declaration->symbol->string);
303 const function_type_t *function_type
304 = (const function_type_t*) declaration->type;
306 declaration_t *parameter = declaration->scope.declarations;
307 for( ; parameter != NULL; parameter = parameter->next) {
308 write_type(parameter->type);
311 if (function_type->variadic) {
312 fprintf(stderr, "WARNING: Variadic function not supported yet\n");
314 if (function_type->unspecified_parameters) {
315 fprintf(stderr, "WARNING: unspecified params not supported\n");
317 const type_t *return_type = function_type->return_type;
318 write_type(return_type);
321 fputs(declaration->symbol->string, out);
327 void write_caml_decls(FILE *output, const translation_unit_t *unit)
330 global_scope = &unit->scope;
333 fprintf(out, "(* WARNING: Automatically generated file - chaning is useless *)\n");
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)) {
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);
353 /* write global variables */
354 declaration = unit->scope.declarations;
355 for( ; declaration != NULL; declaration = declaration->next) {
356 if (declaration->namespc != NAMESPACE_NORMAL)
358 if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
359 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
362 type_t *type = declaration->type;
363 if (type->kind == TYPE_FUNCTION)
366 write_variable(declaration);
370 /* write functions */
371 declaration_t *declaration = unit->scope.declarations;
372 for( ; declaration != NULL; declaration = declaration->next) {
373 if (declaration->namespc != NAMESPACE_NORMAL)
375 if (declaration->storage_class == STORAGE_CLASS_TYPEDEF
376 || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
379 type_t *type = declaration->type;
380 if (type->kind != TYPE_FUNCTION)
383 write_function(declaration);