save cname in class, save location of statements and expressions add
authorJürg Billeter <j@bitron.ch>
Tue, 25 Apr 2006 21:17:43 +0000 (21:17 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Tue, 25 Apr 2006 21:17:43 +0000 (21:17 +0000)
2006-04-25  Jürg Billeter  <j@bitron.ch>

* valac/parser.y: save cname in class, save location of statements and
  expressions
* valac/context.h: add ValaStruct struct
* valac/context.c: support symbols from methods and structs, add int
  and string fundamental types, resolve types in local variable
  declarations
* valac/generator.h: save pointer to current method block
* valac/generator.c: add special handling for main method, basic support
  for method invocations, literals, member access, simple names,
  additive expressions, return statments, blocks
* tests/test-005.vala: test static method invocation, literal integer,
  simple name, additive expression, return statement, block, main method

svn path=/trunk/; revision=5

vala/ChangeLog
vala/tests/test-005.vala [new file with mode: 0644]
vala/valac/context.c
vala/valac/context.h
vala/valac/generator.c
vala/valac/generator.h
vala/valac/parser.y

index ee8e8ff..dd70e70 100644 (file)
@@ -1,3 +1,18 @@
+2006-04-25  Jürg Billeter  <j@bitron.ch>
+
+       * valac/parser.y: save cname in class, save location of statements and
+         expressions
+       * valac/context.h: add ValaStruct struct
+       * valac/context.c: support symbols from methods and structs, add int
+         and string fundamental types, resolve types in local variable
+         declarations
+       * valac/generator.h: save pointer to current method block
+       * valac/generator.c: add special handling for main method, basic support
+         for method invocations, literals, member access, simple names,
+         additive expressions, return statments, blocks
+       * tests/test-005.vala: test static method invocation, literal integer,
+         simple name, additive expression, return statement, block, main method
+
 2006-04-24  Jürg Billeter  <j@bitron.ch>
 
        * valac/scanner.l: support single-line comments, ASSIGN, PLUS, RETURN,
diff --git a/vala/tests/test-005.vala b/vala/tests/test-005.vala
new file mode 100644 (file)
index 0000000..ab2ef53
--- /dev/null
@@ -0,0 +1,14 @@
+namespace Maman {
+       class Bar {
+               public static int do_action (int i) {
+                       return (i + 42);
+               }
+       }
+       
+       class SubBar : Bar {
+               public static int main (int argc, string[] argv) {
+                       int i = do_action (42);
+                       return (argc + i);
+               }
+       }
+}
index c39a28b..983c03f 100644 (file)
@@ -49,7 +49,7 @@ vala_context_parse (ValaContext *context)
        }
 }
 
-static ValaSymbol *
+ValaSymbol *
 vala_symbol_new (ValaSymbolType type)
 {
        ValaSymbol *symbol;
@@ -59,7 +59,7 @@ vala_symbol_new (ValaSymbolType type)
        return symbol;
 }
 
-static void
+void
 err (ValaLocation *location, const char *format, ...)
 {
        va_list args;
@@ -72,6 +72,67 @@ err (ValaLocation *location, const char *format, ...)
 }
 
 static void
