- parsing of __based implemented (more semantic in assignment might be needed)
[cparser] / write_fluffy.c
index 1d6aeff..63dbe9a 100644 (file)
@@ -1,43 +1,66 @@
+/*
+ * This file is part of cparser.
+ * Copyright (C) 2007-2008 Matthias Braun <matze@braunis.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
 #include <config.h>
 
 #include <errno.h>
 #include <string.h>
 
+#include "write_fluffy.h"
+#include "symbol_t.h"
 #include "ast_t.h"
 #include "type_t.h"
+#include "entity_t.h"
+#include "type.h"
 #include "adt/error.h"
 
-static const context_t *global_context;
-static FILE            *out;
+static const scope_t *global_scope;
+static FILE          *out;
 
 static void write_type(const type_t *type);
 
-static const char *get_atomic_type_string(const atomic_type_type_t type)
+static const char *get_atomic_type_string(const atomic_type_kind_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_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");
+       case ATOMIC_TYPE_BOOL:        return "bool";
+       default:                      panic("unsupported atomic type");
        }
 }
 
 static void write_atomic_type(const atomic_type_t *type)
 {
-       fprintf(out, "%s", get_atomic_type_string(type->atype));
+       fprintf(out, "%s", get_atomic_type_string(type->akind));
 }
 
 static void write_pointer_type(const pointer_type_t *type)
@@ -46,35 +69,33 @@ static void write_pointer_type(const pointer_type_t *type)
        fputc('*', out);
 }
 
-static declaration_t *find_typedef(const type_t *type)
+static entity_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;
+       entity_t *entity = global_scope->entities;
+       for ( ; entity != NULL; entity = entity->base.next) {
+               if (entity->kind != ENTITY_TYPEDEF)
                        continue;
-               }
-               if(declaration->type == type)
+               if (entity->typedefe.type == type)
                        break;
-               declaration = declaration->next;
        }
 
-       return declaration;
+       return entity;
 }
 
 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);
+       entity_t *entity = find_typedef((const type_t*) type);
+       if(entity != NULL) {
+               fprintf(out, "%s", entity->base.symbol->string);
                return;
        }
 
        /* does the struct have a name? */
-       if(type->symbol != NULL) {
+       symbol_t *symbol = type->compound->base.symbol;
+       if(symbol != NULL) {
                /* TODO: make sure we create a struct for it... */
-               fprintf(out, "%s", type->symbol->string);
+               fprintf(out, "%s", symbol->string);
                return;
        }
        /* TODO: create a struct and use its name here... */
@@ -83,28 +104,29 @@ static void write_compound_type(const compound_type_t *type)
 
 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);
+       entity_t *entity = find_typedef((const type_t*) type);
+       if (entity != NULL) {
+               fprintf(out, "%s", entity->base.symbol->string);
                return;
        }
 
        /* does the enum have a name? */
-       if(type->symbol != NULL) {
+       symbol_t *symbol = type->enume->base.symbol;
+       if (symbol != NULL) {
                /* TODO: make sure we create an enum for it... */
-               fprintf(out, "%s", type->symbol->string);
+               fprintf(out, "%s", symbol->string);
                return;
        }
        /* TODO: create a struct and use its name here... */
        fprintf(out, "/* TODO anonymous enum */byte");
 }
 
