preliminary Win32 support added
[cparser] / write_fluffy.c
index 51b058b..e8ccbd7 100644 (file)
@@ -3,34 +3,37 @@
 #include <errno.h>
 #include <string.h>
 
+#include "write_fluffy.h"
 #include "ast_t.h"
 #include "type_t.h"
+#include "type.h"
 #include "adt/error.h"
 
-static FILE *out;
+static const context_t *global_context;
+static FILE            *out;
 
 static void write_type(const type_t *type);
 
 static const char *get_atomic_type_string(const atomic_type_type_t type)
 {
        switch(type) {
-       case ATOMIC_TYPE_VOID:      return "void";
-       case ATOMIC_TYPE_CHAR:      return "byte";
-       case ATOMIC_TYPE_SCHAR:     return "byte";
-       case ATOMIC_TYPE_UCHAR:     return "unsigned byte";
-       case ATOMIC_TYPE_SHORT:     return "short";
-       case ATOMIC_TYPE_USHORT:    return "unsigned short";
-       case ATOMIC_TYPE_INT:       return "int";
-       case ATOMIC_TYPE_UINT:      return "unsigned int";
-       case ATOMIC_TYPE_LONG:      return "int";
-       case ATOMIC_TYPE_ULONG:     return "unsigned int";
-       case ATOMIC_TYPE_LONGLONG:  return "long";
-       case ATOMIC_TYPE_ULONGLONG: return "unsigned long";
-       case ATOMIC_TYPE_FLOAT:     return "float";
-       case ATOMIC_TYPE_DOUBLE:    return "double";
-       case ATOMIC_TYPE_BOOL:      return "bool";
-       default:
-                                                               panic("unsupported atomic type");
+       case ATOMIC_TYPE_VOID:       return "void";
+       case ATOMIC_TYPE_CHAR:       return "byte";
+       case ATOMIC_TYPE_SCHAR:      return "byte";
+       case ATOMIC_TYPE_UCHAR:      return "unsigned byte";
+       case ATOMIC_TYPE_SHORT:      return "short";
+       case ATOMIC_TYPE_USHORT:     return "unsigned short";
+       case ATOMIC_TYPE_INT:        return "int";
+       case ATOMIC_TYPE_UINT:       return "unsigned int";
+       case ATOMIC_TYPE_LONG:       return "int";
+       case ATOMIC_TYPE_ULONG:      return "unsigned int";
+       case ATOMIC_TYPE_LONGLONG:   return "long";
+       case ATOMIC_TYPE_ULONGLONG:  return "unsigned long";
+       case ATOMIC_TYPE_FLOAT:      return "float";
+       case ATOMIC_TYPE_DOUBLE:     return "double";
+       case ATOMIC_TYPE_LONG_DOUBLE: return "double";
+       case ATOMIC_TYPE_BOOL:       return "bool";
+       default:                     panic("unsupported atomic type");
        }
 }
 
@@ -45,6 +48,93 @@ static void write_pointer_type(const pointer_type_t *type)
        fputc('*', out);
 }
 