+vala_context_add_symbols_from_method (ValaContext *context, ValaSymbol *class_symbol, ValaMethod *method)
+{
+       ValaSymbol *method_symbol;
+       
+       method_symbol = g_hash_table_lookup (class_symbol->symbol_table, method->name);
+       if (method_symbol != NULL) {
+               err (method->location, "error: class member ´%s.%s.%s´ already defined", class_symbol->class->namespace->name, class_symbol->class->name, method->name);
+       }
+
+       method_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_METHOD);
+       method_symbol->method = method;
+       g_hash_table_insert (class_symbol->symbol_table, method->name, method_symbol);
+       
+       if (method->body != NULL) {
+               method->body->method = method_symbol;
+       }
+}
+
+static void
+vala_context_add_symbols_from_class (ValaContext *context, ValaClass *class)
+{
+       ValaSymbol *ns_symbol, *class_symbol;
+       ns_symbol = class->namespace->symbol;
+       GList *ml;
+
+       class_symbol = g_hash_table_lookup (ns_symbol->symbol_table, class->name);
+       if (class_symbol != NULL) {
+               err (class->location, "error: class ´%s.%s´ already defined", class->namespace->name, class->name);
+       }
+
+       class_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_CLASS);
+       class_symbol->class = class;
+       g_hash_table_insert (ns_symbol->symbol_table, class->name, class_symbol);
+       
+       class->symbol = class_symbol;
+       
+       for (ml = class->methods; ml != NULL; ml = ml->next) {
+               vala_context_add_symbols_from_method (context, class_symbol, ml->data);
+       }
+}
+
+static void
+vala_context_add_symbols_from_struct (ValaContext *context, ValaStruct *struct_)
+{
+       ValaSymbol *ns_symbol, *struct_symbol;
+       ns_symbol = struct_->namespace->symbol;
+       GList *ml;
+
+       struct_symbol = g_hash_table_lookup (ns_symbol->symbol_table, struct_->name);
+       if (struct_symbol != NULL) {
+               err (struct_->location, "error: struct ´%s.%s´ already defined", struct_->namespace->name, struct_->name);
+       }
+
+       struct_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_STRUCT);
+       struct_symbol->struct_ = struct_;
+       g_hash_table_insert (ns_symbol->symbol_table, struct_->name, struct_symbol);
+       
+       struct_->symbol = struct_symbol;
+}
+
+static void
 vala_context_add_symbols_from_namespace (ValaContext *context, ValaNamespace *namespace)
 {
        ValaSymbol *ns_symbol, *class_symbol;
@@ -90,16 +151,11 @@ vala_context_add_symbols_from_namespace (ValaContext *context, ValaNamespace *na
        namespace->symbol = ns_symbol;
        
        for (cl = namespace->classes; cl != NULL; cl = cl->next) {
-               ValaClass *class = cl->data;
-               
-               class_symbol = g_hash_table_lookup (ns_symbol->symbol_table, class->name);
-               if (class_symbol != NULL) {
-                       err (class->location, "error: class ´%s.%s´ already defined", namespace->name, class->name);
-               }
-
-               class_symbol = vala_symbol_new (VALA_SYMBOL_TYPE_CLASS);
-               class_symbol->class = class;
-               g_hash_table_insert (ns_symbol->symbol_table, class->name, class_symbol);
+               vala_context_add_symbols_from_class (context, cl->data);
+       }
+       
+       for (cl = namespace->structs; cl != NULL; cl = cl->next) {
+               vala_context_add_symbols_from_struct (context, cl->data);
        }
 }
 
@@ -109,13 +165,36 @@ vala_context_add_fundamental_symbols (ValaContext *context)
        ValaSymbol *symbol;
        ValaNamespace *namespace;
        ValaClass *class;
+       ValaStruct *struct_;
        
        context->root = vala_symbol_new (VALA_SYMBOL_TYPE_ROOT);
+
+       namespace = g_new0 (ValaNamespace, 1);
+       namespace->name = g_strdup ("");
+       namespace->lower_case_cname = g_strdup ("");
+       namespace->upper_case_cname = g_strdup ("");
        
        /* void */
        symbol = vala_symbol_new (VALA_SYMBOL_TYPE_VOID);
        g_hash_table_insert (context->root->symbol_table, "void", symbol);
 
+       /* int */
+       struct_ = g_new0 (ValaStruct, 1);
+       struct_->name = g_strdup ("int");
+       struct_->namespace = namespace;
+       struct_->cname = g_strdup ("int");
+       namespace->structs = g_list_append (namespace->structs, struct_);
+
+       /* string */
+       struct_ = g_new0 (ValaStruct, 1);
+       struct_->name = g_strdup ("string");
+       struct_->reference_type = TRUE;
+       struct_->namespace = namespace;
+       struct_->cname = g_strdup ("char");
+       namespace->structs = g_list_append (namespace->structs, struct_);
+
+       vala_context_add_symbols_from_namespace (context, namespace);
+
        /* namespace G */       
        namespace = g_new0 (ValaNamespace, 1);
        namespace->name = g_strdup ("G");
@@ -185,7 +264,7 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp
                        err (type_reference->location, "error: specified namespace '%s' not found", type_reference->namespace_name);
                }
 