-static void write_method_type(const method_type_t *type)
+static void write_function_type(const function_type_t *type)
 {
        fprintf(out, "(func(");
 
-       method_parameter_t *parameter = type->parameters;
-       int                 first     = 1;
+       function_parameter_t *parameter = type->parameters;
+       int                   first     = 1;
        while(parameter != NULL) {
                if(!first) {
                        fprintf(out, ", ");
@@ -127,66 +149,56 @@ static void write_method_type(const method_type_t *type)
        }
 
        fprintf(out, ") : ");
-       write_type(type->result_type);
+       write_type(type->return_type);
        fprintf(out, ")");
 }
 
 static void write_type(const type_t *type)
 {
-       switch(type->type) {
+       switch(type->kind) {
        case TYPE_ATOMIC:
-               write_atomic_type((const atomic_type_t*) type);
+               write_atomic_type(&type->atomic);
                return;
        case TYPE_POINTER:
-               write_pointer_type((const pointer_type_t*) type);
+               write_pointer_type(&type->pointer);
                return;
        case TYPE_COMPOUND_UNION:
        case TYPE_COMPOUND_STRUCT:
-               write_compound_type((const compound_type_t*) type);
+               write_compound_type(&type->compound);
                return;
        case TYPE_ENUM:
-               write_enum_type((const enum_type_t*) type);
+               write_enum_type(&type->enumt);
                return;
-       case TYPE_METHOD:
-               write_method_type((const method_type_t*) type);
+       case TYPE_FUNCTION:
+               write_function_type(&type->function);
                return;
        case TYPE_INVALID:
                panic("invalid type found");
                break;
+       case TYPE_COMPLEX:
+       case TYPE_IMAGINARY:
        default:
                fprintf(out, "/* TODO type */");
                break;
        }
 }
 
-static void write_struct_entry(const declaration_t *declaration)
-{
-       fprintf(out, "\t%s : ", declaration->symbol->string);
-       write_type(declaration->type);
-       fprintf(out, "\n");
-}
-
-static void write_struct(const symbol_t *symbol, const compound_type_t *type)
+static void write_compound_entry(const entity_t *entity)
 {
-       fprintf(out, "struct %s:\n", symbol->string);
-
-       const declaration_t *declaration = type->context.declarations;
-       while(declaration != NULL) {
-               write_struct_entry(declaration);
-               declaration = declaration->next;
-       }
-
+       fprintf(out, "\t%s : ", entity->base.symbol->string);
+       write_type(entity->declaration.type);
        fprintf(out, "\n");
 }
 
-static void write_union(const symbol_t *symbol, const compound_type_t *type)
+static void write_compound(const symbol_t *symbol, const compound_type_t *type)
 {
-       fprintf(out, "union %s:\n", symbol->string);
+       fprintf(out, "%s %s:\n",
+               type->base.kind == TYPE_COMPOUND_STRUCT ? "struct" : "union",
+                       symbol->string);
 
-       const declaration_t *declaration = type->context.declarations;
-       while(declaration != NULL) {
-               write_struct_entry(declaration);
-               declaration = declaration->next;
+       const entity_t *entity = type->compound->members.entities;
+       for ( ; entity != NULL; entity = entity->base.next) {
+               write_compound_entry(entity);
        }
 
        fprintf(out, "\n");
@@ -196,11 +208,11 @@ static void write_expression(const expression_t *expression);
 
 static void write_unary_expression(const unary_expression_t *expression)
 {
-       switch(expression->type) {
-       case UNEXPR_NEGATE:
+       switch(expression->base.kind) {
+       case EXPR_UNARY_NEGATE:
                fputc('-', out);
                break;
-       case UNEXPR_NOT:
+       case EXPR_UNARY_NOT:
                fputc('!', out);
                break;
        default:
@@ -211,14 +223,18 @@ static void write_unary_expression(const unary_expression_t *expression)
 
 static void write_expression(const expression_t *expression)
 {
-       const const_t *constant;
+       const const_expression_t *constant;
        /* TODO */
-       switch(expression->type) {
+       switch(expression->kind) {
        case EXPR_CONST:
-               constant = (const const_t*) expression;
-               fprintf(out, "%d", constant->value);
+               constant = &expression->conste;
+               if(is_type_integer(expression->base.type)) {
+                       fprintf(out, "%lld", constant->v.int_value);
+               } else {
+                       fprintf(out, "%Lf", constant->v.float_value);
+               }
                break;
-       case EXPR_UNARY:
+       EXPR_UNARY_CASES
                write_unary_expression((const unary_expression_t*) expression);
                break;
        default:
@@ -230,12 +246,13 @@ static void write_enum(const symbol_t *symbol, const enum_type_t *type)
 {
        fprintf(out, "enum %s:\n", symbol->string);
 
-       const enum_entry_t *entry = type->entries;
-       for ( ; entry != NULL; entry = entry->next) {
-               fprintf(out, "\t%s", entry->symbol->string);
-               if(entry->value != NULL) {
+       entity_t *entry = type->enume->base.next;
+       for ( ; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
+                       entry = entry->base.next) {
+               fprintf(out, "\t%s", entry->base.symbol->string);
+               if(entry->enum_value.value != NULL) {
                        fprintf(out, " <- ");
-                       write_expression(entry->value);
+                       write_expression(entry->enum_value.value);
                }
                fputc('\n', out);
        }
@@ -243,42 +260,42 @@ static void write_enum(const symbol_t *symbol, const enum_type_t *type)
        fprintf(out, "\n");
 }
 
-static void write_variable(const declaration_t *declaration)
+static void write_variable(const entity_t *entity)
 {
-       fprintf(out, "var %s : ", declaration->symbol->string);
-       write_type(declaration->type);
-       /* TODO: initializers */
+       fprintf(out, "var %s : ", entity->base.symbol->string);
+       write_type(entity->declaration.type);
        fprintf(out, "\n");
 }
 
-static void write_function(const declaration_t *declaration)
+static void write_function(const entity_t *entity)
 {
-       if(declaration->statement != NULL) {
+       if (entity->function.statement != NULL) {
                fprintf(stderr, "Warning: can't convert function bodies (at %s)\n",
-                       declaration->symbol->string);
+                       entity->base.symbol->string);
        }
 
-       fprintf(out, "func extern %s(",
-               declaration->symbol->string);
+       fprintf(out, "func extern %s(", entity->base.symbol->string);
 
-       const method_type_t *method_type = (const method_type_t*) declaration->type;
+       const function_type_t *function_type
+               = (const function_type_t*) entity->declaration.type;
 
-       declaration_t *parameter = declaration->context.declarations;
-       int            first     = 1;
-       for( ; parameter != NULL; parameter = parameter->next) {
+       entity_t *parameter = entity->function.parameters.entities;
+       int       first     = 1;
+       for( ; parameter != NULL; parameter = parameter->base.next) {
+               assert(parameter->kind == ENTITY_VARIABLE);
                if(!first) {
                        fprintf(out, ", ");
                } else {
                        first = 0;
                }
-               if(parameter->symbol != NULL) {
-                       fprintf(out, "%s : ", parameter->symbol->string);
+               if(parameter->base.symbol != NULL) {
+                       fprintf(out, "%s : ", parameter->base.symbol->string);
                } else {
                        fputs("_ : ", out);
                }
-               write_type(parameter->type);
+               write_type(parameter->declaration.type);
        }
-       if(method_type->variadic) {
+       if(function_type->variadic) {
                if(!first) {
                        fprintf(out, ", ");
                } else {
@@ -288,74 +305,53 @@ static void write_function(const declaration_t *declaration)
        }
        fprintf(out, ")");
 
-       const type_t        *result_type = method_type->result_type;
-       if(result_type->type != TYPE_ATOMIC ||
-                       ((const atomic_type_t*) result_type)->atype != ATOMIC_TYPE_VOID) {
+       const type_t *return_type = function_type->return_type;
+       if(!is_type_atomic(return_type, ATOMIC_TYPE_VOID)) {
                fprintf(out, " : ");
-               write_type(result_type);
+               write_type(return_type);
        }
        fputc('\n', out);
 }
 
-void write_fluffy_decls(const translation_unit_t *unit)
+void write_fluffy_decls(FILE *output, const translation_unit_t *unit)
 {
-#if 0
-       out = fopen("out.fluffy", "w");
-       if(out == NULL) {
-               fprintf(stderr, "Couldn't open out.fluffy: %s\n", strerror(errno));
-               exit(1);
-       }
-#endif
-       out            = stdout;
-       global_context = &unit->context;
+       out            = output;
+       global_scope = &unit->scope;
 
+       ast_set_output(out);
+       type_set_output(out);
        fprintf(out, "/* WARNING: Automatically generated file */\n");
 
        /* write structs,unions + enums */
-       declaration_t *declaration = unit->context.declarations;
-       while(declaration != NULL) {
-               //fprintf(out, "// Decl: %s\n", declaration->symbol->string);
-               if(! (declaration->storage_class & STORAGE_CLASS_TYPEDEF)) {
-                       declaration = declaration->next;
+       entity_t *entity = unit->scope.entities;
+       for( ; entity != NULL; entity = entity->base.next) {
+               if (entity->kind != ENTITY_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) {
-                       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;
+               type_t *type = entity->typedefe.type;
+               if(type->kind == TYPE_COMPOUND_STRUCT
+                               || type->kind == TYPE_COMPOUND_UNION) {
+                       write_compound(entity->base.symbol, &type->compound);
+               } else if(type->kind == TYPE_ENUM) {
+                       write_enum(entity->base.symbol, &type->enumt);
+               }
        }
 
        /* write global variables */
-       declaration = unit->context.declarations;
-       for( ; declaration != NULL; declaration = declaration->next) {
-               if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
-                       continue;
-
-               type_t *type = declaration->type;
-               if(type->type == TYPE_METHOD)
+       entity = unit->scope.entities;
+       for( ; entity != NULL; entity = entity->base.next) {
+               if (entity->kind != ENTITY_VARIABLE)
                        continue;
 
-               write_variable(declaration);
+               write_variable(entity);
        }
 
        /* write functions */
-       declaration = unit->context.declarations;
-       for( ; declaration != NULL; declaration = declaration->next) {
-               if(declaration->storage_class & STORAGE_CLASS_TYPEDEF)
+       entity = unit->scope.entities;
+       for( ; entity != NULL; entity = entity->base.next) {
+               if (entity->kind != ENTITY_FUNCTION)
                        continue;
 
-               type_t *type = declaration->type;
-               if(type->type != TYPE_METHOD)
-                       continue;
-
-               write_function(declaration);
+               write_function(entity);
        }
-
-       //fclose(out);
 }