+static declaration_t *find_typedef(const type_t *type)
+{
+       /* first: search for a matching typedef in the global type... */
+       declaration_t *declaration = global_context->declarations;
+       while(declaration != NULL) {
+               if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
+                       declaration = declaration->next;
+                       continue;
+               }
+               if(declaration->type == type)
+                       break;
+               declaration = declaration->next;
+       }
+
+       return declaration;
+}
+
+static void write_compound_type(const compound_type_t *type)
+{
+       declaration_t *declaration = find_typedef((const type_t*) type);
+       if(declaration != NULL) {
+               fprintf(out, "%s", declaration->symbol->string);
+               return;
+       }
+
+       /* does the struct have a name? */
+       symbol_t *symbol = type->declaration->symbol;
+       if(symbol != NULL) {
+               /* TODO: make sure we create a struct for it... */
+               fprintf(out, "%s", symbol->string);
+               return;
+       }
+       /* TODO: create a struct and use its name here... */
+       fprintf(out, "/* TODO anonymous struct */byte");
+}
+
+static void write_enum_type(const enum_type_t *type)
+{
+       declaration_t *declaration = find_typedef((const type_t*) type);
+       if(declaration != NULL) {
+               fprintf(out, "%s", declaration->symbol->string);
+               return;
+       }
+
+       /* does the enum have a name? */
+       symbol_t *symbol = type->declaration->symbol;
+       if(symbol != NULL) {
+               /* TODO: make sure we create an enum for it... */
+               fprintf(out, "%s", symbol->string);
+               return;
+       }
+       /* TODO: create a struct and use its name here... */
+       fprintf(out, "/* TODO anonymous enum */byte");
+}
+
+static void write_function_type(const function_type_t *type)
+{
+       fprintf(out, "(func(");
+
+       function_parameter_t *parameter = type->parameters;
+       int                   first     = 1;
+       while(parameter != NULL) {
+               if(!first) {
+                       fprintf(out, ", ");
+               } else {
+                       first = 0;
+               }
+
+#if 0
+               if(parameter->symbol != NULL) {
+                       fprintf(out, "%s : ", parameter->symbol->string);
+               } else {
+                       /* TODO make up some unused names (or allow _ in fluffy?) */
+                       fprintf(out, "_ : ");
+               }
+#endif
+               fputs("_ : ", out);
+               write_type(parameter->type);
+
+               parameter = parameter->next;
+       }
+
+       fprintf(out, ") : ");
+       write_type(type->result_type);
+       fprintf(out, ")");
+}
+
 static void write_type(const type_t *type)
 {
        switch(type->type) {
@@ -54,6 +144,16 @@ static void write_type(const type_t *type)
        case TYPE_POINTER:
                write_pointer_type((const pointer_type_t*) type);
                return;
+       case TYPE_COMPOUND_UNION:
+       case TYPE_COMPOUND_STRUCT:
+               write_compound_type((const compound_type_t*) type);
+               return;
+       case TYPE_ENUM:
+               write_enum_type((const enum_type_t*) type);
+               return;
+       case TYPE_FUNCTION:
+               write_function_type((const function_type_t*) type);
+               return;
        case TYPE_INVALID:
                panic("invalid type found");
                break;
@@ -72,10 +172,22 @@ static void write_struct_entry(const declaration_t *declaration)
 
 static void write_struct(const symbol_t *symbol, const compound_type_t *type)
 {
-       (void) type;
        fprintf(out, "struct %s:\n", symbol->string);
 
-       const declaration_t *declaration = type->context.declarations;
+       const declaration_t *declaration = type->declaration->context.declarations;
+       while(declaration != NULL) {
+               write_struct_entry(declaration);
+               declaration = declaration->next;
+       }
+
+       fprintf(out, "\n");
+}
+
+static void write_union(const symbol_t *symbol, const compound_type_t *type)
+{
+       fprintf(out, "union %s:\n", symbol->string);
+
+       const declaration_t *declaration = type->declaration->context.declarations;
        while(declaration != NULL) {
                write_struct_entry(declaration);
                declaration = declaration->next;
@@ -84,6 +196,71 @@ static void write_struct(const symbol_t *symbol, const compound_type_t *type)
        fprintf(out, "\n");
 }
 
+static void write_expression(const expression_t *expression);
+
+static void write_unary_expression(const unary_expression_t *expression)
+{
+       switch(expression->type) {
+       case UNEXPR_NEGATE:
+               fputc('-', out);
+               break;
+       case UNEXPR_NOT:
+               fputc('!', out);
+               break;
+       default:
+               panic("unimeplemented unary expression found");
+       }
+       write_expression(expression->value);
+}
+
+static void write_expression(const expression_t *expression)
+{
+       const const_t *constant;
+       /* TODO */
+       switch(expression->type) {
+       case EXPR_CONST:
+               constant = (const const_t*) expression;
+               if(is_type_integer(expression->datatype)) {
+                       fprintf(out, "%d", constant->v.int_value);
+               } else {
+                       fprintf(out, "%Lf", constant->v.float_value);
+               }
+               break;
+       case EXPR_UNARY:
+               write_unary_expression((const unary_expression_t*) expression);
+               break;
+       default:
+               panic("not implemented expression");
+       }
+}
+
+static void write_initializer(const initializer_t *initializer)
+{
+       if(initializer->type != INITIALIZER_VALUE) {
+               panic("list initializers not supported yet");
+       }
+
+       write_expression(initializer->v.value);
+}
+
+static void write_enum(const symbol_t *symbol, const enum_type_t *type)
+{
+       fprintf(out, "enum %s:\n", symbol->string);
+
+       declaration_t *entry = type->declaration->next;
+       for ( ; entry != NULL && entry->storage_class == STORAGE_CLASS_ENUM_ENTRY;
+                       entry = entry->next) {
+               fprintf(out, "\t%s", entry->symbol->string);
+               if(entry->init.initializer != NULL) {
+                       fprintf(out, " <- ");
+                       write_initializer(entry->init.initializer);
+               }
+               fputc('\n', out);
+       }
+       fprintf(out, "typealias %s <- int\n", symbol->string);
+       fprintf(out, "\n");
+}
+
 static void write_variable(const declaration_t *declaration)
 {
        fprintf(out, "var %s : ", declaration->symbol->string);
@@ -92,6 +269,53 @@ static void write_variable(const declaration_t *declaration)
        fprintf(out, "\n");
 }
 
+static void write_function(const declaration_t *declaration)
+{
+       if(declaration->init.statement != NULL) {
+               fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
+                       declaration->symbol->string);
+       }
+
+       fprintf(out, "func extern %s(",
+               declaration->symbol->string);
+
+       const function_type_t *function_type
+               = (const function_type_t*) declaration->type;
+
+       declaration_t *parameter = declaration->context.declarations;
+       int            first     = 1;
+       for( ; parameter != NULL; parameter = parameter->next) {
+               if(!first) {
+                       fprintf(out, ", ");
+               } else {
+                       first = 0;
+               }
+               if(parameter->symbol != NULL) {
+                       fprintf(out, "%s : ", parameter->symbol->string);
+               } else {
+                       fputs("_ : ", out);
+               }
+               write_type(parameter->type);
+       }
+       if(function_type->variadic) {
+               if(!first) {
+                       fprintf(out, ", ");
+               } else {
+                       first = 0;
+               }
+               fputs("...", out);
+       }
+       fprintf(out, ")");
+
+       const type_t *result_type = function_type->result_type;
+       if(result_type->type != TYPE_ATOMIC ||
+                       ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
+               fprintf(out, " : ");
+               write_type(result_type);
+       }
+       fputc('\n', out);
+}
+
 void write_fluffy_decls(const translation_unit_t *unit)
 {
 #if 0
@@ -101,41 +325,54 @@ void write_fluffy_decls(const translation_unit_t *unit)
                exit(1);
        }
 #endif
-       out = stdout;
+       out            = stdout;
+       global_context = &unit->context;
 
        fprintf(out, "/* WARNING: Automatically generated file */\n");
 
-       /* write structs + enums */
+       /* write structs,unions + enums */
        declaration_t *declaration = unit->context.declarations;
-       while(declaration != NULL) {
+       for( ; declaration != NULL; declaration = declaration->next) {
                //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
-               if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
-                       declaration = declaration->next;
+               if(! (declaration->storage_class == STORAGE_CLASS_TYPEDEF)) {
                        continue;
                }
                type_t *type = declaration->type;
                if(type->type == TYPE_COMPOUND_STRUCT) {
                        write_struct(declaration->symbol, (compound_type_t*) type);
                } else if(type->type == TYPE_COMPOUND_UNION) {
-                       /* TODO */
+                       write_union(declaration->symbol, (compound_type_t*) type);
+               } else if(type->type == TYPE_ENUM) {
+                       write_enum(declaration->symbol, (enum_type_t*) type);
                }
-
-               declaration = declaration->next;
        }
 
        /* write global variables */
        declaration = unit->context.declarations;
-       while(declaration != NULL) {
-               if(declaration->storage_class & STORAGE_CLASS_TYPEDEF) {
-                       declaration = declaration->next;
+       for( ; declaration != NULL; declaration = declaration->next) {
+               if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+                               || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
                        continue;
-               }
 
                type_t *type = declaration->type;
-               if(type->type != TYPE_METHOD) {
-                       write_variable(declaration);
-               }
-               declaration = declaration->next;
+               if(type->type == TYPE_FUNCTION)
+                       continue;
+
+               write_variable(declaration);
+       }
+
+       /* write functions */
+       declaration = unit->context.declarations;
+       for( ; declaration != NULL; declaration = declaration->next) {
+               if(declaration->storage_class == STORAGE_CLASS_TYPEDEF
+                               || declaration->storage_class == STORAGE_CLASS_ENUM_ENTRY)
+                       continue;
+
+               type_t *type = declaration->type;
+               if(type->type != TYPE_FUNCTION)
+                       continue;
+
+               write_function(declaration);
        }
 
        //fclose(out);