-               type_symbol = g_hash_table_lookup (namespace->symbol->symbol_table, type_reference->type_name);
+               type_symbol = g_hash_table_lookup (ns_symbol->symbol_table, type_reference->type_name);
                if (type_symbol == NULL) {
                        /* specified namespace not found */
                        err (type_reference->location, "error: specified type ´%s´ not found in namespace ´%s´", type_reference->type_name, type_reference->namespace_name);
@@ -193,7 +272,8 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp
        }
        
        if (type_symbol->type == VALA_SYMBOL_TYPE_VOID ||
-           type_symbol->type == VALA_SYMBOL_TYPE_CLASS) {
+           type_symbol->type == VALA_SYMBOL_TYPE_CLASS ||
+           type_symbol->type == VALA_SYMBOL_TYPE_STRUCT) {
                type_reference->symbol = type_symbol;
        } else {
                err (type_reference->location, "error: specified symbol ´%s´ is not a type", type_reference->type_name);
@@ -201,6 +281,26 @@ vala_context_resolve_type_reference (ValaContext *context, ValaNamespace *namesp
 }
 
 static void
+vala_context_resolve_types_in_statement (ValaContext *context, ValaNamespace *namespace, ValaStatement *stmt)
+{
+       switch (stmt->type) {
+       case VALA_STATEMENT_TYPE_VARIABLE_DECLARATION:
+               vala_context_resolve_type_reference (context, namespace, stmt->variable_declaration->type);
+               break;
+       }
+}
+
+static void
+vala_context_resolve_types_in_block (ValaContext *context, ValaNamespace *namespace, ValaStatement *stmt)
+{
+       GList *l;
+       
+       for (l = stmt->block.statements; l != NULL; l = l ->next) {
+               vala_context_resolve_types_in_statement (context, namespace, l->data);
+       }
+}
+
+static void
 vala_context_resolve_types_in_method (ValaContext *context, ValaMethod *method)
 {
        GList *l;
@@ -215,6 +315,10 @@ vala_context_resolve_types_in_method (ValaContext *context, ValaMethod *method)
                        err (formal_parameter->location, "error: method parameters cannot be of type `void`");
                }
        }
+       
+       if (method->body != NULL) {
+               vala_context_resolve_types_in_block (context, method->class->namespace, method->body);
+       }
 }
 
 static void
index d81a493..f3866c1 100644 (file)
@@ -34,6 +34,7 @@ typedef struct _ValaSourceFile ValaSourceFile;
 typedef struct _ValaLocation ValaLocation;
 typedef struct _ValaNamespace ValaNamespace;
 typedef struct _ValaClass ValaClass;
+typedef struct _ValaStruct ValaStruct;
 typedef struct _ValaMethod ValaMethod;
 typedef struct _ValaStatement ValaStatement;
 typedef struct _ValaVariableDeclaration ValaVariableDeclaration;
@@ -47,6 +48,10 @@ enum _ValaSymbolType {
        VALA_SYMBOL_TYPE_NAMESPACE,
        VALA_SYMBOL_TYPE_VOID,
        VALA_SYMBOL_TYPE_CLASS,
+       VALA_SYMBOL_TYPE_STRUCT,
+       VALA_SYMBOL_TYPE_METHOD,
+       VALA_SYMBOL_TYPE_BLOCK,
+       VALA_SYMBOL_TYPE_LOCAL_VARIABLE,
 };
 
 enum _ValaMethodFlags {
@@ -87,6 +92,10 @@ struct _ValaSymbol {
        ValaSymbolType type;
        union {
                ValaClass *class;
+               ValaStruct *struct_;
+               ValaMethod *method;
+               ValaStatement *stmt;
+               ValaTypeReference *typeref;
        };
        GHashTable *symbol_table;
 };
@@ -107,6 +116,7 @@ struct _ValaNamespace {
        char *name;
        ValaSymbol *symbol;
        GList *classes;
+       GList *structs;
        char *lower_case_cname;
        char *upper_case_cname;
 };
@@ -114,21 +124,34 @@ struct _ValaNamespace {
 struct _ValaClass {
        char *name;
        ValaLocation *location;
+       ValaSymbol *symbol;
        ValaNamespace *namespace;
        ValaClass *base_class;
        GList *base_types;
        GList *methods;
+       char *cname;
        char *lower_case_cname;
        char *upper_case_cname;
 };
 
+struct _ValaStruct {
+       char *name;
+       ValaLocation *location;
+       ValaSymbol *symbol;
+       ValaNamespace *namespace;
+       gboolean reference_type;
+       char *cname;
+};
+
 struct _ValaMethod {
        char *name;
        ValaLocation *location;
+       ValaSymbol *symbol;
        ValaClass *class;
        ValaTypeReference *return_type;
        GList *formal_parameters;
        ValaMethodFlags modifiers;
+       char *cname;
        char *cdecl1;
        char *cdecl2;
        ValaStatement *body;
@@ -136,6 +159,10 @@ struct _ValaMethod {
 
 struct _ValaStatement {
        ValaStatementType type;
+       ValaLocation *location;
+       union {
+               ValaSymbol *method;
+       };
        union {
                struct {
                        GList *statements;
@@ -158,6 +185,8 @@ struct _ValaVariableDeclarator {
 
 struct _ValaExpression {
        ValaExpressionType type;
+       ValaLocation *location;
+       ValaSymbol *static_type_symbol;
        union {
                char *str;
                ValaExpression *inner;
@@ -173,6 +202,7 @@ struct _ValaExpression {
                struct {
                        ValaExpression *call;
                        GList *argument_list;
+                       ValaExpression *instance;
                } invocation;
                struct {
                        ValaExpression *left;
@@ -204,3 +234,7 @@ void vala_context_resolve_types (ValaContext *context);
 ValaSourceFile *vala_source_file_new (const char *filename);
 
 void vala_parser_parse (ValaSourceFile *source_file);
+
+ValaSymbol *vala_symbol_new (ValaSymbolType type);
+
+void err (ValaLocation *location, const char *format, ...);
index 4498668..aad37a1 100644 (file)
@@ -20,6 +20,7 @@
  *     Jürg Billeter <j@bitron.ch>
  */
 
+#include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -54,6 +55,22 @@ filename_to_define (const char *filename)
        return define;
 }
 
+static char *
+get_cname_for_type_symbol (ValaSymbol *sym, ValaLocation *location)
+{
+       switch (sym->type) {
+       case VALA_SYMBOL_TYPE_CLASS:
+               return g_strdup_printf ("%s *", sym->class->cname);
+       case VALA_SYMBOL_TYPE_STRUCT:
+               return g_strdup_printf ("%s %s", sym->struct_->cname, (sym->struct_->reference_type ? "*" : ""));
+       case VALA_SYMBOL_TYPE_VOID:
+               return g_strdup ("void");
+       default:
+               err (location, "internal error: symbol type %d is not a type symbol", sym->type);
+               return NULL;
+       }
+}
+
 static void
 vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *class)
 {
@@ -74,18 +91,26 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
        for (l = class->methods; l != NULL; l = l->next) {
                ValaMethod *method = l->data;
                
-               char *method_return_type_cname = g_strdup_printf ("%s%s", method->return_type->namespace_name, method->return_type->type_name);
-               char *method_cname = g_strdup_printf ("%s%s_%s", ns_lower, lower_case, method->name);
+               char *method_return_type_cname = get_cname_for_type_symbol (method->return_type->symbol, method->location);
+               if ((method->modifiers & VALA_METHOD_STATIC) && strcmp (method->name, "main") == 0 && strcmp (method->return_type->type_name, "int") == 0) {
+                       if (g_list_length (method->formal_parameters) == 2) {
+                               method->cname = g_strdup ("main");
+                       }
+               }
+               if (method->cname == NULL) {
+                       method->cname = g_strdup_printf ("%s%s_%s", ns_lower, lower_case, method->name);
+               }
                char *parameters;
                GList *parameter_list = NULL;
                if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
-                       parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s%s *self", namespace->name, class->name));
+                       parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s *self", class->cname));
                }
                
                GList *pl;
                for (pl = method->formal_parameters; pl != NULL; pl = pl->next) {
                        ValaFormalParameter *param = pl->data;
-                       parameter_list = g_list_append (parameter_list, g_strdup_printf ("%s%s *%s", param->type->symbol->class->namespace->name, param->type->symbol->class->name, param->name));
+                       char *param_string = g_strdup_printf ("%s%s", get_cname_for_type_symbol (param->type->symbol, param->location), param->name);
+                       parameter_list = g_list_append (parameter_list, param_string);
                }
                
                if (parameter_list == NULL) {
@@ -100,7 +125,7 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
                        g_list_free (parameter_list);
                }
                
-               method->cdecl2 = g_strdup_printf ("%s (%s)", method_cname, parameters);
+               method->cdecl2 = g_strdup_printf ("%s (%s)", method->cname, parameters);
 
                if (method->modifiers & VALA_METHOD_PUBLIC) {
                        method->cdecl1 = g_strdup (method_return_type_cname);
@@ -113,6 +138,284 @@ vala_code_generator_process_methods1 (ValaCodeGenerator *generator, ValaClass *c
        fprintf (generator->c_file, "\n");
 }
 
+static void vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpression *expr);
+
+static void
+vala_code_generator_process_additive_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       vala_code_generator_process_expression (generator, expr->additive.left);
+       fprintf (generator->c_file, " + ");
+       vala_code_generator_process_expression (generator, expr->additive.right);
+}
+
+static void
+vala_code_generator_process_assignment (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       vala_code_generator_process_expression (generator, expr->assignment.left);
+       fprintf (generator->c_file, " = ");
+       vala_code_generator_process_expression (generator, expr->assignment.right);
+}
+
+static void
+vala_code_generator_process_invocation (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       GList *l;
+       ValaMethod *method = NULL;
+       gboolean first = TRUE;
+       
+       vala_code_generator_process_expression (generator, expr->invocation.call);
+       method = expr->invocation.call->static_type_symbol->method;
+       switch (expr->invocation.call->type) {
+       case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+               expr->invocation.instance = expr->invocation.call->member_access.left;
+               break;
+       }
+       fprintf (generator->c_file, " (");
+       if ((method->modifiers & VALA_METHOD_STATIC) == 0) {
+               if (expr->invocation.instance != NULL) {
+                       vala_code_generator_process_expression (generator, expr->invocation.instance);
+               } else {
+                       fprintf (generator->c_file, "self");
+               }
+               first = FALSE;
+       }
+       for (l = expr->invocation.argument_list; l != NULL; l = l->next) {
+               if (!first) {
+                       fprintf (generator->c_file, ", ");
+               } else {
+                       first = FALSE;
+               }
+               vala_code_generator_process_expression (generator, l->data);
+       }
+       fprintf (generator->c_file, ")");
+}
+
+static void
+vala_code_generator_process_literal (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       fprintf (generator->c_file, "%s", expr->str);
+}
+
+static ValaSymbol *
+get_inherited_member (ValaSymbol *type, const char *name, ValaLocation *location, gboolean break_on_failure)
+{
+       ValaSymbol *sym;
+       sym = g_hash_table_lookup (type->symbol_table, name);
+       if (sym != NULL) {
+               return sym;
+       }
+       
+       if (type->class->base_class == NULL) {
+               if (break_on_failure) {
+                       err (location, "error: type member ´%s´ not found", name);
+               }
+               
+               return NULL;
+       }
+       
+       return get_inherited_member (type->class->base_class->symbol, name, location, break_on_failure);
+}
+
+static void
+vala_code_generator_find_static_type_of_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       ValaSymbol *sym = NULL, *sym2 = NULL;
+       
+       if (expr->static_type_symbol != NULL)
+               return;
+               
+       switch (expr->type) {
+       case VALA_EXPRESSION_TYPE_ADDITIVE:
+               break;
+       case VALA_EXPRESSION_TYPE_ASSIGNMENT:
+               break;
+       case VALA_EXPRESSION_TYPE_INVOCATION:
+               vala_code_generator_find_static_type_of_expression (generator, expr->invocation.call);
+               expr->static_type_symbol = expr->invocation.call->static_type_symbol->method->return_type->symbol;
+               break;
+       case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+               vala_code_generator_find_static_type_of_expression (generator, expr->member_access.left);
+               sym = expr->member_access.left->static_type_symbol;
+               if (sym != NULL && sym->type == VALA_SYMBOL_TYPE_CLASS) {
+                       expr->static_type_symbol = get_inherited_member (sym, expr->member_access.right, expr->member_access.left->location, TRUE);
+               } else if (sym != NULL && sym->type == VALA_SYMBOL_TYPE_LOCAL_VARIABLE) {
+               } else {
+                       err (expr->member_access.left->location, "error: specified expression type %d can't be used for member access", sym->type);
+               }
+               break;
+       case VALA_EXPRESSION_TYPE_PARENTHESIZED:
+               vala_code_generator_find_static_type_of_expression (generator, expr->inner);
+               expr->static_type_symbol = expr->inner->static_type_symbol;
+               break;
+       case VALA_EXPRESSION_TYPE_LITERAL_INTEGER:
+       case VALA_EXPRESSION_TYPE_LITERAL_STRING:
+               break;
+       case VALA_EXPRESSION_TYPE_SIMPLE_NAME:
+               if (strcmp (expr->str, "this") == 0) {
+                       expr->static_type_symbol = generator->sym->stmt->method->method->class->symbol;
+               }
+       
+               if (expr->static_type_symbol == NULL) {
+                       /* local variable */
+                       sym = g_hash_table_lookup (generator->sym->symbol_table, expr->str);
+                       if (sym != NULL) {
+                               expr->static_type_symbol = sym->typeref->symbol;
+                       }
+               }
+               
+               if (expr->static_type_symbol == NULL) {
+                       /* member of this */
+                       expr->static_type_symbol = get_inherited_member (generator->sym->stmt->method->method->class->symbol, expr->str, expr->location, FALSE);
+               }
+
+               if (expr->static_type_symbol == NULL) {
+                       /* member of this */
+                       expr->static_type_symbol = g_hash_table_lookup (generator->context->root->symbol_table, expr->str);
+               }
+
+               if (expr->static_type_symbol == NULL) {
+                       err (expr->location, "error: symbol ´%s´ not found", expr->str);
+               }
+               break;
+       }
+}
+
+static void
+vala_code_generator_process_member_access (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       ValaSymbol *sym = expr->static_type_symbol;
+       if (sym->type == VALA_SYMBOL_TYPE_METHOD) {
+               ValaMethod *method = sym->method;
+               fprintf (generator->c_file, "%s", method->cname);
+       } else {
+               vala_code_generator_process_expression (generator, expr->member_access.left);
+               fprintf (generator->c_file, "->%s", expr->member_access.right);
+       }
+}
+
+static void
+vala_code_generator_process_parenthesized_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       fprintf (generator->c_file, "(");
+       vala_code_generator_process_expression (generator, expr->inner);
+       fprintf (generator->c_file, ")");
+}
+
+static void
+vala_code_generator_process_simple_name (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       switch (expr->static_type_symbol->type) {
+       case VALA_SYMBOL_TYPE_METHOD:
+               fprintf (generator->c_file, "%s", expr->static_type_symbol->method->cname);
+               break;
+       default:
+               fprintf (generator->c_file, "%s", expr->str);
+               break;
+       }
+}
+
+static void
+vala_code_generator_process_expression (ValaCodeGenerator *generator, ValaExpression *expr)
+{
+       vala_code_generator_find_static_type_of_expression (generator, expr);
+
+       switch (expr->type) {
+       case VALA_EXPRESSION_TYPE_ADDITIVE:
+               vala_code_generator_process_additive_expression (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_ASSIGNMENT:
+               vala_code_generator_process_assignment (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_INVOCATION:
+               vala_code_generator_process_invocation (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_MEMBER_ACCESS:
+               vala_code_generator_process_member_access (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_PARENTHESIZED:
+               vala_code_generator_process_parenthesized_expression (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_LITERAL_INTEGER:
+       case VALA_EXPRESSION_TYPE_LITERAL_STRING:
+               vala_code_generator_process_literal (generator, expr);
+               break;
+       case VALA_EXPRESSION_TYPE_SIMPLE_NAME:
+               vala_code_generator_process_simple_name (generator, expr);
+               break;
+       }
+}
+
+static void
+vala_code_generator_process_variable_declaration (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       ValaSymbol *sym = stmt->variable_declaration->type->symbol;
+
+       char *decl_string = get_cname_for_type_symbol (sym, stmt->location);
+
+       fprintf (generator->c_file, "\t%s%s", decl_string, stmt->variable_declaration->declarator->name);
+       
+       ValaExpression *expr = stmt->variable_declaration->declarator->initializer;
+       if (expr != NULL) {
+               fprintf (generator->c_file, " = ");
+               vala_code_generator_process_expression (generator, expr);
+       }
+
+       fprintf (generator->c_file, ";\n");
+
+       sym = vala_symbol_new (VALA_SYMBOL_TYPE_LOCAL_VARIABLE);
+       g_hash_table_insert (generator->sym->symbol_table, stmt->variable_declaration->declarator->name, sym);
+       sym->typeref = stmt->variable_declaration->type;
+}
+
+static void vala_code_generator_process_statement (ValaCodeGenerator *generator, ValaStatement *stmt);
+
+static void
+vala_code_generator_process_block (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       GList *l;
+       
+       fprintf (generator->c_file, "{\n");
+       
+       for (l = stmt->block.statements; l != NULL; l = l->next) {
+               vala_code_generator_process_statement (generator, l->data);
+       }
+       
+       fprintf (generator->c_file, "}\n");
+}
+
+static void
+vala_code_generator_process_return_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       GList *l;
+       
+       fprintf (generator->c_file, "\treturn ");
+       vala_code_generator_process_expression (generator, stmt->expr);
+       fprintf (generator->c_file, ";\n");
+}
+
+static void
+vala_code_generator_process_statement (ValaCodeGenerator *generator, ValaStatement *stmt)
+{
+       switch (stmt->type) {
+       case VALA_STATEMENT_TYPE_BLOCK:
+               vala_code_generator_process_block (generator, stmt);
+               break;
+       case VALA_STATEMENT_TYPE_EXPRESSION:
+               fprintf (generator->c_file, "\t");
+               vala_code_generator_process_expression (generator, stmt->expr);
+               fprintf (generator->c_file, ";\n");
+               break;
+       case VALA_STATEMENT_TYPE_RETURN:
+               vala_code_generator_process_return_statement (generator, stmt);
+               break;
+       case VALA_STATEMENT_TYPE_VARIABLE_DECLARATION:
+               vala_code_generator_process_variable_declaration (generator, stmt);
+               break;
+       default:
+               fprintf (generator->c_file, "\t;\n");
+       }
+}
+
 static void
 vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *class)
 {
@@ -139,8 +442,25 @@ vala_code_generator_process_methods2 (ValaCodeGenerator *generator, ValaClass *c
 
                fprintf (generator->c_file, "%s\n", method->cdecl1);
                fprintf (generator->c_file, "%s\n", method->cdecl2);
-               fprintf (generator->c_file, "{\n");
-               fprintf (generator->c_file, "}\n");
+               
+               if (method->body != NULL) {
+                       generator->sym = vala_symbol_new (VALA_SYMBOL_TYPE_BLOCK);
+                       generator->sym->stmt = method->body;
+
+                       ValaSymbol *sym;
+                       GList *pl;
+
+                       for (pl = method->formal_parameters; pl != NULL; pl = pl->next) {
+                               ValaFormalParameter *param = pl->data;
+                               
+                               sym = vala_symbol_new (VALA_SYMBOL_TYPE_LOCAL_VARIABLE);
+                               g_hash_table_insert (generator->sym->symbol_table, param->name, sym);
+                               sym->typeref = param->type;
+                       }
+
+                       vala_code_generator_process_block (generator, method->body);
+               }
+               
                fprintf (generator->c_file, "\n");
        }
        fprintf (generator->h_file, "\n");
index 1f03aa2..be7cd9f 100644 (file)
@@ -29,6 +29,7 @@ struct _ValaCodeGenerator {
        const char *directory;
        FILE *c_file;
        FILE *h_file;
+       ValaSymbol *sym; /* current block */
 };
 
 ValaCodeGenerator *vala_code_generator_new (ValaContext *context);
index f356d0a..5c28426 100644 (file)
@@ -248,6 +248,7 @@ class_declaration
                current_class->base_types = $3;
                current_class->location = current_location (@2);
                current_class->namespace = current_namespace;
+               current_class->cname = g_strdup_printf ("%s%s", current_namespace->name, current_class->name);
                current_class->lower_case_cname = camel_case_to_lower_case (current_class->name);
                current_class->upper_case_cname = camel_case_to_upper_case (current_class->name);
                current_namespace->classes = g_list_append (current_namespace->classes, current_class);
@@ -421,6 +422,7 @@ block
          {
                $$ = g_new0 (ValaStatement, 1);
                $$->type = VALA_STATEMENT_TYPE_BLOCK;
+               $$->location = current_location (@1);
                $$->block.statements = $2;
          }
        ;
@@ -463,6 +465,7 @@ declaration_statement
          {
                $$ = g_new0 (ValaStatement, 1);
                $$->type = VALA_STATEMENT_TYPE_VARIABLE_DECLARATION;
+               $$->location = current_location (@1);
                $$->variable_declaration = $1;;
          }
        ;
@@ -528,6 +531,7 @@ additive_expression
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_ADDITIVE;
+               $$->location = current_location (@1);
                $$->additive.left = $1;
                $$->additive.op = VALA_OP_TYPE_PLUS;
                $$->additive.right = $3;
@@ -562,12 +566,14 @@ literal
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_LITERAL_INTEGER;
+               $$->location = current_location (@1);
                $$->str = $1;
          }
        | LITERAL_STRING
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_LITERAL_STRING;
+               $$->location = current_location (@1);
                $$->str = $1;
          }
        ;
@@ -577,6 +583,7 @@ simple_name
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_SIMPLE_NAME;
+               $$->location = current_location (@1);
                $$->str = $1;
          }
        ;
@@ -586,6 +593,7 @@ parenthesized_expression
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_PARENTHESIZED;
+               $$->location = current_location (@1);
                $$->inner = $2;
          }
        ;
@@ -595,6 +603,7 @@ member_access
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_MEMBER_ACCESS;
+               $$->location = current_location (@1);
                $$->member_access.left = $1;
                $$->member_access.right = $3;
          }
@@ -605,6 +614,7 @@ invocation_expression
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_INVOCATION;
+               $$->location = current_location (@1);
                $$->invocation.call = $1;
                $$->invocation.argument_list = $3;
          }
@@ -667,6 +677,7 @@ expression_statement
          {
                $$ = g_new0 (ValaStatement, 1);
                $$->type = VALA_STATEMENT_TYPE_EXPRESSION;
+               $$->location = current_location (@1);
                $$->expr = $1;
          }
        ;
@@ -687,6 +698,7 @@ assignment
          {
                $$ = g_new0 (ValaExpression, 1);
                $$->type = VALA_EXPRESSION_TYPE_ASSIGNMENT;
+               $$->location = current_location (@1);
                $$->assignment.left = $1;
                $$->assignment.right = $3;
          }
@@ -704,6 +716,7 @@ return_statement
          {
                $$ = g_new0 (ValaStatement, 1);
                $$->type = VALA_STATEMENT_TYPE_RETURN;
+               $$->location = current_location (@1);
                $$->expr = $2;
          }
        ;
@@ -711,6 +724,7 @@ return_statement
 %%
 
 extern FILE *yyin;
+extern int yylineno;
 
 void yyerror (YYLTYPE *locp, const char *s)
 {
@@ -726,6 +740,10 @@ void vala_parser_parse (ValaSourceFile *source_file)
                printf ("Couldn't open source file: %s.\n", source_file->filename);
                return;
        }
+
+       /* restart line counter on each file */
+       yylineno = 1;
+       
        yyparse ();
        fclose (yyin);
        yyin = NULL;