]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
codegen: Use builder API 7a429688cdf0fd16cc1503a7666681792e309da8
authorJürg Billeter <j@bitron.ch>
Sat, 14 Aug 2010 13:24:18 +0000 (15:24 +0200)
committerJürg Billeter <j@bitron.ch>
Thu, 9 Sep 2010 14:45:49 +0000 (16:45 +0200)
28 files changed:
codegen/valaccodearraymodule.vala
codegen/valaccodeassignmentmodule.vala
codegen/valaccodebasemodule.vala
codegen/valaccodecontrolflowmodule.vala
codegen/valaccodememberaccessmodule.vala
codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valaccodestructmodule.vala
codegen/valadovaarraymodule.vala
codegen/valadovaassignmentmodule.vala
codegen/valadovabasemodule.vala
codegen/valadovacontrolflowmodule.vala
codegen/valadovaerrormodule.vala
codegen/valadovamemberaccessmodule.vala
codegen/valadovamethodcallmodule.vala
codegen/valadovaobjectmodule.vala
codegen/valadovastructmodule.vala
codegen/valadovavaluemodule.vala
codegen/valagasyncmodule.vala
codegen/valagerrormodule.vala
codegen/valagobjectmodule.vala
codegen/valagsignalmodule.vala
codegen/valagtypemodule.vala
vala/valablock.vala
vala/valaexpression.vala
vala/valamethod.vala
vala/valamethodcall.vala
vala/valayieldstatement.vala

index 1a5f239e216d441ae6c734fc7df94f2a646fdf2b..6db8f301fc1b19510f029df0e3e7e1ebc6d33234 100644 (file)
@@ -48,7 +48,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        var name_cnode = get_variable_cexpression (temp_var.name);
                        int i = 0;
 
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
 
                        append_initializer_list (ce, name_cnode, expr.initializer_list, expr.rank, ref i);
 
@@ -80,7 +80,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                                var name_cnode = get_variable_cexpression (temp_var.name);
                                size.ccodenode = name_cnode;
 
-                               temp_vars.add (temp_var);
+                               emit_temp_var (temp_var);
 
                                csize = new CCodeAssignment (name_cnode, csize);
                        }
@@ -112,7 +112,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        var name_cnode = get_variable_cexpression (temp_var.name);
                        int i = 0;
                        
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
                        
                        ce.append_expression (new CCodeAssignment (name_cnode, gnew));
 
@@ -428,15 +428,15 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
                var len_var = get_temp_variable (int_type);
                len_var.source_reference = expr.source_reference;
-               temp_vars.add (len_var);
+               emit_temp_var (len_var);
 
                var slice_var = get_temp_variable (expr.value_type, true, expr);
-               temp_vars.add (slice_var);
+               emit_temp_var (slice_var);
 
                if (!is_pure_ccode_expression (cstart)) {
                        // avoid double evaluation of start
                        var start_var = get_temp_variable (int_type);
-                       temp_vars.add (start_var);
+                       emit_temp_var (start_var);
 
                        var start_assignment = new CCodeAssignment (get_variable_cexpression (start_var.name), cstart);
                        ccomma.append_expression (start_assignment);
@@ -674,7 +674,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        }
 
                        var decl = get_temp_variable (expression_type, false, node);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ctemp = get_variable_cexpression (decl.name);
 
@@ -752,14 +752,11 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
                // definition
 
-               var block = new CCodeBlock ();
+               push_context (new EmitContext ());
+               push_function (function);
 
                if (requires_copy (array_type.element_type)) {
-                       push_context (new EmitContext ());
-
-                       var cdecl = new CCodeDeclaration (array_type.get_cname ());
                        var cvardecl = new CCodeVariableDeclarator ("result");
-                       cdecl.add_declarator (cvardecl);
                        var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
                        gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
 
@@ -770,28 +767,19 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        }
                        gnew.add_argument (length_expr);
 
-                       cvardecl.initializer = gnew;
-                       block.add_statement (cdecl);
-
-                       var idx_decl = new CCodeDeclaration ("int");
-                       idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
-                       block.add_statement (idx_decl);
-
-                       var loop_body = new CCodeBlock ();
-                       loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
+                       ccode.add_declaration (array_type.get_cname (), cvardecl);
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), gnew));
 
-                       var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")), loop_body);
-                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
-                       cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
-                       block.add_statement (cfor);
+                       ccode.add_declaration ("int", new CCodeVariableDeclarator ("i"));
 
-                       block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+                       ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")),
+                                          new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeIdentifier ("length")),
+                                          new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
 
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       block.add_statement (cfrag);
+                       ccode.add_expression (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type)));
+                       ccode.close ();
 
-                       pop_context ();
+                       ccode.add_return (new CCodeIdentifier ("result"));
                } else {
                        var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
                        dup_call.add_argument (new CCodeIdentifier ("self"));
@@ -800,16 +788,16 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
                        dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeIdentifier ("length"), sizeof_call));
 
-                       block.add_statement (new CCodeReturnStatement (dup_call));
+                       ccode.add_return (dup_call);
                }
 
                // append to file
 
                cfile.add_function_declaration (function);
-
-               function.block = block;
                cfile.add_function (function);
 
+               pop_context ();
+
                return dup_func;
        }
 
@@ -831,28 +819,18 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
                // definition
 
-               var block = new CCodeBlock ();
+               push_context (new EmitContext ());
+               push_function (function);
 
                if (requires_copy (array_type.element_type)) {
-                       push_context (new EmitContext ());
-
-                       var idx_decl = new CCodeDeclaration ("int");
-                       idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
-                       block.add_statement (idx_decl);
-
-                       var loop_body = new CCodeBlock ();
-                       loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
+                       ccode.add_declaration ("int", new CCodeVariableDeclarator ("i"));
 
-                       var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))), loop_body);
-                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
-                       cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
-                       block.add_statement (cfor);
+                       ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")),
+                                          new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))),
+                                          new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
 
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       block.add_statement (cfrag);
 
-                       pop_context ();
+                       ccode.add_expression (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type)));
                } else {
                        cfile.add_include ("string.h");
 
@@ -864,16 +842,16 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                        sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
                        dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call));
 
-                       block.add_statement (new CCodeExpressionStatement (dup_call));
+                       ccode.add_expression (dup_call);
                }
 
                // append to file
 
                cfile.add_function_declaration (function);
-
-               function.block = block;
                cfile.add_function (function);
 
+               pop_context ();
+
                return dup_func;
        }
 
index 20ed40923cc078b84781202b58f1f27ca7d19195..a403ada796fd016a61c72a41ac9eb2c7fd7b97ad 100644 (file)
@@ -126,13 +126,13 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
                                var lhs_value_type = assignment.left.value_type.copy ();
                                string lhs_temp_name = "_tmp%d_".printf (next_temp_var_id++);
                                var lhs_temp = new LocalVariable (lhs_value_type, "*" + lhs_temp_name);
-                               temp_vars.add (lhs_temp);
+                               emit_temp_var (lhs_temp);
                                outer_ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (lhs_temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, lhs)));
                                lhs = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (lhs_temp_name)));
                        }
 
                        var temp_decl = get_temp_variable (assignment.left.value_type, true, null, false);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), rhs));
                        if (unref_old) {
                                /* unref old value */
index c23ebe29f90f1c5a81385dc4dcb8205989da8c69..4015c00e37194907cdf82222515e7724ef2ef005 100644 (file)
@@ -31,8 +31,8 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                public Symbol? current_symbol;
                public ArrayList<Symbol> symbol_stack = new ArrayList<Symbol> ();
                public TryStatement current_try;
-               public CCodeSwitchStatement state_switch_statement;
-               public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
+               public CCodeFunction ccode;
+               public ArrayList<CCodeFunction> ccode_stack = new ArrayList<CCodeFunction> ();
                public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
                public int next_temp_var_id;
                public bool current_method_inner_error;
@@ -152,30 +152,19 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        public CCodeFile internal_header_file;
        public CCodeFile cfile;
 
-       public CCodeFragment class_init_fragment;
-       public CCodeFragment base_init_fragment;
-       public CCodeFragment class_finalize_fragment;
-       public CCodeFragment base_finalize_fragment;
-       public CCodeFragment instance_init_fragment;
-       public CCodeFragment instance_finalize_fragment;
+       public EmitContext class_init_context;
+       public EmitContext base_init_context;
+       public EmitContext class_finalize_context;
+       public EmitContext base_finalize_context;
+       public EmitContext instance_init_context;
+       public EmitContext instance_finalize_context;
        
        public CCodeStruct param_spec_struct;
        public CCodeStruct closure_struct;
        public CCodeEnum prop_enum;
-       public CCodeFunction function;
 
-       // code nodes to be inserted before the current statement
-       // used by async method calls in coroutines
-       public CCodeFragment pre_statement_fragment;
+       public CCodeFunction ccode { get { return emit_context.ccode; } }
 
-       // case statements to be inserted for the couroutine state
-       public CCodeSwitchStatement state_switch_statement {
-               get { return emit_context.state_switch_statement; }
-               set { emit_context.state_switch_statement = value; }
-       }
-
-       /* all temporary variables */
-       public ArrayList<LocalVariable> temp_vars { get { return emit_context.temp_vars; } }
        /* temporary variables that own their content */
        public ArrayList<LocalVariable> temp_ref_vars { get { return emit_context.temp_ref_vars; } }
        /* cache to check whether a certain marshaller has been created yet */
@@ -483,6 +472,16 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
        }
 
+       public void push_function (CCodeFunction func) {
+               emit_context.ccode_stack.add (ccode);
+               emit_context.ccode = func;
+       }
+
+       public void pop_function () {
+               emit_context.ccode = emit_context.ccode_stack[emit_context.ccode_stack.size - 1];
+               emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1);
+       }
+
        public bool add_symbol_declaration (CCodeFile decl_space, Symbol sym, string name) {
                if (decl_space.add_declaration (name)) {
                        return true;
@@ -726,13 +725,13 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                /* stuff meant for all lockable members */
                if (m is Lockable && ((Lockable) m).get_lock_used ()) {
                        CCodeExpression l = new CCodeIdentifier ("self");
-                       CCodeFragment init_fragment = class_init_fragment;
-                       CCodeFragment finalize_fragment = class_finalize_fragment;
+                       var init_context = class_init_context;
+                       var finalize_context = class_finalize_context;
 
                        if (m.is_instance_member ()) {
                                l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m.name));
-                               init_fragment = instance_init_fragment;
-                               finalize_fragment = instance_finalize_fragment;
+                               init_context = instance_init_context;
+                               finalize_context = instance_finalize_context;
                        } else if (m.is_class_member ()) {
                                TypeSymbol parent = (TypeSymbol)m.parent_symbol;
 
@@ -743,14 +742,18 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                l = new CCodeIdentifier (get_symbol_lock_name ("%s_%s".printf(m.parent_symbol.get_lower_case_cname (), m.name)));
                        }
 
+                       push_context (init_context);
                        var initf = new CCodeFunctionCall (new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
                        initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-                       init_fragment.append (new CCodeExpressionStatement (initf));
+                       ccode.add_expression (initf);
+                       pop_context ();
 
-                       if (finalize_fragment != null) {
+                       if (finalize_context != null) {
+                               push_context (finalize_context);
                                var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
                                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-                               finalize_fragment.append (new CCodeExpressionStatement (fc));
+                               ccode.add_expression (fc);
+                               pop_context ();
                        }
                }
        }
@@ -894,10 +897,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                check_type (f.variable_type);
 
-               if (f.initializer != null) {
-                       f.initializer.emit (this);
-               }
-
                var cl = f.parent_symbol as Class;
                bool is_gtypeinstance = (cl != null && !cl.is_compact);
 
@@ -916,9 +915,13 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
 
                        if (f.initializer != null) {
+                               push_context (instance_init_context);
+
+                               f.initializer.emit (this);
+
                                var rhs = (CCodeExpression) f.initializer.ccodenode;
 
-                               instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+                               ccode.add_expression (new CCodeAssignment (lhs, rhs));
 
                                if (f.variable_type is ArrayType && !f.no_array_length &&
                                    f.initializer is ArrayCreationExpression) {
@@ -933,30 +936,31 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                                var array_len_lhs = get_array_length_cexpression (ma, dim);
                                                var size = sizes[dim - 1];
-                                               instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode)));
+                                               ccode.add_expression (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode));
                                        }
 
                                        if (array_type.rank == 1 && f.is_internal_symbol ()) {
                                                var lhs_array_size = get_array_size_cexpression (ma);
                                                var rhs_array_len = get_array_length_cexpression (ma, 1);
-                                               instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs_array_size, rhs_array_len)));
+                                               ccode.add_expression (new CCodeAssignment (lhs_array_size, rhs_array_len));
                                        }
                                }
 
-                               append_temp_decl (instance_init_fragment, temp_vars);
-
                                foreach (LocalVariable local in temp_ref_vars) {
                                        var ma = new MemberAccess.simple (local.name);
                                        ma.symbol_reference = local;
                                        ma.value_type = local.variable_type.copy ();
-                                       instance_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                                       ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                                }
 
-                               temp_vars.clear ();
                                temp_ref_vars.clear ();
+
+                               pop_context ();
                        }
                        
-                       if (requires_destroy (f.variable_type) && instance_finalize_fragment != null) {
+                       if (requires_destroy (f.variable_type) && instance_finalize_context != null) {
+                               push_context (instance_finalize_context);
+
                                var this_access = new MemberAccess.simple ("this");
                                this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
 
@@ -970,7 +974,9 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                var ma = new MemberAccess (this_access, f.name);
                                ma.symbol_reference = f;
                                ma.value_type = f.variable_type.copy ();
-                               instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (lhs, f.variable_type, ma));
+
+                               pop_context ();
                        }
                } else if (f.binding == MemberBinding.CLASS)  {
                        if (!is_gtypeinstance) {
@@ -988,21 +994,24 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
 
                        if (f.initializer != null) {
-                               var rhs = (CCodeExpression) f.initializer.ccodenode;
+                               push_context (class_init_context);
+
+                               f.initializer.emit (this);
 
-                               class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+                               var rhs = (CCodeExpression) f.initializer.ccodenode;
 
-                               append_temp_decl (class_init_fragment, temp_vars);
+                               ccode.add_expression (new CCodeAssignment (lhs, rhs));
 
                                foreach (LocalVariable local in temp_ref_vars) {
                                        var ma = new MemberAccess.simple (local.name);
                                        ma.symbol_reference = local;
                                        ma.value_type = local.variable_type.copy ();
-                                       class_init_fragment.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                                       ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                                }
 
-                               temp_vars.clear ();
                                temp_ref_vars.clear ();
+
+                               pop_context ();
                        }
                } else {
                        generate_field_declaration (f, cfile);
@@ -1019,7 +1028,15 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        var var_decl = new CCodeVariableDeclarator (f.get_cname (), null, f.variable_type.get_cdeclarator_suffix ());
                        var_decl.initializer = default_value_for_type (f.variable_type, true);
 
+                       if (class_init_context != null) {
+                               push_context (class_init_context);
+                       } else {
+                               push_context (new EmitContext ());
+                       }
+
                        if (f.initializer != null) {
+                               f.initializer.emit (this);
+
                                var init = (CCodeExpression) f.initializer.ccodenode;
                                if (is_constant_ccode_expression (init)) {
                                        var_decl.initializer = init;
@@ -1095,23 +1112,18 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                if (!is_constant_ccode_expression (rhs)) {
                                        if (f.parent_symbol is Class) {
                                                if (f.initializer is InitializerList) {
-                                                       var block = new CCodeBlock ();
-                                                       var frag = new CCodeFragment ();
+                                                       ccode.open_block ();
 
                                                        var temp_decl = get_temp_variable (f.variable_type);
-                                                       var cdecl = new CCodeDeclaration (temp_decl.variable_type.get_cname ());
-                                                       var vardecl = new CCodeVariableDeclarator (temp_decl.name, rhs);
-                                                       cdecl.add_declarator (vardecl);
-                                                       vardecl.init0 = true;
-                                                       frag.append (cdecl);
+                                                       var vardecl = new CCodeVariableDeclarator.zero (temp_decl.name, rhs);
+                                                       ccode.add_declaration (temp_decl.variable_type.get_cname (), vardecl);
 
                                                        var tmp = get_variable_cexpression (get_variable_cname (temp_decl.name));
-                                                       frag.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, tmp)));
+                                                       ccode.add_expression (new CCodeAssignment (lhs, tmp));
 
-                                                       block.add_statement (frag);
-                                                       class_init_fragment.append (block);
+                                                       ccode.close ();
                                                } else {
-                                                       class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+                                                       ccode.add_expression (new CCodeAssignment (lhs, rhs));
                                                }
 
                                                if (f.variable_type is ArrayType && !f.no_array_length &&
@@ -1124,12 +1136,9 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                                                var array_len_lhs = get_array_length_cexpression (ma, dim);
                                                                var size = sizes[dim - 1];
-                                                               class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode)));
+                                                               ccode.add_expression (new CCodeAssignment (array_len_lhs, (CCodeExpression) size.ccodenode));
                                                        }
                                                }
-
-                                               append_temp_decl (class_init_fragment, temp_vars);
-                                               temp_vars.clear ();
                                        } else {
                                                f.error = true;
                                                Report.error (f.source_reference, "Non-constant field initializers not supported in this context");
@@ -1137,6 +1146,8 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        }
                                }
                        }
+
+                       pop_context ();
                }
        }
 
@@ -1275,6 +1286,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
                generate_type_declaration (acc.value_type, decl_space);
 
+               CCodeFunction function;
                if (acc.readable && !returns_real_struct) {
                        function = new CCodeFunction (acc.get_cname (), acc.value_type.get_cname ());
                } else {
@@ -1531,46 +1543,34 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                }
                        }
 
-                       var init_fragment = new CCodeFragment ();
+                       push_function (function);
 
                        if (prop.binding == MemberBinding.INSTANCE && !is_virtual) {
-                               CCodeStatement check_stmt;
                                if (!acc.readable || returns_real_struct) {
-                                       check_stmt = create_property_type_check_statement (prop, false, t, true, "self");
+                                       create_property_type_check_statement (prop, false, t, true, "self");
                                } else {
-                                       check_stmt = create_property_type_check_statement (prop, true, t, true, "self");
-                               }
-                               if (check_stmt != null) {
-                                       init_fragment.append (check_stmt);
+                                       create_property_type_check_statement (prop, true, t, true, "self");
                                }
                        }
 
+                       if (current_method_inner_error) {
+                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
+                       }
+
                        if (acc.readable && !returns_real_struct) {
                                // do not declare result variable if exit block is known to be unreachable
                                if (acc.return_block == null || acc.return_block.get_predecessors ().size > 0) {
-                                       var cdecl = new CCodeDeclaration (acc.value_type.get_cname ());
-                                       cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
-                                       init_fragment.append (cdecl);
+                                       ccode.add_declaration (acc.value_type.get_cname (), new CCodeVariableDeclarator ("result"));
                                }
                        }
 
                        if (is_virtual) {
-                               var cdecl = new CCodeDeclaration (this_type.get_cname ());
-                               cdecl.add_declarator (new CCodeVariableDeclarator ("self", transform_expression (new CCodeIdentifier ("base"), base_type, this_type)));
-                               init_fragment.append (cdecl);
+                               ccode.add_declaration (this_type.get_cname (), new CCodeVariableDeclarator ("self"));
+                               ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), transform_expression (new CCodeIdentifier ("base"), base_type, this_type)));
                        }
 
                        acc.body.emit (this);
 
-                       function.block = (CCodeBlock) acc.body.ccodenode;
-                       function.block.prepend_statement (init_fragment);
-
-                       if (current_method_inner_error) {
-                               var cdecl = new CCodeDeclaration ("GError *");
-                               cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
-                               function.block.add_statement (cdecl);
-                       }
-
                        // notify on property changes
                        if (is_gobject_property (prop) &&
                            prop.notify &&
@@ -1578,7 +1578,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                var notify_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_notify"));
                                notify_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
                                notify_call.add_argument (prop.get_canonical_cconstant ());
-                               function.block.add_statement (new CCodeExpressionStatement (notify_call));
+                               ccode.add_expression (notify_call);
                        }
 
                        cfile.add_function (function);
@@ -1588,30 +1588,11 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        }
 
        public override void visit_destructor (Destructor d) {
-               bool old_method_inner_error = current_method_inner_error;
-               current_method_inner_error = false;
-
-               d.body.emit (this);
-
                if (d.binding == MemberBinding.STATIC && !in_plugin) {
                        Report.error (d.source_reference, "static destructors are only supported for dynamic types");
                        d.error = true;
                        return;
                }
-
-               CCodeFragment cfrag = new CCodeFragment ();
-
-               if (current_method_inner_error) {
-                       var cdecl = new CCodeDeclaration ("GError *");
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
-                       cfrag.append (cdecl);
-               }
-
-               cfrag.append (d.body.ccodenode);
-
-               d.ccodenode = cfrag;
-
-               current_method_inner_error = old_method_inner_error;
        }
 
        public int get_block_id (Block b) {
@@ -1623,7 +1604,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                return result;
        }
 
-       void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) {
+       void capture_parameter (FormalParameter param, CCodeStruct data, int block_id, CCodeBlock free_block) {
                generate_type_declaration (param.variable_type, cfile);
 
                var param_type = param.variable_type.copy ();
@@ -1647,20 +1628,20 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        param.captured = true;
                }
 
-               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
+               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam));
 
                if (param.variable_type is ArrayType) {
                        var array_type = (ArrayType) param.variable_type;
                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                data.add_field ("gint", get_array_length_cname (get_variable_cname (param.name), dim));
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim))));
                        }
                } else if (param.variable_type is DelegateType) {
                        data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)))));
                        if (param.variable_type.value_owned) {
                                data.add_field ("GDestroyNotify", get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)));
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)))));
                        }
                }
 
@@ -1685,16 +1666,11 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        public override void visit_block (Block b) {
                emit_context.push_symbol (b);
 
-               foreach (Statement stmt in b.get_statements ()) {
-                       stmt.emit (this);
-               }
-
                var local_vars = b.get_local_variables ();
-               foreach (LocalVariable local in local_vars) {
-                       local.active = false;
+
+               if (b.parent_node is Block || b.parent_node is SwitchStatement) {
+                       ccode.open_block ();
                }
-               
-               var cblock = new CCodeBlock ();
 
                if (b.captured) {
                        var parent_block = next_closure_block (b.parent_symbol);
@@ -1770,15 +1746,13 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (struct_name + "*", "_data%d_".printf (block_id));
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression ("_data%d_".printf (block_id)), data_alloc)));
                        } else {
-                               var data_decl = new CCodeDeclaration (struct_name + "*");
-                               data_decl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (block_id), data_alloc));
-                               cblock.add_statement (data_decl);
+                               ccode.add_declaration (struct_name + "*", new CCodeVariableDeclarator ("_data%d_".printf (block_id)));
                        }
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_data%d_".printf (block_id)), data_alloc));
 
                        // initialize ref_count
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_ref_count_"), new CCodeIdentifier ("1"))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_ref_count_"), new CCodeIdentifier ("1")));
 
                        if (parent_block != null) {
                                int parent_block_id = get_block_id (parent_block);
@@ -1786,14 +1760,14 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_ref".printf (parent_block_id)));
                                ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
 
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call));
                        } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE &&
                                                      (!(current_method is CreationMethod) || current_method.body != b)) ||
                                   (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
                                var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
                                ref_call.add_argument (get_result_cexpression ("self"));
 
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call)));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call));
                        }
 
                        if (b.parent_symbol is Method) {
@@ -1802,7 +1776,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                // parameters are captured with the top-level block of the method
                                foreach (var param in m.get_parameters ()) {
                                        if (param.captured) {
-                                               capture_parameter (param, data, cblock, block_id, free_block);
+                                               capture_parameter (param, data, block_id, free_block);
                                        }
                                }
 
@@ -1812,24 +1786,14 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                                        // async method is suspended while waiting for callback,
                                        // so we never need to care about memory management of async data
-                                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("data"))));
+                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_async_data_"), new CCodeIdentifier ("data")));
                                }
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               temp_vars.clear ();
-                               cblock.add_statement (cfrag);
                        } else if (b.parent_symbol is PropertyAccessor) {
                                var acc = (PropertyAccessor) b.parent_symbol;
 
                                if (!acc.readable && acc.value_parameter.captured) {
-                                       capture_parameter (acc.value_parameter, data, cblock, block_id, free_block);
+                                       capture_parameter (acc.value_parameter, data, block_id, free_block);
                                }
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               temp_vars.clear ();
-                               cblock.add_statement (cfrag);
                        }
 
                        var typedef = new CCodeTypeDefinition ("struct _" + struct_name, new CCodeVariableDeclarator (struct_name));
@@ -1867,28 +1831,19 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        cfile.add_function (unref_fun);
                }
 
-               foreach (CodeNode stmt in b.get_statements ()) {
-                       if (stmt.error || stmt.unreachable) {
-                               continue;
-                       }
-                       
-                       if (stmt.ccodenode is CCodeFragment) {
-                               foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
-                                       cblock.add_statement (cstmt);
-                               }
-                       } else {
-                               cblock.add_statement (stmt.ccodenode);
-                       }
+               foreach (Statement stmt in b.get_statements ()) {
+                       stmt.emit (this);
                }
 
                // free in reverse order
                for (int i = local_vars.size - 1; i >= 0; i--) {
                        var local = local_vars[i];
+                       local.active = false;
                        if (!local.unreachable && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
                                ma.value_type = local.variable_type.copy ();
-                               cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
 
@@ -1899,7 +1854,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        var ma = new MemberAccess.simple (param.name);
                                        ma.symbol_reference = param;
                                        ma.value_type = param.variable_type.copy ();
-                                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)));
+                                       ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma));
                                }
                        }
                }
@@ -1909,30 +1864,18 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id)));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cblock.add_statement (new CCodeExpressionStatement (data_unref));
+                       ccode.add_expression (data_unref);
                }
 
-               b.ccodenode = cblock;
+               if (b.parent_node is Block || b.parent_node is SwitchStatement) {
+                       ccode.close ();
+               }
 
                emit_context.pop_symbol ();
        }
 
-       public override void visit_empty_statement (EmptyStatement stmt) {
-               stmt.ccodenode = new CCodeEmptyStatement ();
-       }
-
        public override void visit_declaration_statement (DeclarationStatement stmt) {
                stmt.declaration.accept (this);
-
-               stmt.ccodenode = stmt.declaration.ccodenode;
-
-               var local = stmt.declaration as LocalVariable;
-               if (local != null && local.initializer != null) {
-                       create_temp_decl (stmt, local.initializer.temp_vars);
-               }
-
-               create_temp_decl (stmt, temp_vars);
-               temp_vars.clear ();
        }
 
        public CCodeExpression get_variable_cexpression (string name) {
@@ -1999,12 +1942,12 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                if (!array_type.fixed_length) {
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                                var len_var = new LocalVariable (int_type.copy (), get_array_length_cname (get_variable_cname (local.name), dim));
-                                               temp_vars.add (len_var);
+                                               emit_temp_var (len_var);
                                        }
 
                                        if (array_type.rank == 1) {
                                                var size_var = new LocalVariable (int_type.copy (), get_array_size_cname (get_variable_cname (local.name)));
-                                               temp_vars.add (size_var);
+                                               emit_temp_var (size_var);
                                        }
                                }
                        } else if (local.variable_type is DelegateType) {
@@ -2013,10 +1956,10 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                if (d.has_target) {
                                        // create variable to store delegate target
                                        var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (get_variable_cname (local.name)));
-                                       temp_vars.add (target_var);
+                                       emit_temp_var (target_var);
                                        if (deleg_type.value_owned) {
                                                var target_destroy_notify_var = new LocalVariable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")), get_delegate_target_destroy_notify_cname (get_variable_cname (local.name)));
-                                               temp_vars.add (target_destroy_notify_var);
+                                               emit_temp_var (target_destroy_notify_var);
                                        }
                                }
                        }
@@ -2039,7 +1982,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (local.variable_type, true, local, false);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs));
 
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
@@ -2064,7 +2007,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (local.variable_type, true, local, false);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs));
 
                                        CCodeExpression lhs_delegate_target_destroy_notify;
@@ -2113,19 +2056,12 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
                }
 
-               var cfrag = new CCodeFragment ();
-
-               if (pre_statement_fragment != null) {
-                       cfrag.append (pre_statement_fragment);
-                       pre_statement_fragment = null;
-               }
-
                if (local.captured) {
                        if (local.initializer != null) {
                                if (has_simple_struct_initializer (local)) {
-                                       cfrag.append (new CCodeExpressionStatement (rhs));
+                                       ccode.add_expression (rhs);
                                } else {
-                                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id ((Block) local.parent_symbol))), get_variable_cname (local.name)), rhs)));
+                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id ((Block) local.parent_symbol))), get_variable_cname (local.name)), rhs));
                                }
                        }
                } else if (current_method != null && current_method.coroutine) {
@@ -2133,15 +2069,15 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        if (local.initializer != null) {
                                if (has_simple_struct_initializer (local)) {
-                                       cfrag.append (new CCodeExpressionStatement (rhs));
+                                       ccode.add_expression (rhs);
                                } else {
-                                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
+                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs));
                                }
                        }
                } else {
-                       CCodeStatement post_stmt = null;
+                       CCodeExpression post_rhs = null;
                        if (has_simple_struct_initializer (local)) {
-                               post_stmt = new CCodeExpressionStatement (rhs);
+                               post_rhs = rhs;
                                rhs = null;
                        }
 
@@ -2150,10 +2086,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                cvar.line = rhs.line;
                        }
 
-                       var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
-                       cdecl.add_declarator (cvar);
-                       cfrag.append (cdecl);
-
                        // try to initialize uninitialized variables
                        // initialization not necessary for variables stored in closure
                        if (cvar.initializer == null) {
@@ -2161,8 +2093,15 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                cvar.init0 = true;
                        }
 
-                       if (post_stmt != null) {
-                               cfrag.append (post_stmt);
+                       ccode.add_declaration (local.variable_type.get_cname (), cvar);
+
+                       if (cvar.initializer != null && !cvar.init0) {
+                               cvar.initializer = null;
+                               ccode.add_expression (new CCodeAssignment (get_variable_cexpression (local.name), rhs));
+                       }
+
+                       if (post_rhs != null) {
+                               ccode.add_expression (post_rhs);
                        }
                }
 
@@ -2182,16 +2121,14 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                ccopy.add_argument (get_variable_cexpression (local.name));
                                ccopy.add_argument ((CCodeExpression) local.initializer.ccodenode);
                                ccopy.add_argument (size);
-                               cfrag.append (new CCodeExpressionStatement (ccopy));
+                               ccode.add_expression (ccopy);
                        }
                }
 
                if (local.initializer != null && local.initializer.tree_can_fail) {
-                       add_simple_check (local.initializer, cfrag);
+                       add_simple_check (local.initializer);
                }
 
-               local.ccodenode = cfrag;
-
                local.active = true;
        }
 
@@ -2229,7 +2166,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        } else {
                                // used as expression
                                var temp_decl = get_temp_variable (list.target_type, false, list);
-                               temp_vars.add (temp_decl);
+                               emit_temp_var (temp_decl);
 
                                var instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
 
@@ -3055,25 +2992,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                 * we unref temporary variables at the end of a full
                 * expression
                 */
-               
-               /* can't automatically deep copy lists yet, so do it
-                * manually for now
-                * replace with
-                * expr.temp_vars = temp_vars;
-                * when deep list copying works
-                */
-               if (temp_vars.size > 0) {
-                       if (expr.temp_vars == null) {
-                               expr.temp_vars = new ArrayList<LocalVariable> ();
-                       } else {
-                               expr.temp_vars.clear ();
-                       }
-                       foreach (LocalVariable local in temp_vars) {
-                               expr.add_temp_var (local);
-                       }
-                       temp_vars.clear ();
-               }
-
                if (((List<LocalVariable>) temp_ref_vars).size == 0) {
                        /* nothing to do without temporary variables */
                        return;
@@ -3093,7 +3011,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
 
                        full_expr_var = get_temp_variable (expr_type, true, expr, false);
-                       expr.add_temp_var (full_expr_var);
+                       emit_temp_var (full_expr_var);
                
                        expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
                }
@@ -3114,65 +3032,57 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                temp_ref_vars.clear ();
        }
        
-       public void append_temp_decl (CCodeFragment cfrag, List<LocalVariable>? temp_vars) {
-               if (temp_vars == null) {
-                       return;
-               }
-               foreach (LocalVariable local in temp_vars) {
-                       var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
-
-                       var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ());
-                       // sets #line
-                       local.ccodenode = vardecl;
-                       cdecl.add_declarator (vardecl);
-
-                       var st = local.variable_type.data_type as Struct;
-                       var array_type = local.variable_type as ArrayType;
-
-                       if (local.name.has_prefix ("*")) {
-                               // do not dereference unintialized variable
-                               // initialization is not needed for these special
-                               // pointer temp variables
-                               // used to avoid side-effects in assignments
-                       } else if (local.no_init) {
-                               // no initialization necessary for this temp var
-                       } else if (!local.variable_type.nullable &&
-                                  (st != null && !st.is_simple_type ()) ||
-                                  (array_type != null && array_type.fixed_length)) {
-                               // 0-initialize struct with struct initializer { 0 }
-                               // necessary as they will be passed by reference
-                               var clist = new CCodeInitializerList ();
-                               clist.append (new CCodeConstant ("0"));
+       public void emit_temp_var (LocalVariable local) {
+               var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ());
+               // sets #line
+               local.ccodenode = vardecl;
 
-                               vardecl.initializer = clist;
-                               vardecl.init0 = true;
-                       } else if (local.variable_type.is_reference_type_or_type_parameter () ||
-                              local.variable_type.nullable ||
-                              local.variable_type is DelegateType) {
-                               vardecl.initializer = new CCodeConstant ("NULL");
-                               vardecl.init0 = true;
-                       }
+               var st = local.variable_type.data_type as Struct;
+               var array_type = local.variable_type as ArrayType;
+
+               if (local.name.has_prefix ("*")) {
+                       // do not dereference unintialized variable
+                       // initialization is not needed for these special
+                       // pointer temp variables
+                       // used to avoid side-effects in assignments
+               } else if (local.no_init) {
+                       // no initialization necessary for this temp var
+               } else if (!local.variable_type.nullable &&
+                          (st != null && !st.is_simple_type ()) ||
+                          (array_type != null && array_type.fixed_length)) {
+                       // 0-initialize struct with struct initializer { 0 }
+                       // necessary as they will be passed by reference
+                       var clist = new CCodeInitializerList ();
+                       clist.append (new CCodeConstant ("0"));
 
-                       if (current_method != null && current_method.coroutine) {
-                               closure_struct.add_field (local.variable_type.get_cname (), local.name);
+                       vardecl.initializer = clist;
+                       vardecl.init0 = true;
+               } else if (local.variable_type.is_reference_type_or_type_parameter () ||
+                          local.variable_type.nullable ||
+                          local.variable_type is DelegateType) {
+                       vardecl.initializer = new CCodeConstant ("NULL");
+                       vardecl.init0 = true;
+               }
 
-                               // even though closure struct is zerod, we need to initialize temporary variables
-                               // as they might be used multiple times when declared in a loop
+               if (current_method != null && current_method.coroutine) {
+                       closure_struct.add_field (local.variable_type.get_cname (), local.name);
 
-                               if (vardecl.initializer  is CCodeInitializerList) {
-                                       // C does not support initializer lists in assignments, use memset instead
-                                       cfile.add_include ("string.h");
-                                       var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
-                                       memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name)));
-                                       memset_call.add_argument (new CCodeConstant ("0"));
-                                       memset_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (local.variable_type.get_cname ())));
-                                       cfrag.append (new CCodeExpressionStatement (memset_call));
-                               } else if (vardecl.initializer != null) {
-                                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer)));
-                               }
-                       } else {
-                               cfrag.append (cdecl);
+                       // even though closure struct is zerod, we need to initialize temporary variables
+                       // as they might be used multiple times when declared in a loop
+
+                       if (vardecl.initializer  is CCodeInitializerList) {
+                               // C does not support initializer lists in assignments, use memset instead
+                               cfile.add_include ("string.h");
+                               var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
+                               memset_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (local.name)));
+                               memset_call.add_argument (new CCodeConstant ("0"));
+                               memset_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (local.variable_type.get_cname ())));
+                               ccode.add_expression (memset_call);
+                       } else if (vardecl.initializer != null) {
+                               ccode.add_expression (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer));
                        }
+               } else {
+                       ccode.add_declaration (local.variable_type.get_cname (), vardecl);
                }
        }
 
@@ -3182,62 +3092,26 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        return;
                }
 
-               stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
+               ccode.add_expression ((CCodeExpression) stmt.expression.ccodenode);
 
                /* free temporary objects and handle errors */
 
-               if (((List<LocalVariable>) temp_vars).size == 0
-                    && pre_statement_fragment == null
-                    && (!stmt.tree_can_fail || !stmt.expression.tree_can_fail)) {
-                       /* nothing to do without temporary variables and errors */
-                       return;
-               }
-
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-
-               if (pre_statement_fragment != null) {
-                       cfrag.append (pre_statement_fragment);
-                       pre_statement_fragment = null;
-               }
-
-               cfrag.append (stmt.ccodenode);
-               
                foreach (LocalVariable local in temp_ref_vars) {
                        var ma = new MemberAccess.simple (local.name);
                        ma.symbol_reference = local;
                        ma.value_type = local.variable_type.copy ();
-                       cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                       ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                }
 
                if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
                        // simple case, no node breakdown necessary
-                       add_simple_check (stmt.expression, cfrag);
+                       add_simple_check (stmt.expression);
                }
 
-               stmt.ccodenode = cfrag;
-
-               temp_vars.clear ();
                temp_ref_vars.clear ();
        }
-       
-       public void create_temp_decl (Statement stmt, List<LocalVariable>? temp_vars) {
-               /* declare temporary variables */
-               
-               if (temp_vars == null || temp_vars.size == 0) {
-                       /* nothing to do without temporary variables */
-                       return;
-               }
-               
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-               
-               cfrag.append (stmt.ccodenode);
-               
-               stmt.ccodenode = cfrag;
-       }
 
-       public virtual void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+       public virtual void append_local_free (Symbol sym, bool stop_at_loop = false) {
                var b = (Block) sym;
 
                var local_vars = b.get_local_variables ();
@@ -3248,7 +3122,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
                                ma.value_type = local.variable_type.copy ();
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
 
@@ -3257,7 +3131,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id)));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cfrag.append (new CCodeExpressionStatement (data_unref));
+                       ccode.add_expression (data_unref);
                }
 
                if (stop_at_loop) {
@@ -3269,13 +3143,13 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
 
                if (sym.parent_symbol is Block) {
-                       append_local_free (sym.parent_symbol, cfrag, stop_at_loop);
+                       append_local_free (sym.parent_symbol, stop_at_loop);
                } else if (sym.parent_symbol is Method) {
-                       append_param_free ((Method) sym.parent_symbol, cfrag);
+                       append_param_free ((Method) sym.parent_symbol);
                }
        }
 
-       public void append_error_free (Symbol sym, CCodeFragment cfrag, TryStatement current_try) {
+       public void append_error_free (Symbol sym, TryStatement current_try) {
                var b = (Block) sym;
 
                var local_vars = b.get_local_variables ();
@@ -3285,7 +3159,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        if (!local.unreachable && local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
 
@@ -3294,7 +3168,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (block_id)));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cfrag.append (new CCodeExpressionStatement (data_unref));
+                       ccode.add_expression (data_unref);
                }
 
                if (sym == current_try.body) {
@@ -3302,32 +3176,23 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
 
                if (sym.parent_symbol is Block) {
-                       append_error_free (sym.parent_symbol, cfrag, current_try);
+                       append_error_free (sym.parent_symbol, current_try);
                } else if (sym.parent_symbol is Method) {
-                       append_param_free ((Method) sym.parent_symbol, cfrag);
+                       append_param_free ((Method) sym.parent_symbol);
                }
        }
 
-       private void append_param_free (Method m, CCodeFragment cfrag) {
+       private void append_param_free (Method m) {
                foreach (FormalParameter param in m.get_parameters ()) {
                        if (!param.ellipsis && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) {
                                var ma = new MemberAccess.simple (param.name);
                                ma.symbol_reference = param;
                                ma.value_type = param.variable_type.copy ();
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma));
                        }
                }
        }
 
-       public void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
-               var cfrag = new CCodeFragment ();
-       
-               append_local_free (current_symbol, cfrag, stop_at_loop);
-
-               cfrag.append (stmt.ccodenode);
-               stmt.ccodenode = cfrag;
-       }
-
        public bool variable_accessible_in_finally (LocalVariable local) {
                if (current_try == null) {
                        return false;
@@ -3386,7 +3251,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        ccomma.append_expression (get_variable_cexpression (return_expr_decl.name));
 
                        stmt.return_expression.ccodenode = ccomma;
-                       stmt.return_expression.add_temp_var (return_expr_decl);
+                       emit_temp_var (return_expr_decl);
                } else if ((current_method != null || current_property_accessor != null) && current_return_type is DelegateType) {
                        var delegate_type = (DelegateType) current_return_type;
                        if (delegate_type.delegate_symbol.has_target) {
@@ -3413,52 +3278,37 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                ccomma.append_expression (get_variable_cexpression (return_expr_decl.name));
 
                                stmt.return_expression.ccodenode = ccomma;
-                               stmt.return_expression.add_temp_var (return_expr_decl);
+                               emit_temp_var (return_expr_decl);
                        }
                }
 
-               var cfrag = new CCodeFragment ();
-
                if (stmt.return_expression != null) {
                        // assign method result to `result'
                        CCodeExpression result_lhs = get_result_cexpression ();
                        if (current_return_type.is_real_non_null_struct_type () && (current_method == null || !current_method.coroutine)) {
                                result_lhs = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, result_lhs);
                        }
-                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (result_lhs, (CCodeExpression) stmt.return_expression.ccodenode)));
+                       ccode.add_expression (new CCodeAssignment (result_lhs, (CCodeExpression) stmt.return_expression.ccodenode));
                }
 
                // free local variables
-               append_local_free (current_symbol, cfrag);
+               append_local_free (current_symbol);
 
                if (current_method != null) {
                        // check postconditions
                        foreach (Expression postcondition in current_method.get_postconditions ()) {
-                               cfrag.append (create_postcondition_statement (postcondition));
+                               create_postcondition_statement (postcondition);
                        }
                }
 
-               CCodeReturnStatement creturn = null;
                if (current_method is CreationMethod) {
-                       creturn = new CCodeReturnStatement (new CCodeIdentifier ("self"));
-                       cfrag.append (creturn);
+                       ccode.add_return (new CCodeIdentifier ("self"));
                } else if (current_method != null && current_method.coroutine) {
                } else if (current_return_type is VoidType || current_return_type.is_real_non_null_struct_type ()) {
                        // structs are returned via out parameter
-                       creturn = new CCodeReturnStatement ();
-                       cfrag.append (creturn);
+                       ccode.add_return ();
                } else {
-                       creturn = new CCodeReturnStatement (new CCodeIdentifier ("result"));
-                       cfrag.append (creturn);
-               }
-
-               stmt.ccodenode = cfrag;
-               if (creturn != null) {
-                       creturn.line = stmt.ccodenode.line;
-               }
-
-               if (stmt.return_expression != null) {
-                       create_temp_decl (stmt, stmt.return_expression.temp_vars);
+                       ccode.add_return (new CCodeIdentifier ("result"));
                }
 
                if (return_expression_symbol != null) {
@@ -3515,9 +3365,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
 
-               var cn = new CCodeFragment ();
-               cn.append (new CCodeExpressionStatement (fc));
-               stmt.ccodenode = cn;
+               ccode.add_expression (fc);
        }
                
        public override void visit_unlock_statement (UnlockStatement stmt) {
@@ -3526,9 +3374,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                var fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
                fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
                
-               var cn = new CCodeFragment ();
-               cn.append (new CCodeExpressionStatement (fc));
-               stmt.ccodenode = cn;
+               ccode.add_expression (fc);
        }
 
        public override void visit_delete_statement (DeleteStatement stmt) {
@@ -3540,7 +3386,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
                ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode);
-               stmt.ccodenode = new CCodeExpressionStatement (ccall);
+               ccode.add_expression (ccall);
        }
 
        public override void visit_expression (Expression expr) {
@@ -3627,7 +3473,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
 
                var regex_var = get_temp_variable (regex_type, true, expr, false);
-               expr.add_temp_var (regex_var);
+               emit_temp_var (regex_var);
 
                var cdecl = new CCodeDeclaration ("GRegex*");
 
@@ -3715,7 +3561,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        
                        // assign current value to temp variable
                        var temp_decl = get_temp_variable (prop.property_type, true, expr, false);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), (CCodeExpression) expr.inner.ccodenode));
                        
                        // increment/decrement property
@@ -3826,7 +3672,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        // (copy (&expr, &temp), temp)
 
                        var decl = get_temp_variable (expression_type, false, node);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ctemp = get_variable_cexpression (decl.name);
                        
@@ -3926,7 +3772,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        return ccall;
                } else {
                        var decl = get_temp_variable (expression_type, false, node, false);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ctemp = get_variable_cexpression (decl.name);
                        
@@ -4149,7 +3995,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                }
                        } else {
                                var temp_decl = get_temp_variable (expr.type_reference, false, expr);
-                               temp_vars.add (temp_decl);
+                               emit_temp_var (temp_decl);
 
                                instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
                        }
@@ -4457,7 +4303,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (type, true, null, false);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr));
                                        ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
 
@@ -4529,7 +4375,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        expr.append_array_size (len_call);
                } else if (to is StructValueType) {
                        var temp_decl = get_temp_variable (to, true, null, true);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        var ctemp = get_variable_cexpression (temp_decl.name);
 
                        rv = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeCastExpression (rv, (new PointerType(to)).get_cname ()));
@@ -4577,7 +4423,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                var temp_decl = get_temp_variable (int_type, false, expr);
-                               temp_vars.add (temp_decl);
+                               emit_temp_var (temp_decl);
 
                                ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
                                cfunc.add_parameter (new CCodeFormalParameter (get_array_length_cname ("result", dim), "int*"));
@@ -4631,7 +4477,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                var ccomma = new CCodeCommaExpression ();
                                var temp_decl = get_temp_variable (expr.inner.value_type, true, expr, false);
 
-                               temp_vars.add (temp_decl);
+                               emit_temp_var (temp_decl);
 
                                var ctemp = get_variable_cexpression (temp_decl.name);
                                var cinit = new CCodeAssignment (ctemp, (CCodeExpression) expr.inner.ccodenode);
@@ -4695,7 +4541,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                /* (tmp = var, var = null, tmp) */
                var ccomma = new CCodeCommaExpression ();
                var temp_decl = get_temp_variable (expr.value_type, true, expr, false);
-               temp_vars.add (temp_decl);
+               emit_temp_var (temp_decl);
                var cvar = get_variable_cexpression (temp_decl.name);
 
                ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode));
@@ -4713,7 +4559,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        var lbe = (BinaryExpression) expr.left;
 
                        var temp_decl = get_temp_variable (lbe.right.value_type, true, null, false);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        var cvar = get_variable_cexpression (temp_decl.name);
                        var ccomma = new CCodeCommaExpression ();
                        var clbe = (CCodeBinaryExpression) lbe.ccodenode;
@@ -5095,7 +4941,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                // treat void* special to not leak memory with void* method parameters
                        } else if (requires_destroy (expression_type)) {
                                var decl = get_temp_variable (expression_type, true, expression_type, false);
-                               temp_vars.add (decl);
+                               emit_temp_var (decl);
                                temp_ref_vars.insert (0, decl);
                                cexpr = new CCodeAssignment (get_variable_cexpression (decl.name), cexpr);
 
@@ -5105,7 +4951,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        ccomma.append_expression (cexpr);
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
                                                var len_decl = new LocalVariable (int_type.copy (), get_array_length_cname (decl.name, dim));
-                                               temp_vars.add (len_decl);
+                                               emit_temp_var (len_decl);
                                                ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (len_decl.name), get_array_length_cexpression (expr, dim)));
                                        }
                                        ccomma.append_expression (get_variable_cexpression (decl.name));
@@ -5115,9 +4961,9 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        ccomma.append_expression (cexpr);
 
                                        var target_decl = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (decl.name));
-                                       temp_vars.add (target_decl);
+                                       emit_temp_var (target_decl);
                                        var target_destroy_notify_decl = new LocalVariable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")), get_delegate_target_destroy_notify_cname (decl.name));
-                                       temp_vars.add (target_destroy_notify_decl);
+                                       emit_temp_var (target_destroy_notify_decl);
                                        CCodeExpression target_destroy_notify;
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (target_decl.name), get_delegate_target_cexpression (expr, out target_destroy_notify)));
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (target_destroy_notify_decl.name), target_destroy_notify));
@@ -5136,7 +4982,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                if (gvalue_boxing) {
                        // implicit conversion to GValue
                        var decl = get_temp_variable (target_type, true, target_type);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ccomma = new CCodeCommaExpression ();
 
@@ -5228,7 +5074,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
                        } else {
                                var decl = get_temp_variable (expression_type, expression_type.value_owned, expression_type, false);
-                               temp_vars.add (decl);
+                               emit_temp_var (decl);
 
                                var ccomma = new CCodeCommaExpression ();
                                ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (decl.name), cexpr));
@@ -5350,7 +5196,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (ma.inner.target_type, true, null, false);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance));
                                        ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
 
@@ -5371,7 +5217,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                CCodeExpression rv;
                if (array_type != null && !prop.no_array_length) {
                        var temp_var = get_temp_variable (prop.property_type, true, null, false);
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
                        var ccomma = new CCodeCommaExpression ();
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr));
                        ccall.add_argument (get_variable_cexpression (temp_var.name));
@@ -5437,7 +5283,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                }
                var temp_decl = get_temp_variable (address_of_type, true, null, false);
                var ctemp = get_variable_cexpression (temp_decl.name);
-               temp_vars.add (temp_decl);
+               emit_temp_var (temp_decl);
                ccomma.append_expression (new CCodeAssignment (ctemp, ce));
                ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
                return ccomma;
@@ -5509,19 +5355,19 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                return null;
        }
        
-       private CCodeStatement? create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) {
+       private void create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) {
                if (check_return_type) {
-                       return create_type_check_statement (prop, prop.property_type, t, non_null, var_name);
+                       create_type_check_statement (prop, prop.property_type, t, non_null, var_name);
                } else {
-                       return create_type_check_statement (prop, new VoidType (), t, non_null, var_name);
+                       create_type_check_statement (prop, new VoidType (), t, non_null, var_name);
                }
        }
 
-       public CCodeStatement? create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
+       public void create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
                var ccheck = new CCodeFunctionCall ();
 
                if (!context.assert) {
-                       return null;
+                       return;
                } else if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
                        var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (t)));
                        ctype_check.add_argument (new CCodeIdentifier (var_name));
@@ -5534,10 +5380,10 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
                        ccheck.add_argument (cexpr);
                } else if (!non_null) {
-                       return null;
+                       return;
                } else if (t == glist_type || t == gslist_type) {
                        // NULL is empty list
-                       return null;
+                       return;
                } else {
                        var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
                        ccheck.add_argument (cnonnull);
@@ -5557,11 +5403,11 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        if (cdefault != null) {
                                ccheck.add_argument (cdefault);
                        } else {
-                               return null;
+                               return;
                        }
                }
                
-               return new CCodeExpressionStatement (ccheck);
+               ccode.add_expression (ccheck);
        }
 
        public int get_param_pos (double param_pos, bool ellipsis = false) {
@@ -5590,12 +5436,12 @@ public class Vala.CCodeBaseModule : CodeGenerator {
        public override void visit_class (Class cl) {
        }
 
-       public CCodeStatement create_postcondition_statement (Expression postcondition) {
+       public void create_postcondition_statement (Expression postcondition) {
                var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_warn_if_fail"));
 
                cassert.add_argument ((CCodeExpression) postcondition.ccodenode);
 
-               return new CCodeExpressionStatement (cassert);
+               ccode.add_expression (cassert);
        }
 
        public virtual bool is_gobject_property (Property prop) {
@@ -5707,13 +5553,11 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                        }
                }
 
-               append_temp_decl (cfrag, temp_vars);
-               temp_vars.clear ();
-
                pop_context ();
 
-               cfile.add_function_declaration (function);
                function.block = cblock;
+
+               cfile.add_function_declaration (function);
                cfile.add_function (function);
        }
 
@@ -5789,7 +5633,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
                return new CCodeConstant ("");
        }
 
-       public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) {
+       public virtual void add_simple_check (CodeNode node, bool always_fails = false) {
        }
 }
 
index 49d868b5c1888cffdc9e44d5c97ba1afbe108c65..0793d3374b7e149061818da98179ee491a85dc98 100644 (file)
@@ -26,24 +26,22 @@ using GLib;
 
 public class Vala.CCodeControlFlowModule : CCodeMethodModule {
        public override void visit_if_statement (IfStatement stmt) {
+               ccode.open_if ((CCodeExpression) stmt.condition.ccodenode);
+
                stmt.true_statement.emit (this);
+
                if (stmt.false_statement != null) {
+                       ccode.add_else ();
                        stmt.false_statement.emit (this);
                }
 
-               if (stmt.false_statement != null) {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
-               } else {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
-               }
-               
-               create_temp_decl (stmt, stmt.condition.temp_vars);
+               ccode.close ();
        }
 
        void visit_string_switch_statement (SwitchStatement stmt) {
                // we need a temporary variable to save the property value
                var temp_var = get_temp_variable (stmt.expression.value_type, stmt.expression.value_type.value_owned, stmt, false);
-               stmt.expression.add_temp_var (temp_var);
+               emit_temp_var (temp_var);
 
                var ctemp = get_variable_cexpression (temp_var.name);
                var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
@@ -52,9 +50,6 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
                free_call.add_argument (ctemp);
 
-               var cswitchblock = new CCodeFragment ();
-               stmt.ccodenode = cswitchblock;
-
                var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
                var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
                cquark.add_argument (ctemp);
@@ -62,7 +57,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
 
                temp_var = get_temp_variable (gquark_type);
-               stmt.expression.add_temp_var (temp_var);
+               emit_temp_var (temp_var);
 
                int label_count = 0;
 
@@ -72,48 +67,43 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        }
 
                        foreach (SwitchLabel label in section.get_labels ()) {
+                               label.expression.emit (this);
                                var cexpr = (CCodeExpression) label.expression.ccodenode;
 
                                if (is_constant_ccode_expression (cexpr)) {
                                        var cname = "%s_label%d".printf (temp_var.name, label_count++);
-                                       var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
 
-                                       cdecl.modifiers = CCodeModifiers.STATIC;
-                                       cdecl.add_declarator (new CCodeVariableDeclarator (cname, czero));
-
-                                       cswitchblock.append (cdecl);
+                                       ccode.add_declaration (gquark_type.get_cname (), new CCodeVariableDeclarator (cname, czero), CCodeModifiers.STATIC);
                                }
                        }
                }
 
-               cswitchblock.append (new CCodeExpressionStatement (cinit));
+               ccode.add_expression (cinit);
 
                ctemp = get_variable_cexpression (temp_var.name);
                cinit = new CCodeAssignment (ctemp, ccond);
 
-               cswitchblock.append (new CCodeExpressionStatement (cinit));
-               create_temp_decl (stmt, stmt.expression.temp_vars);
+               ccode.add_expression (cinit);
 
                if (stmt.expression.value_type.value_owned) {
                        // free owned string
-                       cswitchblock.append (new CCodeExpressionStatement (free_call));
+                       ccode.add_expression (free_call);
                }
 
-               List<Statement> default_statements = null;
+               SwitchSection default_section = null;
                label_count = 0;
 
-               // generate nested if statements                
-               CCodeStatement ctopstmt = null;
-               CCodeIfStatement coldif = null;
+               int n = 0;
 
                foreach (SwitchSection section in stmt.get_sections ()) {
                        if (section.has_default_label ()) {
-                               default_statements = section.get_statements ();
+                               default_section = section;
                                continue;
                        }
 
                        CCodeBinaryExpression cor = null;
                        foreach (SwitchLabel label in section.get_labels ()) {
+                               label.expression.emit (this);
                                var cexpr = (CCodeExpression) label.expression.ccodenode;
 
                                if (is_constant_ccode_expression (cexpr)) {
@@ -140,119 +130,86 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                                }
                        }
 
-                       var cblock = new CCodeBlock ();
-                       foreach (CodeNode body_stmt in section.get_statements ()) {
-                               if (body_stmt.ccodenode is CCodeFragment) {
-                                       foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
-                                               cblock.add_statement (cstmt);
-                                       }
-                               } else {
-                                       cblock.add_statement (body_stmt.ccodenode);
-                               }
+                       if (n > 0) {
+                               ccode.else_if (cor);
+                       } else {
+                               ccode.open_if (cor);
                        }
 
-                       var cswitch = new CCodeSwitchStatement (new CCodeConstant ("0"));
-                       cswitch.add_statement (new CCodeLabel ("default"));
-                       cswitch.add_statement (cblock);
-                       var cif = new CCodeIfStatement (cor, cswitch);
+                       ccode.open_switch (new CCodeConstant ("0"));
+                       ccode.add_default ();
 
-                       if (coldif != null) {
-                               coldif.false_statement = cif;
-                       } else {
-                               ctopstmt = cif;
-                       }
+                       section.emit (this);
+
+                       ccode.close ();
 
-                       coldif = cif;
+                       n++;
                }
        
-               if (default_statements != null) {
-                       var cblock = new CCodeBlock ();
-                       foreach (CodeNode body_stmt in default_statements) {
-                               cblock.add_statement (body_stmt.ccodenode);
+               if (default_section != null) {
+                       if (n > 0) {
+                               ccode.add_else ();
                        }
 
-                       var cswitch = new CCodeSwitchStatement (new CCodeConstant ("0"));
-                       cswitch.add_statement (new CCodeLabel ("default"));
-                       cswitch.add_statement (cblock);
+                       ccode.open_switch (new CCodeConstant ("0"));
+                       ccode.add_default ();
 
-                       if (coldif == null) {
-                               // there is only one section and that section
-                               // contains a default label
-                               ctopstmt = cswitch;
-                       } else {
-                               coldif.false_statement = cswitch;
-                       }
+                       default_section.emit (this);
+
+                       ccode.close ();
                }
-       
-               cswitchblock.append (ctopstmt);
+
+               ccode.close ();
        }
 
        public override void visit_switch_statement (SwitchStatement stmt) {
-               foreach (SwitchSection section in stmt.get_sections ()) {
-                       section.emit (this);
-               }
-
                if (stmt.expression.value_type.compatible (string_type)) {
                        visit_string_switch_statement (stmt);
                        return;
                }
 
-               var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
-               stmt.ccodenode = cswitch;
+               ccode.open_switch ((CCodeExpression) stmt.expression.ccodenode);
 
                foreach (SwitchSection section in stmt.get_sections ()) {
                        if (section.has_default_label ()) {
-                               cswitch.add_statement (new CCodeLabel ("default"));
-                               var cdefaultblock = new CCodeBlock ();
-                               cswitch.add_statement (cdefaultblock);
-                               foreach (CodeNode default_stmt in section.get_statements ()) {
-                                       cdefaultblock.add_statement (default_stmt.ccodenode);
-                               }
-                               continue;
+                               ccode.add_default ();
                        }
-
-                       foreach (SwitchLabel label in section.get_labels ()) {
-                               cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
-                       }
-
-                       cswitch.add_statement (section.ccodenode);
+                       section.emit (this);
                }
-               
-               create_temp_decl (stmt, stmt.expression.temp_vars);
+
+               ccode.close ();
        }
 
        public override void visit_switch_label (SwitchLabel label) {
+               if (((SwitchStatement) label.section.parent_node).expression.value_type.compatible (string_type)) {
+                       return;
+               }
+
                if (label.expression != null) {
                        label.expression.emit (this);
 
                        visit_end_full_expression (label.expression);
+
+                       ccode.add_case ((CCodeExpression) label.expression.ccodenode);
                }
        }
 
        public override void visit_loop (Loop stmt) {
-               stmt.body.emit (this);
-
                if (context.profile == Profile.GOBJECT) {
-                       stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("TRUE"), (CCodeStatement) stmt.body.ccodenode);
+                       ccode.open_while (new CCodeConstant ("TRUE"));
                } else {
                        cfile.add_include ("stdbool.h");
-                       stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("true"), (CCodeStatement) stmt.body.ccodenode);
+                       ccode.open_while (new CCodeConstant ("true"));
                }
-       }
 
-       public override void visit_foreach_statement (ForeachStatement stmt) {
                stmt.body.emit (this);
 
-               visit_block (stmt);
+               ccode.close ();
+       }
 
-               var cblock = new CCodeBlock ();
-               // sets #line
-               stmt.ccodenode = cblock;
+       public override void visit_foreach_statement (ForeachStatement stmt) {
+               ccode.open_block ();
 
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, stmt.collection.temp_vars);
-               cblock.add_statement (cfrag);
-               
                var collection_backup = stmt.collection_variable;
                var collection_type = collection_backup.variable_type.copy ();
 
@@ -264,20 +221,15 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                if (current_method != null && current_method.coroutine) {
                        closure_struct.add_field (collection_type.get_cname (), collection_backup.name);
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode)));
                } else {
-                       var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
-                       var ccolvardecl = new CCodeVariableDeclarator (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
-                       ccolvardecl.line = cblock.line;
-                       ccoldecl.add_declarator (ccolvardecl);
-                       cblock.add_statement (ccoldecl);
+                       var ccolvardecl = new CCodeVariableDeclarator (collection_backup.name);
+                       ccode.add_declaration (collection_type.get_cname (), ccolvardecl);
                }
+               ccode.add_expression (new CCodeAssignment (get_variable_cexpression (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode));
                
                if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
                        // exception handling
-                       cfrag = new CCodeFragment ();
-                       add_simple_check (stmt.collection, cfrag);
-                       cblock.add_statement (cfrag);
+                       add_simple_check (stmt.collection);
                }
 
                if (stmt.collection.value_type is ArrayType) {
@@ -288,24 +240,24 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        // store array length for use by _vala_array_free
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field ("int", get_array_length_cname (collection_backup.name, 1));
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (collection_backup.name, 1)), array_len)));
                        } else {
-                               var clendecl = new CCodeDeclaration ("int");
-                               clendecl.add_declarator (new CCodeVariableDeclarator (get_array_length_cname (collection_backup.name, 1), array_len));
-                               cblock.add_statement (clendecl);
+                               ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname (collection_backup.name, 1)));
                        }
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (collection_backup.name, 1)), array_len));
 
                        var it_name = (stmt.variable_name + "_it");
                
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field ("int", it_name);
                        } else {
-                               var citdecl = new CCodeDeclaration ("int");
-                               citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-                               cblock.add_statement (citdecl);
+                               ccode.add_declaration ("int", new CCodeVariableDeclarator (it_name));
                        }
-                       
-                       var cbody = new CCodeBlock ();
+
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len);
+
+                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0")),
+                                          ccond,
+                                          new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1"))));
 
                        CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (collection_backup.name), get_variable_cexpression (it_name));
 
@@ -313,19 +265,12 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        element_type.value_owned = false;
                        element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
 
-                       cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name);
-                               cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)));
                        } else {
-                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                               cdecl.add_declarator (new CCodeVariableDeclarator (stmt.variable_name, element_expr));
-                               cbody.add_statement (cdecl);
+                               ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name));
                        }
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr));
 
                        // add array length variable for stacked arrays
                        if (stmt.type_reference is ArrayType) {
@@ -333,23 +278,16 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                                for (int dim = 1; dim <= inner_array_type.rank; dim++) {
                                        if (current_method != null && current_method.coroutine) {
                                                closure_struct.add_field ("int", get_array_length_cname (stmt.variable_name, dim));
-                                               cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (stmt.variable_name, dim)), new CCodeConstant ("-1"))));
+                                               ccode.add_expression (new CCodeAssignment (get_variable_cexpression (get_array_length_cname (stmt.variable_name, dim)), new CCodeConstant ("-1")));
                                        } else {
-                                               var cdecl = new CCodeDeclaration ("int");
-                                               cdecl.add_declarator (new CCodeVariableDeclarator (get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
-                                               cbody.add_statement (cdecl);
+                                               ccode.add_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
                                        }
                                }
                        }
 
-                       cbody.add_statement (stmt.body.ccodenode);
-                       
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len);
+                       stmt.body.emit (this);
 
-                       var cfor = new CCodeForStatement (ccond, cbody);
-                       cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0")));
-                       cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1"))));
-                       cblock.add_statement (cfor);
+                       ccode.close ();
                } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
                        // iterating over a GList or GSList
 
@@ -358,14 +296,14 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (collection_type.get_cname (), it_name);
                        } else {
-                               var citdecl = new CCodeDeclaration (collection_type.get_cname ());
-                               var citvardecl = new CCodeVariableDeclarator (it_name);
-                               citvardecl.line = cblock.line;
-                               citdecl.add_declarator (citvardecl);
-                               cblock.add_statement (citdecl);
+                               ccode.add_declaration (collection_type.get_cname (), new CCodeVariableDeclarator (it_name));
                        }
                        
-                       var cbody = new CCodeBlock ();
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL"));
+
+                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name)),
+                                          ccond,
+                                          new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
 
                        CCodeExpression element_expr = new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "data");
 
@@ -380,32 +318,16 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        element_expr = convert_from_generic_pointer (element_expr, element_data_type);
                        element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
 
-                       cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name);
-                               cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)));
                        } else {
-                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                               var cvardecl = new CCodeVariableDeclarator (stmt.variable_name, element_expr);
-                               cvardecl.line = cblock.line;
-                               cdecl.add_declarator (cvardecl);
-                               cbody.add_statement (cdecl);
+                               ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name));
                        }
-                       
-                       cbody.add_statement (stmt.body.ccodenode);
-                       
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL"));
-                       
-                       var cfor = new CCodeForStatement (ccond, cbody);
-                       
-                       cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name)));
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr));
 
-                       cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
-                       cblock.add_statement (cfor);
+                       stmt.body.emit (this);
+
+                       ccode.close ();
                } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
                        // iterating over a GValueArray
 
@@ -414,14 +336,14 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (uint_type.get_cname (), arr_index);
                        } else {
-                               var citdecl = new CCodeDeclaration (uint_type.get_cname ());
-                               var citvardecl = new CCodeVariableDeclarator (arr_index);
-                               citvardecl.line = cblock.line;
-                               citdecl.add_declarator (citvardecl);
-                               cblock.add_statement (citdecl);
+                               ccode.add_declaration (uint_type.get_cname (), new CCodeVariableDeclarator (arr_index));
                        }
 
-                       var cbody = new CCodeBlock ();
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values"));
+
+                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")),
+                                          ccond,
+                                          new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
 
                        var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth"));
                        get_item.add_argument (get_variable_cexpression (collection_backup.name));
@@ -433,56 +355,39 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
                                element_expr = get_ref_cexpression (stmt.type_reference, element_expr, null, new StructValueType (gvalue_type));
                        }
 
-                       cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
                        if (current_method != null && current_method.coroutine) {
                                closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name);
-                               cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)));
                        } else {
-                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                               var cvardecl = new CCodeVariableDeclarator (stmt.variable_name, element_expr);
-                               cvardecl.line = cblock.line;
-                               cdecl.add_declarator (cvardecl);
-                               cbody.add_statement (cdecl);
+                               ccode.add_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name));
                        }
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr));
 
-                       cbody.add_statement (stmt.body.ccodenode);
-
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values"));
-
-                       var cfor = new CCodeForStatement (ccond, cbody);
-
-                       cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")));
+                       stmt.body.emit (this);
 
-                       cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
-
-                       cblock.add_statement (cfor);
+                       ccode.close ();
                }
 
                foreach (LocalVariable local in stmt.get_local_variables ()) {
                        if (requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
-                               var cunref = new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
-                               cunref.line = cblock.line;
-                               cblock.add_statement (cunref);
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
+
+               ccode.close ();
        }
 
        public override void visit_break_statement (BreakStatement stmt) {
-               stmt.ccodenode = new CCodeBreakStatement ();
+               append_local_free (current_symbol, true);
 
-               create_local_free (stmt, true);
+               ccode.add_break ();
        }
 
        public override void visit_continue_statement (ContinueStatement stmt) {
-               stmt.ccodenode = new CCodeContinueStatement ();
+               append_local_free (current_symbol, true);
 
-               create_local_free (stmt, true);
+               ccode.add_continue ();
        }
 }
 
index bbe085f88fcc44c0ac1b05e5dde3ca5069758bc8..fbdbbe5a90a53986926ffe9bfb0018e3e0a0fdc5 100644 (file)
@@ -69,7 +69,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                                // instance expression has side-effects
                                                // store in temp. variable
                                                var temp_var = get_temp_variable (expr.inner.value_type, true, null, false);
-                                               temp_vars.add (temp_var);
+                                               emit_temp_var (temp_var);
                                                var ctemp = get_variable_cexpression (temp_var.name);
                                                inst = new CCodeAssignment (ctemp, pub_inst);
                                                expr.inner.ccodenode = ctemp;
@@ -264,7 +264,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                                        var ccomma = new CCodeCommaExpression ();
 
                                                        var temp_var = get_temp_variable (expr.inner.target_type, true, null, false);
-                                                       temp_vars.add (temp_var);
+                                                       emit_temp_var (temp_var);
                                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), pub_inst));
                                                        ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
 
@@ -281,7 +281,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                        var ccomma = new CCodeCommaExpression ();
                                        var temp_var = get_temp_variable (base_property.get_accessor.value_type);
                                        var ctemp = get_variable_cexpression (temp_var.name);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
                                        ccomma.append_expression (ccall);
                                        ccomma.append_expression (ctemp);
@@ -292,7 +292,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
                                                        var temp_var = get_temp_variable (int_type);
                                                        var ctemp = get_variable_cexpression (temp_var.name);
-                                                       temp_vars.add (temp_var);
+                                                       emit_temp_var (temp_var);
                                                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
                                                        expr.append_array_size (ctemp);
                                                }
@@ -301,7 +301,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                                if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
                                                        var temp_var = get_temp_variable (new PointerType (new VoidType ()));
                                                        var ctemp = get_variable_cexpression (temp_var.name);
-                                                       temp_vars.add (temp_var);
+                                                       emit_temp_var (temp_var);
                                                        ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
                                                        expr.delegate_target = ctemp;
                                                }
@@ -332,7 +332,7 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                var ccomma = new CCodeCommaExpression ();
                                var temp_var = get_temp_variable (expr.value_type);
                                var ctemp = get_variable_cexpression (temp_var.name);
-                               temp_vars.add (temp_var);
+                               emit_temp_var (temp_var);
                                ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
                                ccall.add_argument (new CCodeConstant ("NULL"));
                                ccomma.append_expression (ccall);
index 5a01c918304e0d75dc202271d8a83b1bbd3b3f41..f1dd34212edc1c90ec906022db711e119f3f902b 100644 (file)
@@ -200,7 +200,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (ma.inner.target_type, true, null, false);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance));
                                        ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
 
@@ -353,14 +353,14 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                        if (param.array_length_type != null) {
                                                                if (param.direction == ParameterDirection.OUT) {
                                                                        var temp_array_length = get_temp_variable (new CType (param.array_length_type));
-                                                                       temp_vars.add (temp_array_length);
+                                                                       emit_temp_var (temp_array_length);
                                                                        array_length_expr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_array_length.name));
 
                                                                        var comma = new CCodeCommaExpression ();
                                                                        LocalVariable? temp_result = null;
                                                                        if (!(m.return_type is VoidType)) {
                                                                                temp_result = get_temp_variable (m.return_type);
-                                                                               temp_vars.add (temp_result);
+                                                                               emit_temp_var (temp_result);
                                                                                ccall_expr = new CCodeAssignment (get_variable_cexpression (temp_result.name), ccall_expr);
                                                                        }
 
@@ -430,7 +430,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                var ccomma = new CCodeCommaExpression ();
 
                                                var temp_decl = get_temp_variable (arg.value_type, true, null, false);
-                                               temp_vars.add (temp_decl);
+                                               emit_temp_var (temp_decl);
                                                ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), cexpr));
 
                                                cexpr = get_variable_cexpression (temp_decl.name);
@@ -451,7 +451,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                var ccomma = new CCodeCommaExpression ();
 
                                                var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned);
-                                               temp_vars.add (temp_var);
+                                               emit_temp_var (temp_var);
                                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name));
 
                                                if (param.direction == ParameterDirection.REF) {
@@ -468,14 +468,14 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                                        ccomma.append_expression (ccall_expr);
                                                } else {
                                                        ret_temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
-                                                       temp_vars.add (ret_temp_var);
+                                                       emit_temp_var (ret_temp_var);
                                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (ret_temp_var.name), ccall_expr));
                                                }
 
                                                var cassign_comma = new CCodeCommaExpression ();
 
                                                var assign_temp_var = get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned, null, false);
-                                               temp_vars.add (assign_temp_var);
+                                               emit_temp_var (assign_temp_var);
 
                                                cassign_comma.append_expression (new CCodeAssignment (get_variable_cexpression (assign_temp_var.name), transform_expression (get_variable_cexpression (temp_var.name), param.variable_type, unary.inner.value_type, arg)));
 
@@ -538,7 +538,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        var temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
                                        var temp_ref = get_variable_cexpression (temp_var.name);
 
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
 
                                        ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
 
@@ -557,7 +557,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        }
                                        var temp_ref = get_variable_cexpression (temp_var.name);
 
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
 
                                        out_arg_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -573,7 +573,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                var temp_var = get_temp_variable (new PointerType (new VoidType ()));
                                var temp_ref = get_variable_cexpression (temp_var.name);
 
-                               temp_vars.add (temp_var);
+                               emit_temp_var (temp_var);
 
                                out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -583,7 +583,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        temp_var = get_temp_variable (new DelegateType ((Delegate) context.root.scope.lookup ("GLib").scope.lookup ("DestroyNotify")));
                                        temp_ref = get_variable_cexpression (temp_var.name);
 
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
 
                                        out_arg_map.set (get_param_pos (m.cdelegate_target_parameter_position + 0.01), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -602,7 +602,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        var temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
                                        var temp_ref = get_variable_cexpression (temp_var.name);
 
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
 
                                        ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
 
@@ -615,7 +615,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                        var temp_var = get_temp_variable (int_type);
                                        var temp_ref = get_variable_cexpression (temp_var.name);
 
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
 
                                        out_arg_map.set (get_param_pos (deleg.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -631,7 +631,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                                var temp_var = get_temp_variable (new PointerType (new VoidType ()));
                                var temp_ref = get_variable_cexpression (temp_var.name);
 
-                               temp_vars.add (temp_var);
+                               emit_temp_var (temp_var);
 
                                out_arg_map.set (get_param_pos (deleg.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -688,7 +688,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        var temp_var = get_temp_variable (itype.get_return_type ());
                        var temp_ref = get_variable_cexpression (temp_var.name);
 
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
 
                        out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
@@ -746,20 +746,13 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                }
 
                if (expr.is_yield_expression) {
-                       if (pre_statement_fragment == null) {
-                               pre_statement_fragment = new CCodeFragment ();
-                       }
-
                        // set state before calling async function to support immediate callbacks
                        int state = next_coroutine_state++;
 
-                       state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
-                       state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state)));
-
-                       pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
-                       pre_statement_fragment.append (new CCodeExpressionStatement (async_call));
-                       pre_statement_fragment.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-                       pre_statement_fragment.append (new CCodeLabel ("_state_%d".printf (state)));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())));
+                       ccode.add_expression (async_call);
+                       ccode.add_return (new CCodeConstant ("FALSE"));
+                       ccode.add_label ("_state_%d".printf (state));
                }
 
                if (m is ArrayResizeMethod) {
@@ -771,7 +764,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                        var temp_decl = get_temp_variable (int_type);
                        var temp_ref = get_variable_cexpression (temp_decl.name);
 
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
 
                        /* memset needs string.h */
                        cfile.add_include ("string.h");
index 4a6e805e93dbe87e79e3b75c4e8eb4e12ea2d0c2..89d216f2b19f41bdb94a55e27c5cca2079409854 100644 (file)
@@ -129,33 +129,31 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                }
        }
 
-       public CCodeStatement complete_async () {
-               var complete_block = new CCodeBlock ();
+       public void complete_async () {
+               var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_");
+               var zero = new CCodeConstant ("0");
+               var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero);
+               ccode.open_if (state_is_zero);
 
-               var direct_block = new CCodeBlock ();
-               var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
                var async_result_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_async_result");
-               direct_call.add_argument (async_result_expr);
-               direct_block.add_statement (new CCodeExpressionStatement (direct_call));
 
-               var idle_block = new CCodeBlock ();
                var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete_in_idle"));
                idle_call.add_argument (async_result_expr);
-               idle_block.add_statement (new CCodeExpressionStatement (idle_call));
+               ccode.add_expression (idle_call);
 
-               var state = new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_");
-               var zero = new CCodeConstant ("0");
-               var state_is_zero = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, state, zero);
-               var dispatch = new CCodeIfStatement (state_is_zero, idle_block, direct_block);
-               complete_block.add_statement (dispatch);
+               ccode.add_else ();
+
+               var direct_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_complete"));
+               direct_call.add_argument (async_result_expr);
+               ccode.add_expression (direct_call);
+
+               ccode.close ();
 
                var unref = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
                unref.add_argument (async_result_expr);
-               complete_block.add_statement (new CCodeExpressionStatement (unref));
-
-               complete_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+               ccode.add_expression (unref);
 
-               return complete_block;
+               ccode.add_return (new CCodeConstant ("FALSE"));
        }
 
        public override void generate_method_declaration (Method m, CCodeFile decl_space) {
@@ -206,34 +204,34 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                }
        }
 
-       void register_plugin_types (CCodeFragment module_init_fragment, Symbol sym, Set<Symbol> registered_types) {
+       void register_plugin_types (Symbol sym, Set<Symbol> registered_types) {
                var ns = sym as Namespace;
                var cl = sym as Class;
                var iface = sym as Interface;
                if (ns != null) {
                        foreach (var ns_ns in ns.get_namespaces ()) {
-                               register_plugin_types (module_init_fragment, ns_ns, registered_types);
+                               register_plugin_types (ns_ns, registered_types);
                        }
                        foreach (var ns_cl in ns.get_classes ()) {
-                               register_plugin_types (module_init_fragment, ns_cl, registered_types);
+                               register_plugin_types (ns_cl, registered_types);
                        }
                        foreach (var ns_iface in ns.get_interfaces ()) {
-                               register_plugin_types (module_init_fragment, ns_iface, registered_types);
+                               register_plugin_types (ns_iface, registered_types);
                        }
                } else if (cl != null) {
-                       register_plugin_type (module_init_fragment, cl, registered_types);
+                       register_plugin_type (cl, registered_types);
                        foreach (var cl_cl in cl.get_classes ()) {
-                               register_plugin_types (module_init_fragment, cl_cl, registered_types);
+                               register_plugin_types (cl_cl, registered_types);
                        }
                } else if (iface != null) {
-                       register_plugin_type (module_init_fragment, iface, registered_types);
+                       register_plugin_type (iface, registered_types);
                        foreach (var iface_cl in iface.get_classes ()) {
-                               register_plugin_types (module_init_fragment, iface_cl, registered_types);
+                               register_plugin_types (iface_cl, registered_types);
                        }
                }
        }
 
-       void register_plugin_type (CCodeFragment module_init_fragment, ObjectTypeSymbol type_symbol, Set<Symbol> registered_types) {
+       void register_plugin_type (ObjectTypeSymbol type_symbol, Set<Symbol> registered_types) {
                if (type_symbol.external_package) {
                        return;
                }
@@ -251,13 +249,13 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                        // register base types first
                        foreach (var base_type in cl.get_base_types ()) {
-                               register_plugin_type (module_init_fragment, (ObjectTypeSymbol) base_type.data_type, registered_types);
+                               register_plugin_type ((ObjectTypeSymbol) base_type.data_type, registered_types);
                        }
                }
 
                var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (type_symbol.get_lower_case_cname (null))));
                register_call.add_argument (new CCodeIdentifier (module_init_param_name));
-               module_init_fragment.append (new CCodeExpressionStatement (register_call));
+               ccode.add_expression (register_call);
        }
 
        public override void visit_method (Method m) {
@@ -280,13 +278,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                }
 
                if (m.coroutine) {
-                       state_switch_statement = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"));
-
-                       // initial coroutine state
-                       state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant ("0")));
-                       state_switch_statement.add_statement (new CCodeGotoStatement ("_state_0"));
+                       next_coroutine_state = 1;
                }
-               var current_state_switch = state_switch_statement;
 
                var creturn_type = m.return_type;
                if (m.return_type.is_real_non_null_struct_type ()) {
@@ -328,13 +321,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                        }
                }
 
-               if (m.comment != null) {
-                       cfile.add_type_member_definition (new CCodeComment (m.comment.content));
-               }
-
                CCodeFunction function;
                function = new CCodeFunction (m.get_real_cname ());
-               m.ccodenode = function;
 
                if (m.is_inline) {
                        function.modifiers |= CCodeModifiers.INLINE;
@@ -361,8 +349,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                // generate *_real_* functions for virtual methods
                // also generate them for abstract methods of classes to prevent faulty subclassing
                if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
-                       /* Methods imported from a plain C file don't
-                        * have a body, e.g. Vala.Parser.parse_file () */
                        if (m.body != null) {
                                if (m.coroutine) {
                                        function = new CCodeFunction (m.get_real_cname () + "_co", "gboolean");
@@ -376,22 +362,37 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                        }
                }
 
-               var cinit = new CCodeFragment ();
+               if (m.comment != null) {
+                       cfile.add_type_member_definition (new CCodeComment (m.comment.content));
+               }
+
+               push_function (function);
 
                // generate *_real_* functions for virtual methods
                // also generate them for abstract methods of classes to prevent faulty subclassing
                if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
-                       /* Methods imported from a plain C file don't
-                        * have a body, e.g. Vala.Parser.parse_file () */
                        if (m.body != null) {
                                if (m.coroutine) {
+                                       ccode.open_switch (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"));
+
+                                       // initial coroutine state
+                                       ccode.add_case (new CCodeConstant ("0"));
+                                       ccode.add_goto ("_state_0");
+
+                                       for (int state = 1; state <= m.yield_count; state++) {
+                                               ccode.add_case (new CCodeConstant (state.to_string ()));
+                                               ccode.add_goto ("_state_%d".printf (state));
+                                       }
+
+
                                        // let gcc know that this can't happen
-                                       current_state_switch.add_statement (new CCodeLabel ("default"));
-                                       current_state_switch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached"))));
+                                       ccode.add_default ();
+                                       ccode.add_expression (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached")));
 
-                                       cinit.append (current_state_switch);
+                                       ccode.close ();
 
-                                       cinit.append (new CCodeLabel ("_state_0"));
+                                       // coroutine body
+                                       ccode.add_label ("_state_0");
                                }
 
                                if (m.closure) {
@@ -407,10 +408,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                                                int parent_block_id = get_block_id (parent_closure_block);
 
                                                var parent_data = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id));
-                                               var cdecl = new CCodeDeclaration ("Block%dData*".printf (parent_block_id));
-                                               cdecl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id), parent_data));
-
-                                               cinit.append (cdecl);
+                                               ccode.add_declaration ("Block%dData*".printf (parent_block_id), new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id)));
+                                               ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("_data%d_".printf (parent_block_id)), parent_data));
 
                                                closure_block = parent_closure_block;
                                                block_id = parent_block_id;
@@ -420,10 +419,8 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                                        // as closures have block data parameter
                                        if (m.binding == MemberBinding.INSTANCE) {
                                                var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self");
-                                               var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ()));
-                                               cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself));
-
-                                               cinit.append (cdecl);
+                                               ccode.add_declaration ("%s *".printf (current_class.get_cname ()), new CCodeVariableDeclarator ("self"));
+                                               ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself));
                                        }
                                } else if (m.parent_symbol is Class && !m.coroutine) {
                                        var cl = (Class) m.parent_symbol;
@@ -440,19 +437,14 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                                                var self_target_type = new ObjectType (cl);
                                                CCodeExpression cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
 
-                                               var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-                                               cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself));
-                                       
-                                               cinit.append (cdecl);
+                                               ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+                                               ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself));
                                        } else if (m.binding == MemberBinding.INSTANCE
-                                                  && !(m is CreationMethod)) {
-                                               var ccheckstmt = create_method_type_check_statement (m, creturn_type, cl, true, "self");
-                                               if (ccheckstmt != null) {
-                                                       ccheckstmt.line = function.line;
-                                                       cinit.append (ccheckstmt);
-                                               }
+                                                  && !(m is CreationMethod)) {
+                                               create_method_type_check_statement (m, creturn_type, cl, true, "self");
                                        }
                                }
+
                                foreach (FormalParameter param in m.get_parameters ()) {
                                        if (param.ellipsis) {
                                                break;
@@ -461,11 +453,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                                        if (param.direction != ParameterDirection.OUT) {
                                                var t = param.variable_type.data_type;
                                                if (t != null && t.is_reference_type ()) {
-                                                       var type_check = create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name));
-                                                       if (type_check != null) {
-                                                               type_check.line = function.line;
-                                                               cinit.append (type_check);
-                                                       }
+                                                       create_method_type_check_statement (m, creturn_type, t, !param.variable_type.nullable, get_variable_cname (param.name));
                                                }
                                        } else if (!m.coroutine) {
                                                var t = param.variable_type.data_type;
@@ -477,36 +465,28 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                                                        var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (param.name), new CCodeConstant ("NULL"));
                                                        var if_statement = new CCodeIfStatement (condition, cblock);
-                                                       cinit.append (if_statement);
+                                                       ccode.add_statement (if_statement);
                                                }
                                        }
                                }
 
                                if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
-                                       var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
                                        var vardecl =  new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
                                        vardecl.init0 = true;
-                                       cdecl.add_declarator (vardecl);
-                                       cinit.append (cdecl);
+                                       ccode.add_declaration (m.return_type.get_cname (), vardecl);
                                }
 
                                if (m is CreationMethod) {
                                        if (in_gobject_creation_method) {
-                                               var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) current_type_symbol).get_cname ()));
-                                               cdeclaration.add_declarator (new CCodeVariableDeclarator ("self"));
-
-                                               cinit.append (cdeclaration);
+                                               ccode.add_declaration ("%s *".printf (((Class) current_type_symbol).get_cname ()), new CCodeVariableDeclarator ("self"));
                                        } else if (is_gtypeinstance_creation_method (m)) {
                                                var cl = (Class) m.parent_symbol;
-                                               var cdeclaration = new CCodeDeclaration (cl.get_cname () + "*");
-                                               var cdecl = new CCodeVariableDeclarator ("self");
-                                               cdeclaration.add_declarator (cdecl);
-                                               cinit.append (cdeclaration);
+                                               ccode.add_declaration (cl.get_cname () + "*", new CCodeVariableDeclarator ("self"));
 
                                                if (cl.is_fundamental ()) {
                                                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_create_instance"));
                                                        ccall.add_argument (new CCodeIdentifier ("object_type"));
-                                                       cdecl.initializer = new CCodeCastExpression (ccall, cl.get_cname () + "*");
+                                                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, cl.get_cname () + "*")));
 
                                                        /* type, dup func, and destroy func fields for generic types */
                                                        foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
@@ -517,36 +497,33 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                                                                param_name = new CCodeIdentifier ("%s_type".printf (type_param.name.down ()));
                                                                assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name);
-                                                               cinit.append (new CCodeExpressionStatement (assign));
+                                                               ccode.add_expression (assign);
 
                                                                param_name = new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ()));
                                                                assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name);
-                                                               cinit.append (new CCodeExpressionStatement (assign));
+                                                               ccode.add_expression (assign);
 
                                                                param_name = new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ()));
                                                                assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name);
-                                                               cinit.append (new CCodeExpressionStatement (assign));
+                                                               ccode.add_expression (assign);
                                                        }
                                                }
                                        } else if (current_type_symbol is Class) {
                                                var cl = (Class) m.parent_symbol;
-                                               var cdeclaration = new CCodeDeclaration (cl.get_cname () + "*");
-                                               var cdecl = new CCodeVariableDeclarator ("self");
-                                               cdeclaration.add_declarator (cdecl);
-                                               cinit.append (cdeclaration);
+                                               ccode.add_declaration (cl.get_cname () + "*", new CCodeVariableDeclarator ("self"));
 
                                                if (!((CreationMethod) m).chain_up) {
                                                        // TODO implicitly chain up to base class as in add_object_creation
                                                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
                                                        ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
-                                                       cdecl.initializer = ccall;
+                                                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall));
                                                }
 
                                                if (cl.base_class == null) {
                                                        // derived compact classes do not have fields
                                                        var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (cl.get_lower_case_cname (null))));
                                                        cinitcall.add_argument (new CCodeIdentifier ("self"));
-                                                       cinit.append (new CCodeExpressionStatement (cinitcall));
+                                                       ccode.add_expression (cinitcall);
                                                }
                                        } else {
                                                var st = (Struct) m.parent_symbol;
@@ -557,20 +534,17 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                                                czero.add_argument (new CCodeIdentifier ("self"));
                                                czero.add_argument (new CCodeConstant ("0"));
                                                czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (st.get_cname ())));
-                                               cinit.append (new CCodeExpressionStatement (czero));
+                                               ccode.add_expression (czero);
                                        }
                                }
 
                                if (context.module_init_method == m && in_plugin) {
                                        // GTypeModule-based plug-in, register types
-                                       register_plugin_types (cinit, context.root, new HashSet<Symbol> ());
+                                       register_plugin_types (context.root, new HashSet<Symbol> ());
                                }
 
                                foreach (Expression precondition in m.get_preconditions ()) {
-                                       var check_stmt = create_precondition_statement (m, creturn_type, precondition);
-                                       if (check_stmt != null) {
-                                               cinit.append (check_stmt);
-                                       }
+                                       create_precondition_statement (m, creturn_type, precondition);
                                }
                        }
                }
@@ -585,11 +559,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                        /* Methods imported from a plain C file don't
                         * have a body, e.g. Vala.Parser.parse_file () */
                        if (m.body != null) {
-                               function.block = (CCodeBlock) m.body.ccodenode;
-                               function.block.line = function.line;
-
-                               function.block.prepend_statement (cinit);
-
                                if (current_method_inner_error) {
                                        /* always separate error parameter and inner_error local variable
                                         * as error may be set to NULL but we're always interested in inner errors
@@ -599,61 +568,90 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                                                // no initialization necessary, closure struct is zeroed
                                        } else {
-                                               var cdecl = new CCodeDeclaration ("GError *");
-                                               cdecl.add_declarator (new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
-                                               function.block.add_statement (cdecl);
+                                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
                                        }
                                }
 
                                if (m.coroutine) {
                                        // epilogue
-                                       function.block.add_statement (complete_async ());
+                                       complete_async ();
                                }
 
                                if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
                                        // add dummy return if exit block is known to be unreachable to silence C compiler
                                        if (m.return_block != null && m.return_block.get_predecessors ().size == 0) {
-                                               function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+                                               ccode.add_return (new CCodeIdentifier ("result"));
                                        }
                                }
 
-                               cfile.add_function (function);
-                       } else if (m.is_abstract) {
-                               // generate helpful error message if a sublcass does not implement an abstract method.
-                               // This is only meaningful for subclasses implemented in C since the vala compiler would
-                               // complain during compile time of such en error.
+                               if (m is CreationMethod) {
+                                       if (current_type_symbol is Class) {
+                                               creturn_type = new ObjectType (current_class);
+                                       } else {
+                                               creturn_type = new VoidType ();
+                                       }
+
 
-                               var cblock = new CCodeBlock ();
+                                       if (current_type_symbol is Class && gobject_type != null && current_class.is_subtype_of (gobject_type)
+                                           && current_class.get_type_parameters ().size > 0
+                                           && !((CreationMethod) m).chain_up) {
+                                               var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("__params_it"), new CCodeIdentifier ("__params"));
+                                               var cdofreeparam = new CCodeBlock ();
+                                               cdofreeparam.add_statement (new CCodeExpressionStatement (new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, new CCodeIdentifier ("__params_it"))));
+                                               var cunsetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_unset"));
+                                               cunsetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("__params_it"), "value")));
+                                               cdofreeparam.add_statement (new CCodeExpressionStatement (cunsetcall));
+                                               ccode.add_statement (new CCodeWhileStatement (ccond, cdofreeparam));
+
+                                               var cfreeparams = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
+                                               cfreeparams.add_argument (new CCodeIdentifier ("__params"));
+                                               ccode.add_expression (cfreeparams);
+                                       }
+
+                                       if (current_type_symbol is Class) {
+                                               CCodeExpression cresult = new CCodeIdentifier ("self");
+                                               if (get_custom_creturn_type (m) != null) {
+                                                       cresult = new CCodeCastExpression (cresult, get_custom_creturn_type (m));
+                                               }
 
-                               // add a typecheck statement for "self"
-                               var check_stmt = create_method_type_check_statement (m, creturn_type, current_type_symbol, true, "self");
-                               if (check_stmt != null) {
-                                       cblock.add_statement (check_stmt);
+                                               ccode.add_return (cresult);
+                                       }
                                }
 
-                               // add critical warning that this method should not have been called
-                               var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
-                               type_from_instance_call.add_argument (new CCodeIdentifier ("self"));
-                       
-                               var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
-                               type_name_call.add_argument (type_from_instance_call);
+                               cfile.add_function (ccode);
+                       }
+               }
 
-                               var error_string = "\"Type `%%s' does not implement abstract method `%s'\"".printf (m.get_cname ());
+               if (m.is_abstract) {
+                       // generate helpful error message if a sublcass does not implement an abstract method.
+                       // This is only meaningful for subclasses implemented in C since the vala compiler would
+                       // complain during compile time of such en error.
 
-                               var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
-                               cerrorcall.add_argument (new CCodeConstant (error_string));
-                               cerrorcall.add_argument (type_name_call);
+                       // add a typecheck statement for "self"
+                       create_method_type_check_statement (m, creturn_type, current_type_symbol, true, "self");
 
-                               cblock.add_statement (new CCodeExpressionStatement (cerrorcall));
+                       // add critical warning that this method should not have been called
+                       var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
+                       type_from_instance_call.add_argument (new CCodeIdentifier ("self"));
 
-                               // add return statement
-                               cblock.add_statement (new CCodeReturnStatement (default_value_for_type (creturn_type, false)));
+                       var type_name_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name"));
+                       type_name_call.add_argument (type_from_instance_call);
 
-                               function.block = cblock;
-                               cfile.add_function (function);
-                       }
+                       var error_string = "\"Type `%%s' does not implement abstract method `%s'\"".printf (m.get_cname ());
+
+                       var cerrorcall = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
+                       cerrorcall.add_argument (new CCodeConstant (error_string));
+                       cerrorcall.add_argument (type_name_call);
+
+                       ccode.add_expression (cerrorcall);
+
+                       // add return statement
+                       ccode.add_return (default_value_for_type (creturn_type, false));
+
+                       cfile.add_function (ccode);
                }
 
+
                in_static_or_class_context = false;
 
                pop_context ();
@@ -885,23 +883,13 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
        }
 
        public void generate_vfunc (Method m, DataType return_type, Map<int,CCodeFormalParameter> cparam_map, Map<int,CCodeExpression> carg_map, string suffix = "", int direction = 3) {
+               push_context (new EmitContext ());
+
                string cname = m.get_cname ();
                if (suffix == "_finish" && cname.has_suffix ("_async")) {
                        cname = cname.substring (0, cname.length - "_async".length);
                }
                var vfunc = new CCodeFunction (cname + suffix);
-               if (function != null) {
-                       vfunc.line = function.line;
-               }
-
-               var vblock = new CCodeBlock ();
-
-               foreach (Expression precondition in m.get_preconditions ()) {
-                       var check_stmt = create_precondition_statement (m, return_type, precondition);
-                       if (check_stmt != null) {
-                               vblock.add_statement (check_stmt);
-                       }
-               }
 
                CCodeFunctionCall vcast = null;
                if (m.parent_symbol is Interface) {
@@ -924,47 +912,45 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                generate_cparameters (m, cfile, cparam_map, vfunc, null, carg_map, vcall, direction);
 
-               CCodeStatement cstmt;
+               push_function (vfunc);
+
+               foreach (Expression precondition in m.get_preconditions ()) {
+                       create_precondition_statement (m, return_type, precondition);
+               }
+
                if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) {
-                       cstmt = new CCodeExpressionStatement (vcall);
+                       ccode.add_expression (vcall);
                } else if (m.get_postconditions ().size == 0) {
                        /* pass method return value */
-                       cstmt = new CCodeReturnStatement (vcall);
+                       ccode.add_return (vcall);
                } else {
                        /* store method return value for postconditions */
-                       var cdecl = new CCodeDeclaration (get_creturn_type (m, return_type.get_cname ()));
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("result", vcall));
-                       cstmt = cdecl;
+                       ccode.add_declaration (get_creturn_type (m, return_type.get_cname ()), new CCodeVariableDeclarator ("result"));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), vcall));
                }
-               cstmt.line = vfunc.line;
-               vblock.add_statement (cstmt);
 
                if (m.get_postconditions ().size > 0) {
                        foreach (Expression postcondition in m.get_postconditions ()) {
-                               vblock.add_statement (create_postcondition_statement (postcondition));
+                               create_postcondition_statement (postcondition);
                        }
 
                        if (!(return_type is VoidType)) {
-                               var cret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result"));
-                               cret_stmt.line = vfunc.line;
-                               vblock.add_statement (cret_stmt);
+                               ccode.add_return (new CCodeIdentifier ("result"));
                        }
                }
 
-               vfunc.block = vblock;
-
                cfile.add_function (vfunc);
+
+               pop_context ();
        }
 
-       private CCodeStatement? create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) {
-               if (m.coroutine) {
-                       return null;
-               } else {
-                       return create_type_check_statement (m, return_type, t, non_null, var_name);
+       private void create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) {
+               if (!m.coroutine) {
+                       create_type_check_statement (m, return_type, t, non_null, var_name);
                }
        }
 
-       private CCodeStatement? create_precondition_statement (CodeNode method_node, DataType ret_type, Expression precondition) {
+       private void create_precondition_statement (CodeNode method_node, DataType ret_type, Expression precondition) {
                var ccheck = new CCodeFunctionCall ();
 
                ccheck.add_argument ((CCodeExpression) precondition.ccodenode);
@@ -986,11 +972,11 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                        if (cdefault != null) {
                                ccheck.add_argument (cdefault);
                        } else {
-                               return null;
+                               return;
                        }
                }
                
-               return new CCodeExpressionStatement (ccheck);
+               ccode.add_expression (ccheck);
        }
 
        private TypeSymbol? find_parent_type (Symbol sym) {
@@ -1012,19 +998,9 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
                        return;
                }
 
-               function = (CCodeFunction) m.ccodenode;
-
-               DataType creturn_type;
-               if (current_type_symbol is Class) {
-                       creturn_type = new ObjectType (current_class);
-               } else {
-                       creturn_type = new VoidType ();
-               }
-
                // do not generate _new functions for creation methods of abstract classes
                if (current_type_symbol is Class && !current_class.is_compact && !current_class.is_abstract) {
                        var vfunc = new CCodeFunction (m.get_cname ());
-                       vfunc.line = function.line;
 
                        var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
                        var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
@@ -1047,17 +1023,6 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 
                        cfile.add_function (vfunc);
                }
-
-               if (current_type_symbol is Class) {
-                       CCodeExpression cresult = new CCodeIdentifier ("self");
-                       if (get_custom_creturn_type (m) != null) {
-                               cresult = new CCodeCastExpression (cresult, get_custom_creturn_type (m));
-                       }
-
-                       var creturn = new CCodeReturnStatement ();
-                       creturn.return_expression = cresult;
-                       function.block.add_statement (creturn);
-               }
        }
 }
 
index 04b831c0b9570bc5ab1d44b4de59ad2442765893..51e5d7f8133ee78daaa6a7fb534e86a105e4e03a 100644 (file)
@@ -142,8 +142,8 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
        public override void visit_struct (Struct st) {
                push_context (new EmitContext (st));
 
-               var old_instance_finalize_fragment = instance_finalize_fragment;
-               instance_finalize_fragment = new CCodeFragment ();
+               var old_instance_finalize_context = instance_finalize_context;
+               instance_finalize_context = new EmitContext ();
 
                generate_struct_declaration (st, cfile);
 
@@ -154,6 +154,8 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
                        generate_struct_declaration (st, internal_header_file);
                }
 
+               begin_struct_destroy_function (st);
+
                st.accept_children (this);
 
                if (context.profile == Profile.GOBJECT && !st.is_boolean_type () && !st.is_integer_type () && !st.is_floating_type ()) {
@@ -166,7 +168,7 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
                        add_struct_free_function (st);
                }
 
-               instance_finalize_fragment = old_instance_finalize_fragment;
+               instance_finalize_context = old_instance_finalize_context;
 
                pop_context ();
        }
@@ -294,15 +296,14 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
                        }
                }
 
-               append_temp_decl (cfrag, temp_vars);
-               temp_vars.clear ();
-
                function.block = cblock;
 
                cfile.add_function (function);
        }
 
-       void add_struct_destroy_function (Struct st) {
+       void begin_struct_destroy_function (Struct st) {
+               push_context (instance_finalize_context);
+
                var function = new CCodeFunction (st.get_destroy_function (), "void");
                if (st.access == SymbolAccessibility.PRIVATE) {
                        function.modifiers = CCodeModifiers.STATIC;
@@ -310,13 +311,13 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
 
                function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
 
-               var cblock = new CCodeBlock ();
-
-               cblock.add_statement (instance_finalize_fragment);
+               push_function (function);
 
-               function.block = cblock;
+               pop_context ();
+       }
 
-               cfile.add_function (function);
+       void add_struct_destroy_function (Struct st) {
+               cfile.add_function (instance_finalize_context.ccode);
        }
 }
 
index 93978f1b7aa38a66909280ff73389e2196cf2b02..182ffce3465192717a0b92bb083fb29706372436 100644 (file)
@@ -38,7 +38,7 @@ public class Vala.DovaArrayModule : DovaMethodCallModule {
                        var name_cnode = new CCodeIdentifier (temp_var.name);
                        int i = 0;
 
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
 
                        append_initializer_list (ce, name_cnode, expr.initializer_list, ref i);
 
index 3d21f33e9843d07bdcbc4c6e1dd4991f8693cd08..1219a44e6013437b462850b1bd963c87353a934d 100644 (file)
@@ -102,13 +102,13 @@ public class Vala.DovaAssignmentModule : DovaMemberAccessModule {
                                var lhs_value_type = assignment.left.value_type.copy ();
                                string lhs_temp_name = "_tmp%d_".printf (next_temp_var_id++);
                                var lhs_temp = new LocalVariable (lhs_value_type, "*" + lhs_temp_name);
-                               temp_vars.add (lhs_temp);
+                               emit_temp_var (lhs_temp);
                                outer_ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (lhs_temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, lhs)));
                                lhs = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (lhs_temp_name)));
                        }
 
                        var temp_decl = get_temp_variable (assignment.left.value_type);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), rhs));
                        if (unref_old) {
                                /* unref old value */
index 28aaefffc54640cb0694cd146ea51616d8d42fcd..8c5fe91ff1c4f35d017ebaf0f3a62d9cea7f7bd6 100644 (file)
@@ -30,7 +30,8 @@ public class Vala.DovaBaseModule : CodeGenerator {
                public Symbol? current_symbol;
                public ArrayList<Symbol> symbol_stack = new ArrayList<Symbol> ();
                public TryStatement current_try;
-               public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
+               public CCodeFunction ccode;
+               public ArrayList<CCodeFunction> ccode_stack = new ArrayList<CCodeFunction> ();
                public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
                public int next_temp_var_id;
                public Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
@@ -150,21 +151,15 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
        string? csource_filename;
 
-       public CCodeFragment module_init_fragment;
-       public CCodeFragment instance_init_fragment;
-       public CCodeFragment instance_finalize_fragment;
+       public CCodeFunction ccode { get { return emit_context.ccode; } }
 
-       // code nodes to be inserted before the current statement
-       // used by async method calls in coroutines
-       public CCodeFragment pre_statement_fragment;
-
-       /* all temporary variables */
-       public ArrayList<LocalVariable> temp_vars { get { return emit_context.temp_vars; } }
        /* temporary variables that own their content */
        public ArrayList<LocalVariable> temp_ref_vars { get { return emit_context.temp_ref_vars; } }
        /* (constant) hash table with all reserved identifiers in the generated code */
        Set<string> reserved_identifiers;
 
+       public List<Field> static_fields = new ArrayList<Field> ();
+
        public int next_temp_var_id {
                get { return emit_context.next_temp_var_id; }
                set { emit_context.next_temp_var_id = value; }
@@ -276,7 +271,6 @@ public class Vala.DovaBaseModule : CodeGenerator {
                header_file.is_header = true;
 
                cfile = new CCodeFile ();
-               module_init_fragment = new CCodeFragment ();
 
                if (context.nostdpkg) {
                        header_file.add_include ("dova-types.h");
@@ -331,6 +325,16 @@ public class Vala.DovaBaseModule : CodeGenerator {
                }
        }
 
+       public void push_function (CCodeFunction func) {
+               emit_context.ccode_stack.add (ccode);
+               emit_context.ccode = func;
+       }
+
+       public void pop_function () {
+               emit_context.ccode = emit_context.ccode_stack[emit_context.ccode_stack.size - 1];
+               emit_context.ccode_stack.remove_at (emit_context.ccode_stack.size - 1);
+       }
+
        public bool add_symbol_declaration (CCodeFile decl_space, Symbol sym, string name) {
                if (decl_space.add_declaration (name)) {
                        return true;
@@ -458,71 +462,23 @@ public class Vala.DovaBaseModule : CodeGenerator {
        }
 
        public override void visit_field (Field f) {
-               if (f.initializer != null) {
-                       f.initializer.emit (this);
-               }
-
-               var cl = f.parent_symbol as Class;
-
-               CCodeExpression lhs = null;
-
-               string field_ctype = f.variable_type.get_cname ();
-               if (f.is_volatile) {
-                       field_ctype = "volatile " + field_ctype;
-               }
-
-               if (f.binding == MemberBinding.INSTANCE)  {
-                       if (cl != null && f.is_internal_symbol ()) {
-                               var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
-                               priv_call.add_argument (new CCodeIdentifier ("this"));
-                               lhs = new CCodeMemberAccess.pointer (priv_call, f.get_cname ());
-                       } else {
-                               lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("this"), f.get_cname ());
-                       }
-
-                       if (f.initializer != null) {
-                               var rhs = (CCodeExpression) f.initializer.ccodenode;
-
-                               instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
-
-                               append_temp_decl (instance_init_fragment, temp_vars);
-                               temp_vars.clear ();
-                       }
-
-                       if (requires_destroy (f.variable_type) && instance_finalize_fragment != null) {
-                               var this_access = new MemberAccess.simple ("this");
-                               this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
-
-                               var field_st = f.parent_symbol as Struct;
-                               if (field_st != null && !field_st.is_simple_type ()) {
-                                       this_access.ccodenode = new CCodeIdentifier ("(*this)");
-                               } else {
-                                       this_access.ccodenode = new CCodeIdentifier ("this");
-                               }
-
-                               var ma = new MemberAccess (this_access, f.name);
-                               ma.symbol_reference = f;
-                               instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.variable_type, ma)));
-                       }
-               } else {
+               if (f.binding == MemberBinding.STATIC)  {
                        generate_field_declaration (f, cfile);
 
                        if (!f.is_internal_symbol ()) {
                                generate_field_declaration (f, header_file);
                        }
 
-                       lhs = new CCodeIdentifier (f.get_cname ());
-
                        var var_decl = new CCodeVariableDeclarator (f.get_cname ());
                        var_decl.initializer = default_value_for_type (f.variable_type, true);
 
                        if (f.initializer != null) {
-                               var rhs = (CCodeExpression) f.initializer.ccodenode;
-
-                               module_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+                               static_fields.add (f);
+                       }
 
-                               append_temp_decl (module_init_fragment, temp_vars);
-                               temp_vars.clear ();
+                       string field_ctype = f.variable_type.get_cname ();
+                       if (f.is_volatile) {
+                               field_ctype = "volatile " + field_ctype;
                        }
 
                        var var_def = new CCodeDeclaration (field_ctype);
@@ -644,16 +600,6 @@ public class Vala.DovaBaseModule : CodeGenerator {
        public virtual void generate_property_accessor_declaration (PropertyAccessor acc, CCodeFile decl_space) {
        }
 
-       public override void visit_destructor (Destructor d) {
-               d.body.emit (this);
-
-               CCodeFragment cfrag = new CCodeFragment ();
-
-               cfrag.append (d.body.ccodenode);
-
-               d.ccodenode = cfrag;
-       }
-
        public int get_block_id (Block b) {
                int result = block_map[b];
                if (result == 0) {
@@ -663,7 +609,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                return result;
        }
 
-       void capture_parameter (FormalParameter param, CCodeStruct data, CCodeBlock cblock, int block_id, CCodeBlock free_block) {
+       void capture_parameter (FormalParameter param, CCodeStruct data, int block_id, CCodeBlock free_block) {
                generate_type_declaration (param.variable_type, cfile);
 
                var param_type = param.variable_type.copy ();
@@ -682,7 +628,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        param.captured = true;
                }
 
-               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam)));
+               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), get_variable_cname (param.name)), cparam));
 
                if (requires_destroy (param_type)) {
                        var ma = new MemberAccess.simple (param.name);
@@ -695,17 +641,11 @@ public class Vala.DovaBaseModule : CodeGenerator {
        public override void visit_block (Block b) {
                emit_context.push_symbol (b);
 
-               foreach (Statement stmt in b.get_statements ()) {
-                       stmt.emit (this);
-               }
-
                var local_vars = b.get_local_variables ();
-               foreach (LocalVariable local in local_vars) {
-                       local.active = false;
-               }
-
-               var cblock = new CCodeBlock ();
 
+               if (b.parent_node is Block || b.parent_node is SwitchStatement) {
+                       ccode.open_block ();
+               }
 
                if (b.captured) {
                        var parent_block = next_closure_block (b.parent_symbol);
@@ -759,7 +699,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                        var data_decl = new CCodeDeclaration (struct_name + "*");
                        data_decl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (block_id), data_alloc));
-                       cblock.add_statement (data_decl);
+                       ccode.add_statement (data_decl);
 
                        if (parent_block != null) {
                                int parent_block_id = get_block_id (parent_block);
@@ -767,13 +707,13 @@ public class Vala.DovaBaseModule : CodeGenerator {
                                var ref_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_ref"));
                                ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
 
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)));
+                               ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call)));
                        } else if ((current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
                                   (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
                                var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
                                ref_call.add_argument (new CCodeIdentifier ("this"));
 
-                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "this"), ref_call)));
+                               ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "this"), ref_call)));
                        }
 
                        if (b.parent_symbol is Method) {
@@ -782,25 +722,15 @@ public class Vala.DovaBaseModule : CodeGenerator {
                                // parameters are captured with the top-level block of the method
                                foreach (var param in m.get_parameters ()) {
                                        if (param.captured) {
-                                               capture_parameter (param, data, cblock, block_id, free_block);
+                                               capture_parameter (param, data, block_id, free_block);
                                        }
                                }
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               temp_vars.clear ();
-                               cblock.add_statement (cfrag);
                        } else if (b.parent_symbol is PropertyAccessor) {
                                var acc = (PropertyAccessor) b.parent_symbol;
 
                                if (!acc.readable && acc.value_parameter.captured) {
-                                       capture_parameter (acc.value_parameter, data, cblock, block_id, free_block);
+                                       capture_parameter (acc.value_parameter, data, block_id, free_block);
                                }
-
-                               var cfrag = new CCodeFragment ();
-                               append_temp_decl (cfrag, temp_vars);
-                               temp_vars.clear ();
-                               cblock.add_statement (cfrag);
                        }
 
                        var typedef = new CCodeTypeDefinition ("struct _" + struct_name, new CCodeVariableDeclarator (struct_name));
@@ -858,18 +788,8 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        cfile.add_function (unref_fun);
                }
 
-               foreach (CodeNode stmt in b.get_statements ()) {
-                       if (stmt.error) {
-                               continue;
-                       }
-
-                       if (stmt.ccodenode is CCodeFragment) {
-                               foreach (CCodeNode cstmt in ((CCodeFragment) stmt.ccodenode).get_children ()) {
-                                       cblock.add_statement (cstmt);
-                               }
-                       } else {
-                               cblock.add_statement (stmt.ccodenode);
-                       }
+               foreach (Statement stmt in b.get_statements ()) {
+                       stmt.emit (this);
                }
 
                // free in reverse order
@@ -878,7 +798,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        if (!local.floating && !local.captured && requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
-                               cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
                        }
                }
 
@@ -888,7 +808,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                                if (!param.captured && requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) {
                                        var ma = new MemberAccess.simple (param.name);
                                        ma.symbol_reference = param;
-                                       cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)));
+                                       ccode.add_statement (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)));
                                }
                        }
                }
@@ -898,30 +818,18 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cblock.add_statement (new CCodeExpressionStatement (data_unref));
+                       ccode.add_statement (new CCodeExpressionStatement (data_unref));
                }
 
-               b.ccodenode = cblock;
+               if (b.parent_node is Block || b.parent_node is SwitchStatement) {
+                       ccode.close ();
+               }
 
                emit_context.pop_symbol ();
        }
 
-       public override void visit_empty_statement (EmptyStatement stmt) {
-               stmt.ccodenode = new CCodeEmptyStatement ();
-       }
-
        public override void visit_declaration_statement (DeclarationStatement stmt) {
                stmt.declaration.accept (this);
-
-               stmt.ccodenode = stmt.declaration.ccodenode;
-
-               var local = stmt.declaration as LocalVariable;
-               if (local != null && local.initializer != null) {
-                       create_temp_decl (stmt, local.initializer.temp_vars);
-               }
-
-               create_temp_decl (stmt, temp_vars);
-               temp_vars.clear ();
        }
 
        public CCodeExpression get_variable_cexpression (string name) {
@@ -957,23 +865,16 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        rhs = (CCodeExpression) local.initializer.ccodenode;
                }
 
-               var cfrag = new CCodeFragment ();
-
-               if (pre_statement_fragment != null) {
-                       cfrag.append (pre_statement_fragment);
-                       pre_statement_fragment = null;
-               }
-
                if (local.captured) {
                        if (local.initializer != null) {
-                               cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id ((Block) local.parent_symbol))), get_variable_cname (local.name)), rhs)));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id ((Block) local.parent_symbol))), get_variable_cname (local.name)), rhs));
                        }
                } else {
                        var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
 
                        var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
                        cdecl.add_declarator (cvar);
-                       cfrag.append (cdecl);
+                       ccode.add_statement (cdecl);
 
                        // try to initialize uninitialized variables
                        // initialization not necessary for variables stored in closure
@@ -984,11 +885,9 @@ public class Vala.DovaBaseModule : CodeGenerator {
                }
 
                if (local.initializer != null && local.initializer.tree_can_fail) {
-                       add_simple_check (local.initializer, cfrag);
+                       add_simple_check (local.initializer);
                }
 
-               local.ccodenode = cfrag;
-
                local.active = true;
        }
 
@@ -1209,24 +1108,6 @@ public class Vala.DovaBaseModule : CodeGenerator {
                 * expression
                 */
 
-               /* can't automatically deep copy lists yet, so do it
-                * manually for now
-                * replace with
-                * expr.temp_vars = temp_vars;
-                * when deep list copying works
-                */
-               if (temp_vars.size > 0) {
-                       if (expr.temp_vars == null) {
-                               expr.temp_vars = new ArrayList<LocalVariable> ();
-                       } else {
-                               expr.temp_vars.clear ();
-                       }
-                       foreach (LocalVariable local in temp_vars) {
-                               expr.temp_vars.add (local);
-                       }
-                       temp_vars.clear ();
-               }
-
                if (((List<LocalVariable>) temp_ref_vars).size == 0) {
                        /* nothing to do without temporary variables */
                        return;
@@ -1238,7 +1119,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                }
 
                var full_expr_var = get_temp_variable (expr_type, true, expr);
-               expr.add_temp_var (full_expr_var);
+               emit_temp_var (full_expr_var);
 
                var expr_list = new CCodeCommaExpression ();
                expr_list.append_expression (new CCodeAssignment (get_variable_cexpression (full_expr_var.name), (CCodeExpression) expr.ccodenode));
@@ -1256,58 +1137,53 @@ public class Vala.DovaBaseModule : CodeGenerator {
                temp_ref_vars.clear ();
        }
 
-       public void append_temp_decl (CCodeFragment cfrag, List<LocalVariable>? temp_vars) {
-               if (temp_vars == null) {
-                       return;
-               }
-               foreach (LocalVariable local in temp_vars) {
-                       var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
+       public void emit_temp_var (LocalVariable local) {
+               var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
 
-                       var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ());
-                       // sets #line
-                       local.ccodenode = vardecl;
-                       cdecl.add_declarator (vardecl);
+               var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ());
+               // sets #line
+               local.ccodenode = vardecl;
+               cdecl.add_declarator (vardecl);
 
-                       var st = local.variable_type.data_type as Struct;
-                       var array_type = local.variable_type as ArrayType;
+               var st = local.variable_type.data_type as Struct;
+               var array_type = local.variable_type as ArrayType;
 
-                       if (local.name.has_prefix ("*")) {
-                               // do not dereference unintialized variable
-                               // initialization is not needed for these special
-                               // pointer temp variables
-                               // used to avoid side-effects in assignments
-                       } else if (local.variable_type is GenericType) {
-                               var value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size"));
-                               value_size.add_argument (get_type_id_expression (local.variable_type));
-
-                               var alloca_call = new CCodeFunctionCall (new CCodeIdentifier ("alloca"));
-                               alloca_call.add_argument (value_size);
+               if (local.name.has_prefix ("*")) {
+                       // do not dereference unintialized variable
+                       // initialization is not needed for these special
+                       // pointer temp variables
+                       // used to avoid side-effects in assignments
+               } else if (local.variable_type is GenericType) {
+                       var value_size = new CCodeFunctionCall (new CCodeIdentifier ("dova_type_get_value_size"));
+                       value_size.add_argument (get_type_id_expression (local.variable_type));
 
-                               var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
-                               memset_call.add_argument (alloca_call);
-                               memset_call.add_argument (new CCodeConstant ("0"));
-                               memset_call.add_argument (value_size);
+                       var alloca_call = new CCodeFunctionCall (new CCodeIdentifier ("alloca"));
+                       alloca_call.add_argument (value_size);
 
-                               vardecl.initializer = memset_call;
-                               vardecl.init0 = true;
-                       } else if (!local.variable_type.nullable &&
-                                  (st != null && st.get_fields ().size > 0) ||
-                                  (array_type != null && array_type.fixed_length)) {
-                               // 0-initialize struct with struct initializer { 0 }
-                               // necessary as they will be passed by reference
-                               var clist = new CCodeInitializerList ();
-                               clist.append (new CCodeConstant ("0"));
+                       var memset_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
+                       memset_call.add_argument (alloca_call);
+                       memset_call.add_argument (new CCodeConstant ("0"));
+                       memset_call.add_argument (value_size);
 
-                               vardecl.initializer = clist;
-                               vardecl.init0 = true;
-                       } else if (local.variable_type.is_reference_type_or_type_parameter () ||
-                              local.variable_type.nullable) {
-                               vardecl.initializer = new CCodeConstant ("NULL");
-                               vardecl.init0 = true;
-                       }
+                       vardecl.initializer = memset_call;
+                       vardecl.init0 = true;
+               } else if (!local.variable_type.nullable &&
+                          (st != null && st.get_fields ().size > 0) ||
+                          (array_type != null && array_type.fixed_length)) {
+                       // 0-initialize struct with struct initializer { 0 }
+                       // necessary as they will be passed by reference
+                       var clist = new CCodeInitializerList ();
+                       clist.append (new CCodeConstant ("0"));
 
-                       cfrag.append (cdecl);
+                       vardecl.initializer = clist;
+                       vardecl.init0 = true;
+               } else if (local.variable_type.is_reference_type_or_type_parameter () ||
+                      local.variable_type.nullable) {
+                       vardecl.initializer = new CCodeConstant ("NULL");
+                       vardecl.init0 = true;
                }
+
+               ccode.add_statement (cdecl);
        }
 
        public override void visit_expression_statement (ExpressionStatement stmt) {
@@ -1316,67 +1192,25 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        return;
                }
 
-               stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
-
-               if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
-                       // simple case, no node breakdown necessary
-
-                       var cfrag = new CCodeFragment ();
-
-                       cfrag.append (stmt.ccodenode);
-
-                       add_simple_check (stmt.expression, cfrag);
-
-                       stmt.ccodenode = cfrag;
-               }
-
-               /* free temporary objects */
-
-               if (((List<LocalVariable>) temp_vars).size == 0
-                    && pre_statement_fragment == null) {
-                       /* nothing to do without temporary variables */
-                       return;
-               }
-
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-
-               if (pre_statement_fragment != null) {
-                       cfrag.append (pre_statement_fragment);
-                       pre_statement_fragment = null;
-               }
-
-               cfrag.append (stmt.ccodenode);
+               ccode.add_expression ((CCodeExpression) stmt.expression.ccodenode);
+               /* free temporary objects and handle errors */
 
                foreach (LocalVariable local in temp_ref_vars) {
                        var ma = new MemberAccess.simple (local.name);
                        ma.symbol_reference = local;
-                       cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma)));
+                       ma.value_type = local.variable_type.copy ();
+                       ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                }
 
-               stmt.ccodenode = cfrag;
-
-               temp_vars.clear ();
-               temp_ref_vars.clear ();
-       }
-
-       public void create_temp_decl (Statement stmt, List<LocalVariable>? temp_vars) {
-               /* declare temporary variables */
-
-               if (temp_vars == null || temp_vars.size == 0) {
-                       /* nothing to do without temporary variables */
-                       return;
+               if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
+                       // simple case, no node breakdown necessary
+                       add_simple_check (stmt.expression);
                }
 
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-
-               cfrag.append (stmt.ccodenode);
-
-               stmt.ccodenode = cfrag;
+               temp_ref_vars.clear ();
        }
 
-       public virtual void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+       public virtual void append_local_free (Symbol sym, bool stop_at_loop = false) {
                var b = (Block) sym;
 
                var local_vars = b.get_local_variables ();
@@ -1386,7 +1220,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        if (local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
 
@@ -1395,7 +1229,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cfrag.append (new CCodeExpressionStatement (data_unref));
+                       ccode.add_expression (data_unref);
                }
 
                if (stop_at_loop) {
@@ -1407,13 +1241,13 @@ public class Vala.DovaBaseModule : CodeGenerator {
                }
 
                if (sym.parent_symbol is Block) {
-                       append_local_free (sym.parent_symbol, cfrag, stop_at_loop);
+                       append_local_free (sym.parent_symbol, stop_at_loop);
                } else if (sym.parent_symbol is Method) {
-                       append_param_free ((Method) sym.parent_symbol, cfrag);
+                       append_param_free ((Method) sym.parent_symbol);
                }
        }
 
-       public void append_error_free (Symbol sym, CCodeFragment cfrag, TryStatement current_try) {
+       public void append_error_free (Symbol sym, TryStatement current_try) {
                var b = (Block) sym;
 
                var local_vars = b.get_local_variables ();
@@ -1423,7 +1257,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        if (local.active && !local.floating && !local.captured && requires_destroy (local.variable_type)) {
                                var ma = new MemberAccess.simple (local.name);
                                ma.symbol_reference = local;
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
                        }
                }
 
@@ -1432,7 +1266,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                        var data_unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
                        data_unref.add_argument (get_variable_cexpression ("_data%d_".printf (block_id)));
-                       cfrag.append (new CCodeExpressionStatement (data_unref));
+                       ccode.add_expression (data_unref);
                }
 
                if (sym == current_try.body) {
@@ -1440,40 +1274,27 @@ public class Vala.DovaBaseModule : CodeGenerator {
                }
 
                if (sym.parent_symbol is Block) {
-                       append_error_free (sym.parent_symbol, cfrag, current_try);
+                       append_error_free (sym.parent_symbol, current_try);
                } else if (sym.parent_symbol is Method) {
-                       append_param_free ((Method) sym.parent_symbol, cfrag);
+                       append_param_free ((Method) sym.parent_symbol);
                }
        }
 
-       private void append_param_free (Method m, CCodeFragment cfrag) {
+       private void append_param_free (Method m) {
                foreach (FormalParameter param in m.get_parameters ()) {
                        if (requires_destroy (param.variable_type) && param.direction == ParameterDirection.IN) {
                                var ma = new MemberAccess.simple (param.name);
                                ma.symbol_reference = param;
-                               cfrag.append (new CCodeExpressionStatement (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma)));
+                               ccode.add_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma));
                        }
                }
        }
 
-       public void create_local_free (CodeNode stmt, bool stop_at_loop = false) {
-               var cfrag = new CCodeFragment ();
-
-               append_local_free (current_symbol, cfrag, stop_at_loop);
-
-               cfrag.append (stmt.ccodenode);
-               stmt.ccodenode = cfrag;
-       }
-
        public override void visit_return_statement (ReturnStatement stmt) {
-               var cfrag = new CCodeFragment ();
-
                // free local variables
-               append_local_free (current_symbol, cfrag);
-
-               cfrag.append (new CCodeReturnStatement ((current_return_type is VoidType) ? null : new CCodeIdentifier ("result")));
+               append_local_free (current_symbol);
 
-               stmt.ccodenode = cfrag;
+               ccode.add_return ((current_return_type is VoidType) ? null : new CCodeIdentifier ("result"));
        }
 
        public override void visit_delete_statement (DeleteStatement stmt) {
@@ -1485,7 +1306,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
                ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode);
-               stmt.ccodenode = new CCodeExpressionStatement (ccall);
+               ccode.add_expression (ccall);
        }
 
        public override void visit_expression (Expression expr) {
@@ -1555,7 +1376,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
                        // assign current value to temp variable
                        var temp_decl = get_temp_variable (prop.property_type, true, expr);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_decl.name), (CCodeExpression) expr.inner.ccodenode));
 
                        // increment/decrement property
@@ -1647,7 +1468,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        // (copy (&temp, 0, &expr, 0), temp)
 
                        var decl = get_temp_variable (expression_type, false, node);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ctemp = get_variable_cexpression (decl.name);
 
@@ -1691,7 +1512,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                        return ccall;
                } else {
                        var decl = get_temp_variable (expression_type, false, node);
-                       temp_vars.add (decl);
+                       emit_temp_var (decl);
 
                        var ctemp = get_variable_cexpression (decl.name);
 
@@ -1752,7 +1573,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                if (struct_by_ref || expr.get_object_initializer ().size > 0) {
                        // value-type initialization or object creation expression with object initializer
                        var temp_decl = get_temp_variable (expr.type_reference, false, expr);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
 
                        instance = get_variable_cexpression (get_variable_cname (temp_decl.name));
                }
@@ -1914,7 +1735,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                                        var ccomma = new CCodeCommaExpression ();
 
                                        var temp_var = get_temp_variable (arg.target_type);
-                                       temp_vars.add (temp_var);
+                                       emit_temp_var (temp_var);
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), cexpr));
                                        ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
 
@@ -1970,7 +1791,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                if (expr.type_reference.data_type != null && expr.type_reference.data_type.get_full_name () == "Dova.Value") {
                        // box value
                        var temp_decl = get_temp_variable (expr.inner.value_type, true, expr);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        var cvar = get_variable_cexpression (temp_decl.name);
 
                        var ccomma = new CCodeCommaExpression ();
@@ -1987,7 +1808,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                } else if (expr.inner.value_type.data_type != null && expr.inner.value_type.data_type.get_full_name () == "Dova.Value") {
                        // unbox value
                        var temp_decl = get_temp_variable (expr.type_reference, true, expr);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        var cvar = get_variable_cexpression (temp_decl.name);
 
                        var ccomma = new CCodeCommaExpression ();
@@ -2030,7 +1851,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                /* (tmp = var, var = null, tmp) */
                var ccomma = new CCodeCommaExpression ();
                var temp_decl = get_temp_variable (expr.value_type, true, expr);
-               temp_vars.add (temp_decl);
+               emit_temp_var (temp_decl);
                var cvar = get_variable_cexpression (temp_decl.name);
 
                ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode));
@@ -2178,7 +1999,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
                                // treat void* special to not leak memory with void* method parameters
                        } else if (requires_destroy (expression_type)) {
                                var decl = get_temp_variable (expression_type, true, expression_type);
-                               temp_vars.add (decl);
+                               emit_temp_var (decl);
                                temp_ref_vars.insert (0, decl);
                                cexpr = new CCodeAssignment (get_variable_cexpression (decl.name), cexpr);
                        }
@@ -2442,6 +2263,6 @@ public class Vala.DovaBaseModule : CodeGenerator {
                return false;
        }
 
-       public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) {
+       public virtual void add_simple_check (CodeNode node, bool always_fails = false) {
        }
 }
index 0fddf3f97ead169000a9309bd6e51f5c4d264c02..93894ed46eecd4822a36296d0341a7c6106bc3d6 100644 (file)
 
 public class Vala.DovaControlFlowModule : DovaMethodModule {
        public override void visit_if_statement (IfStatement stmt) {
+               ccode.open_if ((CCodeExpression) stmt.condition.ccodenode);
+
                stmt.true_statement.emit (this);
-               if (stmt.false_statement != null) {
-                       stmt.false_statement.emit (this);
-               }
 
                if (stmt.false_statement != null) {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode, (CCodeStatement) stmt.false_statement.ccodenode);
-               } else {
-                       stmt.ccodenode = new CCodeIfStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.true_statement.ccodenode);
+                       ccode.add_else ();
+                       stmt.false_statement.emit (this);
                }
 
-               create_temp_decl (stmt, stmt.condition.temp_vars);
+               ccode.close ();
        }
 
        public override void visit_switch_statement (SwitchStatement stmt) {
-               foreach (SwitchSection section in stmt.get_sections ()) {
-                       section.emit (this);
-               }
-
-               var cswitch = new CCodeSwitchStatement ((CCodeExpression) stmt.expression.ccodenode);
-               stmt.ccodenode = cswitch;
+               ccode.open_switch ((CCodeExpression) stmt.expression.ccodenode);
 
                foreach (SwitchSection section in stmt.get_sections ()) {
                        if (section.has_default_label ()) {
-                               cswitch.add_statement (new CCodeLabel ("default"));
-                               var cdefaultblock = new CCodeBlock ();
-                               cswitch.add_statement (cdefaultblock);
-                               foreach (CodeNode default_stmt in section.get_statements ()) {
-                                       cdefaultblock.add_statement (default_stmt.ccodenode);
-                               }
-                               continue;
-                       }
-
-                       foreach (SwitchLabel label in section.get_labels ()) {
-                               cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
-                       }
-
-                       var cblock = new CCodeBlock ();
-                       cswitch.add_statement (cblock);
-                       foreach (CodeNode body_stmt in section.get_statements ()) {
-                               cblock.add_statement (body_stmt.ccodenode);
+                               ccode.add_default ();
                        }
+                       section.emit (this);
                }
 
-               create_temp_decl (stmt, stmt.expression.temp_vars);
+               ccode.close ();
        }
 
        public override void visit_switch_label (SwitchLabel label) {
@@ -74,25 +52,29 @@ public class Vala.DovaControlFlowModule : DovaMethodModule {
                        label.expression.emit (this);
 
                        visit_end_full_expression (label.expression);
+
+                       ccode.add_case ((CCodeExpression) label.expression.ccodenode);
                }
        }
 
        public override void visit_loop (Loop stmt) {
+               ccode.open_while (new CCodeConstant ("true"));
+
                stmt.body.emit (this);
 
-               stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("true"), (CCodeStatement) stmt.body.ccodenode);
+               ccode.close ();
        }
 
        public override void visit_break_statement (BreakStatement stmt) {
-               stmt.ccodenode = new CCodeBreakStatement ();
+               append_local_free (current_symbol, true);
 
-               create_local_free (stmt, true);
+               ccode.add_break ();
        }
 
        public override void visit_continue_statement (ContinueStatement stmt) {
-               stmt.ccodenode = new CCodeContinueStatement ();
+               append_local_free (current_symbol, true);
 
-               create_local_free (stmt, true);
+               ccode.add_continue ();
        }
 }
 
index f38bafde1a805e5c3ef24063debe44469c42fdde..be2fcafd2c2d239635f467df1f66777a321b7bcc 100644 (file)
@@ -27,67 +27,44 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
        private bool is_in_catch = false;
 
        public override void visit_throw_statement (ThrowStatement stmt) {
-               var cfrag = new CCodeFragment ();
+               ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("dova_error"), (CCodeExpression) stmt.error_expression.ccodenode));
 
-               // method will fail
-               var cassign = new CCodeAssignment (new CCodeIdentifier ("dova_error"), (CCodeExpression) stmt.error_expression.ccodenode);
-               cfrag.append (new CCodeExpressionStatement (cassign));
-
-               add_simple_check (stmt, cfrag, true);
-
-               stmt.ccodenode = cfrag;
-
-               create_temp_decl (stmt, stmt.error_expression.temp_vars);
+               add_simple_check (stmt, true);
        }
 
-       public virtual CCodeStatement return_with_exception () {
-               var cerror_block = new CCodeBlock ();
-
+       public void return_with_exception () {
                // propagate error
                // nothing to do
 
                // free local variables
-               var free_frag = new CCodeFragment ();
-               append_local_free (current_symbol, free_frag, false);
-               cerror_block.add_statement (free_frag);
+               append_local_free (current_symbol, false);
 
                if (current_method is CreationMethod && current_method.parent_symbol is Class) {
                        var cl = current_method.parent_symbol as Class;
                        var unref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
                        unref_call.add_argument (new CCodeIdentifier ("this"));
-                       cerror_block.add_statement (new CCodeExpressionStatement (unref_call));
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_expression (unref_call);
+                       ccode.add_return ();
                } else if (current_return_type is VoidType) {
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_return ();
                } else {
-                       cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+                       ccode.add_return (default_value_for_type (current_return_type, false));
                }
-
-               return cerror_block;
        }
 
-       CCodeStatement uncaught_error_statement (CCodeBlock? block = null, bool unexpected = false) {
-               var cerror_block = block;
-               if (cerror_block == null) {
-                       cerror_block = new CCodeBlock ();
-               }
-
+       void uncaught_error_statement () {
                // free local variables
-               var free_frag = new CCodeFragment ();
-               append_local_free (current_symbol, free_frag, false);
-               cerror_block.add_statement (free_frag);
+               append_local_free (current_symbol, false);
 
                // TODO log uncaught error as critical warning
 
                if (current_method is CreationMethod) {
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_return ();
                } else if (current_return_type is VoidType) {
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_return ();
                } else if (current_return_type != null) {
-                       cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+                       ccode.add_return (default_value_for_type (current_return_type, false));
                }
-
-               return cerror_block;
        }
 
        bool in_finally_block (CodeNode node) {
@@ -102,17 +79,20 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                return false;
        }
 
-       public override void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) {
-               CCodeStatement cerror_handler = null;
+       public override void add_simple_check (CodeNode node, bool always_fails = false) {
+               if (always_fails) {
+                       // inner_error is always set, avoid unnecessary if statement
+                       // eliminates C warnings
+               } else {
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL"));
+                       ccode.open_if (ccond);
+               }
 
                if (current_try != null) {
                        // surrounding try found
-                       var cerror_block = new CCodeBlock ();
 
                        // free local variables
-                       var free_frag = new CCodeFragment ();
-                       append_error_free (current_symbol, free_frag, current_try);
-                       cerror_block.add_statement (free_frag);
+                       append_error_free (current_symbol, current_try);
 
                        var error_types = new ArrayList<DataType> ();
                        foreach (DataType node_error_type in node.get_error_types ()) {
@@ -135,24 +115,23 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                                        }
                                        handled_error_types.clear ();
 
-                                       // go to catch clause if error domain matches
-                                       var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name);
-
                                        if (clause.error_type.equals (new ObjectType (error_class))) {
                                                // general catch clause, this should be the last one
                                                has_general_catch_clause = true;
-                                               cerror_block.add_statement (cgoto_stmt);
+                                               ccode.add_goto (clause.clabel_name);
                                                break;
                                        } else {
                                                var catch_type = clause.error_type as ObjectType;
-                                               var cgoto_block = new CCodeBlock ();
-                                               cgoto_block.add_statement (cgoto_stmt);
 
                                                var type_check = new CCodeFunctionCall (new CCodeIdentifier ("any_is_a"));
                                                type_check.add_argument (new CCodeIdentifier ("dova_error"));
                                                type_check.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("%s_type_get".printf (catch_type.type_symbol.get_lower_case_cname ()))));
 
-                                               cerror_block.add_statement (new CCodeIfStatement (type_check, cgoto_block));
+                                               ccode.open_if (type_check);
+
+                                               // go to catch clause if error domain matches
+                                               ccode.add_goto (clause.clabel_name);
+                                               ccode.close ();
                                        }
                                }
                        }
@@ -164,16 +143,13 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                        } else if (error_types.size > 0) {
                                // go to finally clause if no catch clause matches
                                // and there are still unhandled error types
-                               cerror_block.add_statement (new CCodeGotoStatement ("__finally%d".printf (current_try_id)));
+                               ccode.add_goto ("__finally%d".printf (current_try_id));
                        } else if (in_finally_block (node)) {
                                // do not check unexpected errors happening within finally blocks
                                // as jump out of finally block is not supported
                        } else {
-                               // should never happen with correct bindings
-                               uncaught_error_statement (cerror_block, true);
+                               assert_not_reached ();
                        }
-
-                       cerror_handler = cerror_block;
                } else if (current_method != null && current_method.get_error_types ().size > 0) {
                        // current method can fail, propagate error
                        CCodeExpression ccond = null;
@@ -197,25 +173,20 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                        }
 
                        if (ccond == null) {
-                               cerror_handler = return_with_exception ();
+                               return_with_exception ();
                        } else {
-                               var cerror_block = new CCodeBlock ();
-                               cerror_block.add_statement (new CCodeIfStatement (ccond,
-                                       return_with_exception (),
-                                       uncaught_error_statement ()));
-                               cerror_handler = cerror_block;
+                               ccode.open_if (ccond);
+                               return_with_exception ();
+                               ccode.add_else ();
+                               uncaught_error_statement ();
+                               ccode.close ();
                        }
                } else {
-                       cerror_handler = uncaught_error_statement ();
+                       uncaught_error_statement ();
                }
 
-               if (always_fails) {
-                       // inner_error is always set, avoid unnecessary if statement
-                       // eliminates C warnings
-                       cfrag.append (cerror_handler);
-               } else {
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL"));
-                       cfrag.append (new CCodeIfStatement (ccond, cerror_handler));
+               if (!always_fails) {
+                       ccode.close ();
                }
        }
 
@@ -233,15 +204,12 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                        clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ());
                }
 
-               if (stmt.finally_body != null) {
-                       stmt.finally_body.emit (this);
-               }
-
                is_in_catch = false;
                stmt.body.emit (this);
                is_in_catch = true;
 
                foreach (CatchClause clause in stmt.get_catch_clauses ()) {
+                       ccode.add_goto ("__finally%d".printf (this_try_id));
                        clause.emit (this);
                }
 
@@ -249,35 +217,22 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                current_try_id = old_try_id;
                is_in_catch = old_is_in_catch;
 
-               var cfrag = new CCodeFragment ();
-               cfrag.append (stmt.body.ccodenode);
-
-               foreach (CatchClause clause in stmt.get_catch_clauses ()) {
-                       cfrag.append (new CCodeGotoStatement ("__finally%d".printf (this_try_id)));
-                       cfrag.append (clause.ccodenode);
-               }
-
-               cfrag.append (new CCodeLabel ("__finally%d".printf (this_try_id)));
+               ccode.add_label ("__finally%d".printf (this_try_id));
                if (stmt.finally_body != null) {
-                       cfrag.append (stmt.finally_body.ccodenode);
+                       stmt.finally_body.emit (this);
                }
 
                // check for errors not handled by this try statement
                // may be handled by outer try statements or propagated
-               add_simple_check (stmt, cfrag, !stmt.after_try_block_reachable);
-
-               stmt.ccodenode = cfrag;
+               add_simple_check (stmt, !stmt.after_try_block_reachable);
        }
 
        public override void visit_catch_clause (CatchClause clause) {
                generate_type_declaration (clause.error_type, cfile);
 
-               clause.body.emit (this);
-
-               var cfrag = new CCodeFragment ();
-               cfrag.append (new CCodeLabel (clause.clabel_name));
+               ccode.add_label (clause.clabel_name);
 
-               var cblock = new CCodeBlock ();
+               ccode.open_block ();
 
                string variable_name;
                if (clause.variable_name != null) {
@@ -289,23 +244,21 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                if (clause.variable_name != null) {
                        var cdecl = new CCodeDeclaration (clause.error_type.get_cname ());
                        cdecl.add_declarator (new CCodeVariableDeclarator (variable_name, new CCodeIdentifier ("dova_error")));
-                       cblock.add_statement (cdecl);
+                       ccode.add_statement (cdecl);
                } else {
                        // error object is not used within catch statement, clear it
                        var cclear = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
                        cclear.add_argument (new CCodeIdentifier ("dova_error"));
-                       cblock.add_statement (new CCodeExpressionStatement (cclear));
+                       ccode.add_statement (new CCodeExpressionStatement (cclear));
                }
-               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL"))));
+               ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("dova_error"), new CCodeConstant ("NULL"))));
 
-               cblock.add_statement (clause.body.ccodenode);
-
-               cfrag.append (cblock);
+               clause.body.emit (this);
 
-               clause.ccodenode = cfrag;
+               ccode.close ();
        }
 
-       public override void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+       public override void append_local_free (Symbol sym, bool stop_at_loop = false) {
                var finally_block = (Block) null;
                if (sym.parent_node is TryStatement) {
                        finally_block = (sym.parent_node as TryStatement).finally_body;
@@ -314,10 +267,10 @@ public class Vala.DovaErrorModule : DovaDelegateModule {
                }
 
                if (finally_block != null) {
-                       cfrag.append (finally_block.ccodenode);
+                       finally_block.emit (this);
                }
 
-               base.append_local_free (sym, cfrag, stop_at_loop);
+               base.append_local_free (sym, stop_at_loop);
        }
 }
 
index 3e7b102528a44fe081952f73583b021478919156..3e87b0514da8ac16a0ff278777c56f3866c8ee2a 100644 (file)
@@ -71,7 +71,7 @@ public class Vala.DovaMemberAccessModule : DovaControlFlowModule {
                                                // instance expression has side-effects
                                                // store in temp. variable
                                                var temp_var = get_temp_variable (expr.inner.value_type);
-                                               temp_vars.add (temp_var);
+                                               emit_temp_var (temp_var);
                                                var ctemp = new CCodeIdentifier (temp_var.name);
                                                inst = new CCodeAssignment (ctemp, pub_inst);
                                                expr.inner.ccodenode = ctemp;
index 7a245b0bc1736d148109f07cbc888db06f3da626..958aa2635a6afb6d574c8e07fcd77ffe4aaade62 100644 (file)
@@ -81,7 +81,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule {
                                                var ccomma = new CCodeCommaExpression ();
 
                                                var temp_var = get_temp_variable (ma.inner.target_type);
-                                               temp_vars.add (temp_var);
+                                               emit_temp_var (temp_var);
                                                ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), instance));
                                                ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name)));
 
@@ -135,7 +135,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule {
                                                var ccomma = new CCodeCommaExpression ();
 
                                                var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned);
-                                               temp_vars.add (temp_var);
+                                               emit_temp_var (temp_var);
                                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression (temp_var.name));
 
                                                if (param.direction == ParameterDirection.REF) {
@@ -151,14 +151,14 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule {
                                                        ccomma.append_expression (ccall_expr);
                                                } else {
                                                        ret_temp_var = get_temp_variable (itype.get_return_type ());
-                                                       temp_vars.add (ret_temp_var);
+                                                       emit_temp_var (ret_temp_var);
                                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (ret_temp_var.name), ccall_expr));
                                                }
 
                                                var cassign_comma = new CCodeCommaExpression ();
 
                                                var assign_temp_var = get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned);
-                                               temp_vars.add (assign_temp_var);
+                                               emit_temp_var (assign_temp_var);
 
                                                cassign_comma.append_expression (new CCodeAssignment (get_variable_cexpression (assign_temp_var.name), transform_expression (get_variable_cexpression (temp_var.name), param.variable_type, unary.inner.value_type, arg)));
 
@@ -203,7 +203,7 @@ public class Vala.DovaMethodCallModule : DovaAssignmentModule {
                        var ccomma = new CCodeCommaExpression ();
 
                        var temp_var = get_temp_variable (expr.value_type);
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
                        if (expr.value_type is GenericType) {
                                ccall.add_argument (get_variable_cexpression (temp_var.name));
                        } else {
index fca759d39f0e40a7110730ac07f68c91b25e0bcc..4d65c26a5fe379f9bf6eb0dbb9556081226fe2f7 100644 (file)
@@ -758,16 +758,42 @@ public class Vala.DovaObjectModule : DovaArrayModule {
 
                function.add_parameter (new CCodeFormalParameter ("this", cl.get_cname () + "*"));
 
-               cfile.add_function_declaration (function);
-
+               push_function (function);
 
-               var cblock = new CCodeBlock ();
+               cfile.add_function_declaration (function);
 
                if (cl.destructor != null) {
-                       cblock.add_statement (cl.destructor.ccodenode);
+                       cl.destructor.body.emit (this);
                }
 
-               cblock.add_statement (instance_finalize_fragment);
+               foreach (var f in cl.get_fields ()) {
+                       if (f.binding == MemberBinding.INSTANCE)  {
+                               CCodeExpression lhs = null;
+                               if (f.is_internal_symbol ()) {
+                                       var priv_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
+                                       priv_call.add_argument (new CCodeIdentifier ("this"));
+                                       lhs = new CCodeMemberAccess.pointer (priv_call, f.get_cname ());
+                               } else {
+                                       lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("this"), f.get_cname ());
+                               }
+
+                               if (requires_destroy (f.variable_type)) {
+                                       var this_access = new MemberAccess.simple ("this");
+                                       this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+
+                                       var field_st = f.parent_symbol as Struct;
+                                       if (field_st != null && !field_st.is_simple_type ()) {
+                                               this_access.ccodenode = new CCodeIdentifier ("(*this)");
+                                       } else {
+                                               this_access.ccodenode = new CCodeIdentifier ("this");
+                                       }
+
+                                       var ma = new MemberAccess (this_access, f.name);
+                                       ma.symbol_reference = f;
+                                       ccode.add_expression (get_unref_expression (lhs, f.variable_type, ma));
+                               }
+                       }
+               }
 
                // chain up to finalize function of the base class
                foreach (DataType base_type in cl.get_base_types ()) {
@@ -780,12 +806,11 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                }
                                ccall.add_argument (type_get_call);
                                ccall.add_argument (new CCodeIdentifier ("this"));
-                               cblock.add_statement (new CCodeExpressionStatement (ccall));
+                               ccode.add_statement (new CCodeExpressionStatement (ccall));
                        }
                }
 
-
-               function.block = cblock;
+               pop_function ();
 
                cfile.add_function (function);
        }
@@ -793,9 +818,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
        public override void visit_class (Class cl) {
                push_context (new EmitContext (cl));
 
-               var old_instance_finalize_fragment = instance_finalize_fragment;
-               instance_finalize_fragment = new CCodeFragment ();
-
                generate_class_declaration (cl, cfile);
                generate_class_private_declaration (cl, cfile);
 
@@ -969,8 +991,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        cfile.add_function (create_set_value_from_any_function ());
                }
 
-               instance_finalize_fragment = old_instance_finalize_fragment;
-
                pop_context ();
        }
 
@@ -1148,14 +1168,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
 
                var prop = (Property) acc.prop;
 
-               if (acc.result_var != null) {
-                       acc.result_var.accept (this);
-               }
-
-               if (acc.body != null) {
-                       acc.body.emit (this);
-               }
-
                // do not declare overriding properties and interface implementations
                if (prop.is_abstract || prop.is_virtual
                    || (prop.base_property == null && prop.base_interface_property == null)) {
@@ -1256,7 +1268,13 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                function.modifiers |= CCodeModifiers.STATIC;
                        }
 
-                       function.block = (CCodeBlock) acc.body.ccodenode;
+                       push_function (function);
+
+                       if (acc.result_var != null) {
+                               acc.result_var.accept (this);
+                       }
+
+                       acc.body.emit (this);
 
                        if (acc.readable) {
                                var cdecl = new CCodeDeclaration (acc.value_type.get_cname ());
@@ -1386,10 +1404,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        param.accept (this);
                }
 
-               if (m.result_var != null) {
-                       m.result_var.accept (this);
-               }
-
                foreach (Expression precondition in m.get_preconditions ()) {
                        precondition.emit (this);
                }
@@ -1398,12 +1412,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        postcondition.emit (this);
                }
 
-               if (m.body != null) {
-                       m.body.emit (this);
-               }
-
-
-               pop_context ();
 
                generate_method_declaration (m, cfile);
 
@@ -1412,7 +1420,6 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                }
 
                var function = new CCodeFunction (m.get_real_cname ());
-               m.ccodenode = function;
 
                generate_cparameters (m, cfile, function);
 
@@ -1427,14 +1434,10 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        }
 
                        if (m.body != null) {
-                               function.block = (CCodeBlock) m.body.ccodenode;
-                               function.block.line = function.line;
-
-                               var cinit = new CCodeFragment ();
-                               function.block.prepend_statement (cinit);
+                               push_function (function);
 
                                if (context.module_init_method == m) {
-                                       cinit.append (module_init_fragment);
+                                       add_module_init ();
                                }
 
                                if (m.closure) {
@@ -1453,7 +1456,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                                var cdecl = new CCodeDeclaration ("Block%dData*".printf (parent_block_id));
                                                cdecl.add_declarator (new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id), parent_data));
 
-                                               cinit.append (cdecl);
+                                               ccode.add_statement (cdecl);
 
                                                closure_block = parent_closure_block;
                                                block_id = parent_block_id;
@@ -1466,7 +1469,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                                var cdecl = new CCodeDeclaration ("%s *".printf (current_class.get_cname ()));
                                                cdecl.add_declarator (new CCodeVariableDeclarator ("this", cself));
 
-                                               cinit.append (cdecl);
+                                               ccode.add_statement (cdecl);
                                        }
                                }
                                foreach (FormalParameter param in m.get_parameters ()) {
@@ -1484,26 +1487,32 @@ public class Vala.DovaObjectModule : DovaArrayModule {
 
                                                        var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (param.name), new CCodeConstant ("NULL"));
                                                        var if_statement = new CCodeIfStatement (condition, cblock);
-                                                       cinit.append (if_statement);
+                                                       ccode.add_statement (if_statement);
                                                }
                                        }
                                }
 
+                               if (m.result_var != null) {
+                                       m.result_var.accept (this);
+                               }
+
+                               m.body.emit (this);
+
                                if (!(m.return_type is VoidType) && !(m.return_type is GenericType)) {
                                        var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
                                        cdecl.add_declarator (new CCodeVariableDeclarator.zero ("result", default_value_for_type (m.return_type, true)));
-                                       cinit.append (cdecl);
+                                       ccode.add_statement (cdecl);
 
-                                       function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+                                       ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
                                }
 
                                var st = m.parent_symbol as Struct;
                                if (m is CreationMethod && st != null && (st.is_boolean_type () || st.is_integer_type () || st.is_floating_type ())) {
                                        var cdecl = new CCodeDeclaration (st.get_cname ());
                                        cdecl.add_declarator (new CCodeVariableDeclarator ("this", new CCodeConstant ("0")));
-                                       cinit.append (cdecl);
+                                       ccode.add_statement (cdecl);
 
-                                       function.block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("this")));
+                                       ccode.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("this")));
                                }
 
                                cfile.add_function (function);
@@ -1639,6 +1648,8 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        cfile.add_function (override_func);
                }
 
+               pop_context ();
+
                if (m.entry_point) {
                        generate_type_declaration (new ObjectType (array_class), cfile);
 
@@ -1647,18 +1658,19 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        cmain.line = function.line;
                        cmain.add_parameter (new CCodeFormalParameter ("argc", "int"));
                        cmain.add_parameter (new CCodeFormalParameter ("argv", "char **"));
-                       var main_block = new CCodeBlock ();
+
+                       push_function (cmain);
 
                        var dova_init_call = new CCodeFunctionCall (new CCodeIdentifier ("dova_init"));
                        dova_init_call.add_argument (new CCodeIdentifier ("argc"));
                        dova_init_call.add_argument (new CCodeIdentifier ("argv"));
-                       main_block.add_statement (new CCodeExpressionStatement (dova_init_call));
+                       ccode.add_statement (new CCodeExpressionStatement (dova_init_call));
 
-                       main_block.add_statement (module_init_fragment);
+                       add_module_init ();
 
                        var cdecl = new CCodeDeclaration ("int");
                        cdecl.add_declarator (new CCodeVariableDeclarator ("result", new CCodeConstant ("0")));
-                       main_block.add_statement (cdecl);
+                       ccode.add_statement (cdecl);
 
                        var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name));
 
@@ -1671,18 +1683,18 @@ public class Vala.DovaObjectModule : DovaArrayModule {
 
                                cdecl = new CCodeDeclaration ("DovaArray*");
                                cdecl.add_declarator (new CCodeVariableDeclarator ("args", array_creation));
-                               main_block.add_statement (cdecl);
+                               ccode.add_statement (cdecl);
 
                                var array_data = new CCodeFunctionCall (new CCodeIdentifier ("dova_array_get_data"));
                                array_data.add_argument (new CCodeIdentifier ("args"));
 
                                cdecl = new CCodeDeclaration ("string_t*");
                                cdecl.add_declarator (new CCodeVariableDeclarator ("args_data", array_data));
-                               main_block.add_statement (cdecl);
+                               ccode.add_statement (cdecl);
 
                                cdecl = new CCodeDeclaration ("int");
                                cdecl.add_declarator (new CCodeVariableDeclarator ("argi"));
-                               main_block.add_statement (cdecl);
+                               ccode.add_statement (cdecl);
 
                                var string_creation = new CCodeFunctionCall (new CCodeIdentifier ("string_create_from_cstring"));
                                string_creation.add_argument (new CCodeElementAccess (new CCodeIdentifier ("argv"), new CCodeIdentifier ("argi")));
@@ -1693,7 +1705,7 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                var for_stmt = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("argi"), new CCodeIdentifier ("argc")), loop_block);
                                for_stmt.add_initializer (new CCodeAssignment (new CCodeIdentifier ("argi"), new CCodeConstant ("0")));
                                for_stmt.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("argi")));
-                               main_block.add_statement (for_stmt);
+                               ccode.add_statement (for_stmt);
 
                                main_call.add_argument (new CCodeIdentifier ("args"));
                        }
@@ -1702,25 +1714,26 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                                // method returns void, always use 0 as exit code
                                var main_stmt = new CCodeExpressionStatement (main_call);
                                main_stmt.line = cmain.line;
-                               main_block.add_statement (main_stmt);
+                               ccode.add_statement (main_stmt);
                        } else {
                                var main_stmt = new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), main_call));
                                main_stmt.line = cmain.line;
-                               main_block.add_statement (main_stmt);
+                               ccode.add_statement (main_stmt);
                        }
 
                        if (m.get_parameters ().size == 1) {
                                // destroy Dova array
                                var unref = new CCodeFunctionCall (new CCodeIdentifier ("dova_object_unref"));
                                unref.add_argument (new CCodeIdentifier ("args"));
-                               main_block.add_statement (new CCodeExpressionStatement (unref));
+                               ccode.add_statement (new CCodeExpressionStatement (unref));
                        }
 
                        var ret_stmt = new CCodeReturnStatement (new CCodeIdentifier ("result"));
                        ret_stmt.line = cmain.line;
-                       main_block.add_statement (ret_stmt);
+                       ccode.add_statement (ret_stmt);
+
+                       pop_function ();
 
-                       cmain.block = main_block;
                        cfile.add_function (cmain);
                }
        }
@@ -1955,4 +1968,15 @@ public class Vala.DovaObjectModule : DovaArrayModule {
                        base.visit_element_access (expr);
                }
        }
+
+       void add_module_init () {
+               foreach (var field in static_fields) {
+                       field.initializer.emit (this);
+
+                       var lhs = new CCodeIdentifier (field.get_cname ());
+                       var rhs = (CCodeExpression) field.initializer.ccodenode;
+
+                       ccode.add_expression (new CCodeAssignment (lhs, rhs));
+               }
+       }
 }
index b7a99cd3a42e1c02d3e5f56d0b562b7190f696b4..2c6cdf2c7e2bcfd92110adefcf1af5126f074af3 100644 (file)
@@ -72,9 +72,6 @@ public class Vala.DovaStructModule : DovaBaseModule {
        public override void visit_struct (Struct st) {
                push_context (new EmitContext (st));
 
-               var old_instance_finalize_fragment = instance_finalize_fragment;
-               instance_finalize_fragment = new CCodeFragment ();
-
                generate_struct_declaration (st, cfile);
 
                if (!st.is_internal_symbol ()) {
@@ -83,8 +80,6 @@ public class Vala.DovaStructModule : DovaBaseModule {
 
                st.accept_children (this);
 
-               instance_finalize_fragment = old_instance_finalize_fragment;
-
                pop_context ();
        }
 }
index e87686982b26a6c49c3afee922be8487ba7873c5..94369253b080dd91a0182e4d69d7c79d86d08a0b 100644 (file)
@@ -362,9 +362,6 @@ public class Vala.DovaValueModule : DovaObjectModule {
 
                cblock.add_statement (new CCodeIfStatement (new CCodeIdentifier ("src"), copy_block));
 
-               append_temp_decl (cfrag, temp_vars);
-               temp_vars.clear ();
-
                function.block = cblock;
 
                cfile.add_function (function);
@@ -549,7 +546,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
                        var temp_var = get_temp_variable (array_type, true, expr);
                        var name_cnode = get_variable_cexpression (temp_var.name);
 
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
 
                        int i = 0;
                        foreach (Expression e in expr.get_expressions ()) {
@@ -583,7 +580,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
                        var temp_var = get_temp_variable (array_type, true, expr);
                        var name_cnode = get_variable_cexpression (temp_var.name);
 
-                       temp_vars.add (temp_var);
+                       emit_temp_var (temp_var);
 
                        int i = 0;
                        foreach (Expression e in expr.get_expressions ()) {
@@ -619,7 +616,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
                        var key_temp_var = get_temp_variable (key_array_type, true, expr);
                        var key_name_cnode = get_variable_cexpression (key_temp_var.name);
 
-                       temp_vars.add (key_temp_var);
+                       emit_temp_var (key_temp_var);
 
                        var value_array_type = new ArrayType (expr.map_value_type, 1, expr.source_reference);
                        value_array_type.inline_allocated = true;
@@ -629,7 +626,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
                        var value_temp_var = get_temp_variable (value_array_type, true, expr);
                        var value_name_cnode = get_variable_cexpression (value_temp_var.name);
 
-                       temp_vars.add (value_temp_var);
+                       emit_temp_var (value_temp_var);
 
                        for (int i = 0; i < length; i++) {
                                key_ce.append_expression (new CCodeAssignment (new CCodeElementAccess (key_name_cnode, new CCodeConstant (i.to_string ())), (CCodeExpression) expr.get_keys ().get (i).ccodenode));
@@ -658,7 +655,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
 
                var type_temp_var = get_temp_variable (type_array_type, true, tuple);
                var type_name_cnode = get_variable_cexpression (type_temp_var.name);
-               temp_vars.add (type_temp_var);
+               emit_temp_var (type_temp_var);
 
                var array_type = new ArrayType (new PointerType (new VoidType ()), 1, tuple.source_reference);
                array_type.inline_allocated = true;
@@ -667,7 +664,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
 
                var temp_var = get_temp_variable (array_type, true, tuple);
                var name_cnode = get_variable_cexpression (temp_var.name);
-               temp_vars.add (temp_var);
+               emit_temp_var (temp_var);
 
                var type_ce = new CCodeCommaExpression ();
                var ce = new CCodeCommaExpression ();
@@ -691,7 +688,7 @@ public class Vala.DovaValueModule : DovaObjectModule {
                                // tmp = expr, &tmp
 
                                var element_temp_var = get_temp_variable (element_type);
-                               temp_vars.add (element_temp_var);
+                               emit_temp_var (element_temp_var);
                                ce.append_expression (new CCodeAssignment (get_variable_cexpression (element_temp_var.name), cexpr));
                                cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (element_temp_var.name));
                        }
index a62167dcfe7096431317976b3eba5c0295897af3..02846d250544ef51335ef5e46e341ab11d80ffc8 100644 (file)
@@ -138,8 +138,27 @@ public class Vala.GAsyncModule : GSignalModule {
                return freefunc;
        }
 
-       CCodeFunction generate_async_function (Method m) {
-               var asyncblock = new CCodeBlock ();
+       void generate_async_function (Method m) {
+               push_context (new EmitContext ());
+
+               var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
+               var asyncfunc = new CCodeFunction (m.get_real_cname (), "void");
+               var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+               cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
+               cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
+
+               generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1);
+
+               if (m.base_method != null || m.base_interface_method != null) {
+                       // declare *_real_* function
+                       asyncfunc.modifiers |= CCodeModifiers.STATIC;
+                       cfile.add_function_declaration (asyncfunc);
+               } else if (m.is_private_symbol ()) {
+                       asyncfunc.modifiers |= CCodeModifiers.STATIC;
+               }
+
+               push_function (asyncfunc);
 
                // logic copied from valaccodemethodmodule
                if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
@@ -156,24 +175,17 @@ public class Vala.GAsyncModule : GSignalModule {
 
                        var self_target_type = new ObjectType (type_symbol);
                        var cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
-                       var cdecl = new CCodeDeclaration ("%s *".printf (type_symbol.get_cname ()));
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("self", cself));
-                       asyncblock.add_statement (cdecl);
+                       ccode.add_declaration ("%s *".printf (type_symbol.get_cname ()), new CCodeVariableDeclarator ("self"));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself));
                }
 
-               var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
-               var asyncfunc = new CCodeFunction (m.get_real_cname (), "void");
-               var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
-
                var dataalloc = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
                dataalloc.add_argument (new CCodeIdentifier (dataname));
 
                var data_var = new CCodeIdentifier ("_data_");
 
-               var datadecl = new CCodeDeclaration (dataname + "*");
-               datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
-               asyncblock.add_statement (datadecl);
-               asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, dataalloc)));
+               ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
+               ccode.add_expression (new CCodeAssignment (data_var, dataalloc));
 
                var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
 
@@ -201,13 +213,13 @@ public class Vala.GAsyncModule : GSignalModule {
                create_result.add_argument (new CCodeIdentifier ("_user_data_"));
                create_result.add_argument (new CCodeIdentifier (m.get_real_cname ()));
 
-               asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result)));
+               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "_async_result"), create_result));
 
                var set_op_res_call = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_op_res_gpointer"));
                set_op_res_call.add_argument (new CCodeMemberAccess.pointer (data_var, "_async_result"));
                set_op_res_call.add_argument (data_var);
                set_op_res_call.add_argument (new CCodeIdentifier (m.get_real_cname () + "_data_free"));
-               asyncblock.add_statement (new CCodeExpressionStatement (set_op_res_call));
+               ccode.add_expression (set_op_res_call);
 
                if (m.binding == MemberBinding.INSTANCE) {
                        CCodeExpression self_expr = new CCodeIdentifier ("self");
@@ -219,7 +231,7 @@ public class Vala.GAsyncModule : GSignalModule {
                                self_expr = refcall;
                        }
 
-                       asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr)));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr));
                }
 
                foreach (FormalParameter param in m.get_parameters ()) {
@@ -228,7 +240,7 @@ public class Vala.GAsyncModule : GSignalModule {
                                param_type.value_owned = true;
 
                                // create copy if necessary as variables in async methods may need to be kept alive
-                               CCodeExpression cparam = get_variable_cexpression (param.name);
+                               CCodeExpression cparam = new CCodeIdentifier (get_variable_cname (param.name));
                                if (param.variable_type.is_real_non_null_struct_type ()) {
                                        cparam = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cparam);
                                }
@@ -238,51 +250,33 @@ public class Vala.GAsyncModule : GSignalModule {
                                        cparam = get_ref_cexpression (param.variable_type, cparam, ma, param);
                                }
 
-                               asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam)));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), cparam));
                                if (param.variable_type is ArrayType) {
                                        var array_type = (ArrayType) param.variable_type;
                                        if (!param.no_array_length) {
                                                for (int dim = 1; dim <= array_type.rank; dim++) {
-                                                       asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim)))));
+                                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_array_length_cname (get_variable_cname (param.name), dim)), new CCodeIdentifier (get_array_length_cname (get_variable_cname (param.name), dim))));
                                                }
                                        }
                                } else if (param.variable_type is DelegateType) {
                                        var deleg_type = (DelegateType) param.variable_type;
                                        if (deleg_type.delegate_symbol.has_target) {
-                                               asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
+                                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)))));
                                                if (deleg_type.value_owned) {
-                                                       asyncblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))))));
+                                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_delegate_target_destroy_notify_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_destroy_notify_cname (get_variable_cname (param.name)))));
                                                }
                                        }
                                }
                        }
                }
 
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-               temp_vars.clear ();
-               asyncblock.add_statement (cfrag);
-
                var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname () + "_co"));
                ccall.add_argument (data_var);
-               asyncblock.add_statement (new CCodeExpressionStatement (ccall));
-
-               cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("_callback_", "GAsyncReadyCallback"));
-               cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("_user_data_", "gpointer"));
-
-               generate_cparameters (m, cfile, cparam_map, asyncfunc, null, null, null, 1);
-
-               if (m.base_method != null || m.base_interface_method != null) {
-                       // declare *_real_* function
-                       asyncfunc.modifiers |= CCodeModifiers.STATIC;
-                       cfile.add_function_declaration (asyncfunc);
-               } else if (m.is_private_symbol ()) {
-                       asyncfunc.modifiers |= CCodeModifiers.STATIC;
-               }
+               ccode.add_expression (ccall);
 
-               asyncfunc.block = asyncblock;
+               cfile.add_function (asyncfunc);
 
-               return asyncfunc;
+               pop_context ();
        }
 
        void append_struct (CCodeStruct structure) {
@@ -293,12 +287,7 @@ public class Vala.GAsyncModule : GSignalModule {
        }
 
        void append_function (CCodeFunction function) {
-               var block = function.block;
-               function.block = null;
                cfile.add_function_declaration (function);
-
-               function.block = block;
                cfile.add_function (function);
        }
 
@@ -347,13 +336,14 @@ public class Vala.GAsyncModule : GSignalModule {
                        if (!m.is_abstract && m.body != null) {
                                var data = generate_data_struct (m);
 
+                               closure_struct = data;
+
                                append_function (generate_free_function (m));
-                               cfile.add_function (generate_async_function (m));
-                               cfile.add_function (generate_finish_function (m));
+                               generate_async_function (m);
+                               generate_finish_function (m);
                                append_function (generate_ready_function (m));
 
                                // append the _co function
-                               closure_struct = data;
                                base.visit_method (m);
                                closure_struct = null;
 
@@ -387,27 +377,33 @@ public class Vala.GAsyncModule : GSignalModule {
        }
 
 
-       CCodeFunction generate_finish_function (Method m) {
+       void generate_finish_function (Method m) {
+               push_context (new EmitContext ());
+
                string dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
 
                var finishfunc = new CCodeFunction (m.get_finish_real_cname ());
 
                var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-               var finishblock = new CCodeBlock ();
+               cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
+
+               generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2);
+
+               if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) {
+                       finishfunc.modifiers |= CCodeModifiers.STATIC;
+               }
+
+               push_function (finishfunc);
 
                var return_type = m.return_type;
                if (!(return_type is VoidType) && !return_type.is_real_non_null_struct_type ()) {
-                       var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
-                       finishblock.add_statement (cdecl);
+                       ccode.add_declaration (m.return_type.get_cname (), new CCodeVariableDeclarator ("result"));
                }
 
                var data_var = new CCodeIdentifier ("_data_");
 
-               var datadecl = new CCodeDeclaration (dataname + "*");
-               datadecl.add_declarator (new CCodeVariableDeclarator ("_data_"));
-               finishblock.add_statement (datadecl);
+               ccode.add_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
 
                var simple_async_result_cast = new CCodeFunctionCall (new CCodeIdentifier ("G_SIMPLE_ASYNC_RESULT"));
                simple_async_result_cast.add_argument (new CCodeIdentifier ("_res_"));
@@ -417,24 +413,25 @@ public class Vala.GAsyncModule : GSignalModule {
                        var propagate_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_propagate_error"));
                        propagate_error.add_argument (simple_async_result_cast);
                        propagate_error.add_argument (new CCodeIdentifier ("error"));
-                       var errorblock = new CCodeBlock ();
+
+                       ccode.open_if (propagate_error);
                        if (return_type is VoidType || return_type.is_real_non_null_struct_type ()) {
-                               errorblock.add_statement (new CCodeReturnStatement ());
+                               ccode.add_return ();
                        } else {
-                               errorblock.add_statement (new CCodeReturnStatement (default_value_for_type (return_type, false)));
+                               ccode.add_return (default_value_for_type (return_type, false));
                        }
-                       finishblock.add_statement (new CCodeIfStatement (propagate_error, errorblock));
+                       ccode.close ();
                }
 
                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_get_op_res_gpointer"));
                ccall.add_argument (simple_async_result_cast);
-               finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (data_var, ccall)));
+               ccode.add_expression (new CCodeAssignment (data_var, ccall));
 
                foreach (FormalParameter param in m.get_parameters ()) {
                        if (param.direction != ParameterDirection.IN) {
-                               finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (param.name)), new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name))));
                                if (!(param.variable_type is ValueType) || param.variable_type.nullable) {
-                                       finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL"))));
+                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL")));
                                }
                        }
                }
@@ -445,41 +442,30 @@ public class Vala.GAsyncModule : GSignalModule {
                        if (requires_copy (return_type)) {
                                cexpr = get_ref_cexpression (return_type, cexpr, null, return_type);
                        }
-                       finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr)));
+                       ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result")), cexpr));
                } else if (!(return_type is VoidType)) {
-                       finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result"))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("result"), new CCodeMemberAccess.pointer (data_var, "result")));
                        if (return_type is ArrayType) {
                                var array_type = (ArrayType) return_type;
                                if (!m.no_array_length) {
                                        for (int dim = 1; dim <= array_type.rank; dim++) {
-                                               finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim)))));
+                                               ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_array_length_cname ("result", dim))), new CCodeMemberAccess.pointer (data_var, get_array_length_cname ("result", dim))));
                                        }
                                }
                        } else if (return_type is DelegateType && ((DelegateType) return_type).delegate_symbol.has_target) {
-                               finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result")))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_delegate_target_cname ("result"))), new CCodeMemberAccess.pointer (data_var, get_delegate_target_cname ("result"))));
                        }
                        if (!(return_type is ValueType) || return_type.nullable) {
-                               finishblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL"))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL")));
                        }
-                       finishblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+                       ccode.add_return (new CCodeIdentifier ("result"));
                }
 
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-               temp_vars.clear ();
-               finishblock.add_statement (cfrag);
-
-               cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("_res_", "GAsyncResult*"));
+               pop_function ();
 
-               generate_cparameters (m, cfile, cparam_map, finishfunc, null, null, null, 2);
+               cfile.add_function (finishfunc);
 
-               if (m.is_private_symbol () || m.base_method != null || m.base_interface_method != null) {
-                       finishfunc.modifiers |= CCodeModifiers.STATIC;
-               }
-
-               finishfunc.block = finishblock;
-
-               return finishfunc;
+               pop_context ();
        }
 
        CCodeFunction generate_ready_function (Method m) {
@@ -550,23 +536,16 @@ public class Vala.GAsyncModule : GSignalModule {
 
        public override void visit_yield_statement (YieldStatement stmt) {
                if (current_method == null || !current_method.coroutine) {
-                       stmt.ccodenode = new CCodeEmptyStatement ();
                        return;
                }
 
                if (stmt.yield_expression == null) {
-                       var cfrag = new CCodeFragment ();
-                       stmt.ccodenode = cfrag;
-
                        int state = next_coroutine_state++;
 
-                       state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
-                       state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state)));
-
-                       cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ()))));
-                       cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-                       cfrag.append (new CCodeLabel ("_state_%d".printf (state)));
-                       cfrag.append (new CCodeEmptyStatement ());
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())));
+                       ccode.add_return (new CCodeConstant ("FALSE"));
+                       ccode.add_label ("_state_%d".printf (state));
+                       ccode.add_statement (new CCodeEmptyStatement ());
 
                        return;
                }
@@ -576,68 +555,44 @@ public class Vala.GAsyncModule : GSignalModule {
                        return;
                }
 
-               stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.yield_expression.ccodenode);
+               ccode.add_expression ((CCodeExpression) stmt.yield_expression.ccodenode);
 
                if (stmt.tree_can_fail && stmt.yield_expression.tree_can_fail) {
                        // simple case, no node breakdown necessary
 
-                       var cfrag = new CCodeFragment ();
-
-                       cfrag.append (stmt.ccodenode);
-
-                       add_simple_check (stmt.yield_expression, cfrag);
-
-                       stmt.ccodenode = cfrag;
+                       add_simple_check (stmt.yield_expression);
                }
 
                /* free temporary objects */
 
-               if (((List<LocalVariable>) temp_vars).size == 0) {
-                       /* nothing to do without temporary variables */
-                       return;
-               }
-               
-               var cfrag = new CCodeFragment ();
-               append_temp_decl (cfrag, temp_vars);
-               
-               cfrag.append (stmt.ccodenode);
-               
                foreach (LocalVariable local in temp_ref_vars) {
                        var ma = new MemberAccess.simple (local.name);
                        ma.symbol_reference = local;
-                       cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma)));
+                       ccode.add_expression (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma));
                }
-               
-               stmt.ccodenode = cfrag;
-               
-               temp_vars.clear ();
+
                temp_ref_vars.clear ();
        }
 
-       public override CCodeStatement return_with_exception (CCodeExpression error_expr)
+       public override void return_with_exception (CCodeExpression error_expr)
        {
                if (!current_method.coroutine) {
-                       return base.return_with_exception (error_expr);
+                       base.return_with_exception (error_expr);
+                       return;
                }
 
-               var block = new CCodeBlock ();
-
                var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_set_from_error"));
                set_error.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_async_result"));
                set_error.add_argument (error_expr);
-               block.add_statement (new CCodeExpressionStatement (set_error));
+               ccode.add_expression (set_error);
 
                var free_error = new CCodeFunctionCall (new CCodeIdentifier ("g_error_free"));
                free_error.add_argument (error_expr);
-               block.add_statement (new CCodeExpressionStatement (free_error));
+               ccode.add_expression (free_error);
 
-               var free_locals = new CCodeFragment ();
-               append_local_free (current_symbol, free_locals, false);
-               block.add_statement (free_locals);
+               append_local_free (current_symbol, false);
 
-               block.add_statement (complete_async ());
-
-               return block;
+               complete_async ();
        }
 
        public override void visit_return_statement (ReturnStatement stmt) {
@@ -647,9 +602,7 @@ public class Vala.GAsyncModule : GSignalModule {
                        return;
                }
 
-               var cfrag = (CCodeFragment) stmt.ccodenode;
-
-               cfrag.append (complete_async ());
+               complete_async ();
        }
 
        public override void generate_cparameters (Method m, CCodeFile decl_space, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
index 19db146a9dc84eb5e917d9f7fca28800e9e80995..ae406e13fc60a33d0aefd97d08eaf09c772c7905 100644 (file)
@@ -81,60 +81,40 @@ public class Vala.GErrorModule : CCodeDelegateModule {
        }
 
        public override void visit_throw_statement (ThrowStatement stmt) {
-               var cfrag = new CCodeFragment ();
-
                // method will fail
                current_method_inner_error = true;
-               var cassign = new CCodeAssignment (get_variable_cexpression ("_inner_error_"), (CCodeExpression) stmt.error_expression.ccodenode);
-               cfrag.append (new CCodeExpressionStatement (cassign));
-
-               add_simple_check (stmt, cfrag, true);
-
-               stmt.ccodenode = cfrag;
+               ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), (CCodeExpression) stmt.error_expression.ccodenode));
 
-               create_temp_decl (stmt, stmt.error_expression.temp_vars);
+               add_simple_check (stmt, true);
        }
 
-       public virtual CCodeStatement return_with_exception (CCodeExpression error_expr)
-       {
+       public virtual void return_with_exception (CCodeExpression error_expr) {
                var cpropagate = new CCodeFunctionCall (new CCodeIdentifier ("g_propagate_error"));
                cpropagate.add_argument (new CCodeIdentifier ("error"));
                cpropagate.add_argument (error_expr);
 
-               var cerror_block = new CCodeBlock ();
-               cerror_block.add_statement (new CCodeExpressionStatement (cpropagate));
+               ccode.add_expression (cpropagate);
 
                // free local variables
-               var free_frag = new CCodeFragment ();
-               append_local_free (current_symbol, free_frag, false);
-               cerror_block.add_statement (free_frag);
+               append_local_free (current_symbol, false);
 
                if (current_method is CreationMethod) {
                        var cl = current_method.parent_symbol as Class;
                        var unref_call = get_unref_expression (new CCodeIdentifier ("self"), new ObjectType (cl), null);
-                       cerror_block.add_statement (new CCodeExpressionStatement (unref_call));
-                       cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
+                       ccode.add_expression (unref_call);
+                       ccode.add_return (new CCodeConstant ("NULL"));
                } else if (current_method != null && current_method.coroutine) {
-                       cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+                       ccode.add_return (new CCodeConstant ("FALSE"));
                } else if (current_return_type is VoidType) {
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_return ();
                } else {
-                       cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+                       ccode.add_return (default_value_for_type (current_return_type, false));
                }
-
-               return cerror_block;
        }
 
-       CCodeStatement uncaught_error_statement (CCodeExpression inner_error, CCodeBlock? block = null, bool unexpected = false) {
-               var cerror_block = block;
-               if (cerror_block == null) {
-                       cerror_block = new CCodeBlock ();
-               }
-
+       void uncaught_error_statement (CCodeExpression inner_error, bool unexpected = false) {
                // free local variables
-               var free_frag = new CCodeFragment ();
-               append_local_free (current_symbol, free_frag, false);
-               cerror_block.add_statement (free_frag);
+               append_local_free (current_symbol, false);
 
                var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
                ccritical.add_argument (new CCodeConstant (unexpected ? "\"file %s: line %d: unexpected error: %s (%s, %d)\"" : "\"file %s: line %d: uncaught error: %s (%s, %d)\""));
@@ -149,24 +129,19 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error"));
                cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, inner_error));
 
-               var cprint_frag = new CCodeFragment ();
-               cprint_frag.append (new CCodeExpressionStatement (ccritical));
-               cprint_frag.append (new CCodeExpressionStatement (cclear));
-
                // print critical message
-               cerror_block.add_statement (cprint_frag);
+               ccode.add_expression (ccritical);
+               ccode.add_expression (cclear);
 
                if (current_method is CreationMethod) {
-                       cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
+                       ccode.add_return (new CCodeConstant ("NULL"));
                } else if (current_method != null && current_method.coroutine) {
-                       cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+                       ccode.add_return (new CCodeConstant ("FALSE"));
                } else if (current_return_type is VoidType) {
-                       cerror_block.add_statement (new CCodeReturnStatement ());
+                       ccode.add_return ();
                } else if (current_return_type != null) {
-                       cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+                       ccode.add_return (default_value_for_type (current_return_type, false));
                }
-
-               return cerror_block;
        }
 
        bool in_finally_block (CodeNode node) {
@@ -181,21 +156,24 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                return false;
        }
 
-       public override void add_simple_check (CodeNode node, CCodeFragment cfrag, bool always_fails = false) {
+       public override void add_simple_check (CodeNode node, bool always_fails = false) {
                current_method_inner_error = true;
 
                var inner_error = get_variable_cexpression ("_inner_error_");
 
-               CCodeStatement cerror_handler = null;
+               if (always_fails) {
+                       // inner_error is always set, avoid unnecessary if statement
+                       // eliminates C warnings
+               } else {
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant ("NULL"));
+                       ccode.open_if (ccond);
+               }
 
                if (current_try != null) {
                        // surrounding try found
-                       var cerror_block = new CCodeBlock ();
 
                        // free local variables
-                       var free_frag = new CCodeFragment ();
-                       append_error_free (current_symbol, free_frag, current_try);
-                       cerror_block.add_statement (free_frag);
+                       append_error_free (current_symbol, current_try);
 
                        var error_types = new ArrayList<DataType> ();
                        foreach (DataType node_error_type in node.get_error_types ()) {
@@ -218,18 +196,13 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                                        }
                                        handled_error_types.clear ();
 
-                                       // go to catch clause if error domain matches
-                                       var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name);
-
                                        if (clause.error_type.equals (gerror_type)) {
                                                // general catch clause, this should be the last one
                                                has_general_catch_clause = true;
-                                               cerror_block.add_statement (cgoto_stmt);
+                                               ccode.add_goto (clause.clabel_name);
                                                break;
                                        } else {
                                                var catch_type = clause.error_type as ErrorType;
-                                               var cgoto_block = new CCodeBlock ();
-                                               cgoto_block.add_statement (cgoto_stmt);
 
                                                if (catch_type.error_code != null) {
                                                        /* catch clause specifies a specific error code */
@@ -238,15 +211,19 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                                                        error_match.add_argument (new CCodeIdentifier (catch_type.data_type.get_upper_case_cname ()));
                                                        error_match.add_argument (new CCodeIdentifier (catch_type.error_code.get_cname ()));
 
-                                                       cerror_block.add_statement (new CCodeIfStatement (error_match, cgoto_block));
+                                                       ccode.open_if (error_match);
                                                } else {
                                                        /* catch clause specifies a full error domain */
                                                        var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY,
                                                                        new CCodeMemberAccess.pointer (inner_error, "domain"), new CCodeIdentifier
                                                                        (clause.error_type.data_type.get_upper_case_cname ()));
 
-                                                       cerror_block.add_statement (new CCodeIfStatement (ccond, cgoto_block));
+                                                       ccode.open_if (ccond);
                                                }
+
+                                               // go to catch clause if error domain matches
+                                               ccode.add_goto (clause.clabel_name);
+                                               ccode.close ();
                                        }
                                }
                        }
@@ -258,16 +235,14 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                        } else if (error_types.size > 0) {
                                // go to finally clause if no catch clause matches
                                // and there are still unhandled error types
-                               cerror_block.add_statement (new CCodeGotoStatement ("__finally%d".printf (current_try_id)));
+                               ccode.add_goto ("__finally%d".printf (current_try_id));
                        } else if (in_finally_block (node)) {
                                // do not check unexpected errors happening within finally blocks
                                // as jump out of finally block is not supported
                        } else {
                                // should never happen with correct bindings
-                               uncaught_error_statement (inner_error, cerror_block, true);
+                               uncaught_error_statement (inner_error, true);
                        }
-
-                       cerror_handler = cerror_block;
                } else if (current_method != null && current_method.get_error_types ().size > 0) {
                        // current method can fail, propagate error
                        CCodeBinaryExpression ccond = null;
@@ -289,26 +264,22 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                                }
                        }
 
-                       if (ccond == null) {
-                               cerror_handler = return_with_exception (inner_error);
+                       if (ccond != null) {
+                               ccode.open_if (ccond);
+                               return_with_exception (inner_error);
+
+                               ccode.add_else ();
+                               uncaught_error_statement (inner_error);
+                               ccode.close ();
                        } else {
-                               var cerror_block = new CCodeBlock ();
-                               cerror_block.add_statement (new CCodeIfStatement (ccond,
-                                       return_with_exception (inner_error),
-                                       uncaught_error_statement (inner_error)));
-                               cerror_handler = cerror_block;
+                               return_with_exception (inner_error);
                        }
                } else {
-                       cerror_handler = uncaught_error_statement (inner_error);
+                       uncaught_error_statement (inner_error);
                }
 
-               if (always_fails) {
-                       // inner_error is always set, avoid unnecessary if statement
-                       // eliminates C warnings
-                       cfrag.append (cerror_handler);
-               } else {
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, inner_error, new CCodeConstant ("NULL"));
-                       cfrag.append (new CCodeIfStatement (ccond, cerror_handler));
+               if (!always_fails) {
+                       ccode.close ();
                }
        }
 
@@ -326,15 +297,12 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                        clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ());
                }
 
-               if (stmt.finally_body != null) {
-                       stmt.finally_body.emit (this);
-               }
-
                is_in_catch = false;
                stmt.body.emit (this);
                is_in_catch = true;
 
                foreach (CatchClause clause in stmt.get_catch_clauses ()) {
+                       ccode.add_goto ("__finally%d".printf (this_try_id));
                        clause.emit (this);
                }
 
@@ -342,24 +310,14 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                current_try_id = old_try_id;
                is_in_catch = old_is_in_catch;
 
-               var cfrag = new CCodeFragment ();
-               cfrag.append (stmt.body.ccodenode);
-
-               foreach (CatchClause clause in stmt.get_catch_clauses ()) {
-                       cfrag.append (new CCodeGotoStatement ("__finally%d".printf (this_try_id)));
-                       cfrag.append (clause.ccodenode);
-               }
-
-               cfrag.append (new CCodeLabel ("__finally%d".printf (this_try_id)));
+               ccode.add_label ("__finally%d".printf (this_try_id));
                if (stmt.finally_body != null) {
-                       cfrag.append (stmt.finally_body.ccodenode);
+                       stmt.finally_body.emit (this);
                }
 
                // check for errors not handled by this try statement
                // may be handled by outer try statements or propagated
-               add_simple_check (stmt, cfrag, !stmt.after_try_block_reachable);
-
-               stmt.ccodenode = cfrag;
+               add_simple_check (stmt, !stmt.after_try_block_reachable);
        }
 
        public override void visit_catch_clause (CatchClause clause) {
@@ -370,12 +328,9 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                        generate_error_domain_declaration (error_type.error_domain, cfile);
                }
 
-               clause.body.emit (this);
-
-               var cfrag = new CCodeFragment ();
-               cfrag.append (new CCodeLabel (clause.clabel_name));
+               ccode.add_label (clause.clabel_name);
 
-               var cblock = new CCodeBlock ();
+               ccode.open_block ();
 
                string variable_name;
                if (clause.variable_name != null) {
@@ -384,31 +339,27 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                        variable_name = "__err";
                }
 
-               if (current_method != null && current_method.coroutine) {
-                       closure_struct.add_field ("GError *", variable_name);
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (variable_name), get_variable_cexpression ("_inner_error_"))));
-               } else {
-                       if (clause.variable_name != null) {
-                               var cdecl = new CCodeDeclaration ("GError *");
-                               cdecl.add_declarator (new CCodeVariableDeclarator (variable_name, get_variable_cexpression ("_inner_error_")));
-                               cblock.add_statement (cdecl);
+               if (clause.variable_name != null) {
+                       if (current_method != null && current_method.coroutine) {
+                               closure_struct.add_field ("GError *", variable_name);
                        } else {
-                               // error object is not used within catch statement, clear it
-                               var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error"));
-                               cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
-                               cblock.add_statement (new CCodeExpressionStatement (cclear));
+                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator (variable_name));
                        }
+                       ccode.add_expression (new CCodeAssignment (get_variable_cexpression (variable_name), get_variable_cexpression ("_inner_error_")));
+               } else {
+                       // error object is not used within catch statement, clear it
+                       var cclear = new CCodeFunctionCall (new CCodeIdentifier ("g_clear_error"));
+                       cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_variable_cexpression ("_inner_error_")));
+                       ccode.add_expression (cclear);
                }
-               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), new CCodeConstant ("NULL"))));
+               ccode.add_expression (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), new CCodeConstant ("NULL")));
 
-               cblock.add_statement (clause.body.ccodenode);
-
-               cfrag.append (cblock);
+               clause.body.emit (this);
 
-               clause.ccodenode = cfrag;
+               ccode.close ();
        }
 
-       public override void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop = false) {
+       public override void append_local_free (Symbol sym, bool stop_at_loop = false) {
                var finally_block = (Block) null;
                if (sym.parent_node is TryStatement) {
                        finally_block = (sym.parent_node as TryStatement).finally_body;
@@ -417,10 +368,10 @@ public class Vala.GErrorModule : CCodeDelegateModule {
                }
 
                if (finally_block != null) {
-                       cfrag.append (finally_block.ccodenode);
+                       finally_block.emit (this);
                }
 
-               base.append_local_free (sym, cfrag, stop_at_loop);
+               base.append_local_free (sym, stop_at_loop);
        }
 }
 
index ef7e11fe73346f6137d142d062056a74a4043d83..d181108116158e916c3aa36c6d69caa9726ddc7b 100644 (file)
@@ -42,7 +42,7 @@ public class Vala.GObjectModule : GTypeModule {
                }
        }
 
-       public override void generate_class_init (Class cl, CCodeBlock init_block) {
+       public override void generate_class_init (Class cl) {
                if (!cl.is_subtype_of (gobject_type)) {
                        return;
                }
@@ -51,24 +51,24 @@ public class Vala.GObjectModule : GTypeModule {
                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
                ccall.add_argument (new CCodeIdentifier ("klass"));
                if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (cl.get_lower_case_cname (null))))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("_vala_%s_get_property".printf (cl.get_lower_case_cname (null)))));
                }
                if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) {
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (cl.get_lower_case_cname (null))))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("_vala_%s_set_property".printf (cl.get_lower_case_cname (null)))));
                }
        
                /* set constructor */
                if (cl.constructor != null) {
                        var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
                        ccast.add_argument (new CCodeIdentifier ("klass"));
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null))))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null)))));
                }
 
                /* set finalize function */
                if (cl.get_fields ().size > 0 || cl.destructor != null) {
                        var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
                        ccast.add_argument (new CCodeIdentifier ("klass"));
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null))))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null)))));
                }
 
                /* create type, dup_func, and destroy_func properties for generic types */
@@ -90,7 +90,7 @@ public class Vala.GObjectModule : GTypeModule {
                        cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
                        cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                        cinst.add_argument (cspec);
-                       init_block.add_statement (new CCodeExpressionStatement (cinst));
+                       ccode.add_expression (cinst);
                        prop_enum.add_value (new CCodeEnumValue (enum_value));
 
 
@@ -106,7 +106,7 @@ public class Vala.GObjectModule : GTypeModule {
                        cspec.add_argument (new CCodeConstant ("\"dup func\""));
                        cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                        cinst.add_argument (cspec);
-                       init_block.add_statement (new CCodeExpressionStatement (cinst));
+                       ccode.add_expression (cinst);
                        prop_enum.add_value (new CCodeEnumValue (enum_value));
 
 
@@ -122,7 +122,7 @@ public class Vala.GObjectModule : GTypeModule {
                        cspec.add_argument (new CCodeConstant ("\"destroy func\""));
                        cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY"));
                        cinst.add_argument (cspec);
-                       init_block.add_statement (new CCodeExpressionStatement (cinst));
+                       ccode.add_expression (cinst);
                        prop_enum.add_value (new CCodeEnumValue (enum_value));
                }
 
@@ -134,7 +134,7 @@ public class Vala.GObjectModule : GTypeModule {
                        }
 
                        if (prop.comment != null) {
-                               init_block.add_statement (new CCodeComment (prop.comment.content));
+                               ccode.add_statement (new CCodeComment (prop.comment.content));
                        }
 
                        if (prop.overrides || prop.base_interface_property != null) {
@@ -143,14 +143,14 @@ public class Vala.GObjectModule : GTypeModule {
                                cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ()));
                                cinst.add_argument (prop.get_canonical_cconstant ());
                        
-                               init_block.add_statement (new CCodeExpressionStatement (cinst));
+                               ccode.add_expression (cinst);
                        } else {
                                var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property"));
                                cinst.add_argument (ccall);
                                cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ()));
                                cinst.add_argument (get_param_spec (prop));
                        
-                               init_block.add_statement (new CCodeExpressionStatement (cinst));
+                               ccode.add_expression (cinst);
                        }
                }
        }
@@ -412,18 +412,11 @@ public class Vala.GObjectModule : GTypeModule {
        }
 
        public override void visit_constructor (Constructor c) {
-               bool old_method_inner_error = current_method_inner_error;
-               current_method_inner_error = false;
-
                if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
                        in_static_or_class_context = true;
                } else {
                        in_constructor = true;
                }
-               c.body.emit (this);
-               in_static_or_class_context = false;
-
-               in_constructor = false;
 
                var cl = (Class) c.parent_symbol;
 
@@ -434,7 +427,9 @@ public class Vala.GObjectModule : GTypeModule {
                                return;
                        }
 
-                       function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
+                       push_context (new EmitContext (c));
+
+                       var function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
                        function.modifiers = CCodeModifiers.STATIC;
                
                        function.add_parameter (new CCodeFormalParameter ("type", "GType"));
@@ -443,52 +438,43 @@ public class Vala.GObjectModule : GTypeModule {
                
                        cfile.add_function_declaration (function);
 
+                       push_function (function);
 
-                       var cblock = new CCodeBlock ();
-                       var cdecl = new CCodeDeclaration ("GObject *");
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
-                       cblock.add_statement (cdecl);
-
-                       cdecl = new CCodeDeclaration ("GObjectClass *");
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
-                       cblock.add_statement (cdecl);
-
+                       ccode.add_declaration ("GObject *", new CCodeVariableDeclarator ("obj"));
+                       ccode.add_declaration ("GObjectClass *", new CCodeVariableDeclarator ("parent_class"));
 
                        var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
                        ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast));
 
-               
                        var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
                        ccall.add_argument (new CCodeIdentifier ("type"));
                        ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
                        ccall.add_argument (new CCodeIdentifier ("construct_properties"));
-                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall));
 
 
                        ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
 
-                       cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall));
-                       cblock.add_statement (cdecl);
+                       ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall));
 
                        if (current_method_inner_error) {
                                /* always separate error parameter and inner_error local variable
                                 * as error may be set to NULL but we're always interested in inner errors
                                 */
-                               cdecl = new CCodeDeclaration ("GError *");
-                               cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
-                               cblock.add_statement (cdecl);
+                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
                        }
 
 
-                       cblock.add_statement (c.body.ccodenode);
-               
-                       cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
+                       c.body.emit (this);
                
-                       function.block = cblock;
+                       ccode.add_return (new CCodeIdentifier ("obj"));
 
+                       pop_function ();
                        cfile.add_function (function);
+
+                       pop_context ();
                } else if (c.binding == MemberBinding.CLASS) {
                        // class constructor
 
@@ -498,16 +484,18 @@ public class Vala.GObjectModule : GTypeModule {
                                return;
                        }
 
+                       push_context (base_init_context);
+
+                       c.body.emit (this);
+
                        if (current_method_inner_error) {
                                /* always separate error parameter and inner_error local variable
                                 * as error may be set to NULL but we're always interested in inner errors
                                 */
-                               var cdecl = new CCodeDeclaration ("GError *");
-                               cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
-                               base_init_fragment.append (cdecl);
+                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
                        }
 
-                       base_init_fragment.append (c.body.ccodenode);
+                       pop_context ();
                } else if (c.binding == MemberBinding.STATIC) {
                        // static class constructor
                        // add to class_init
@@ -518,21 +506,25 @@ public class Vala.GObjectModule : GTypeModule {
                                return;
                        }
 
+                       push_context (class_init_context);
+
+                       c.body.emit (this);
+
                        if (current_method_inner_error) {
                                /* always separate error parameter and inner_error local variable
                                 * as error may be set to NULL but we're always interested in inner errors
                                 */
-                               var cdecl = new CCodeDeclaration ("GError *");
-                               cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
-                               class_init_fragment.append (cdecl);
+                               ccode.add_declaration ("GError *", new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
                        }
 
-                       class_init_fragment.append (c.body.ccodenode);
+                       pop_context ();
                } else {
                        Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
                }
 
-               current_method_inner_error = old_method_inner_error;
+               in_static_or_class_context = false;
+
+               in_constructor = false;
        }
 
        public override string get_dynamic_property_getter_cname (DynamicProperty prop) {
@@ -756,7 +748,7 @@ public class Vala.GObjectModule : GTypeModule {
 
                                var ccomma = new CCodeCommaExpression ();
                                var temp_var = get_temp_variable (expr.value_type, false, expr, false);
-                               temp_vars.add (temp_var);
+                               emit_temp_var (temp_var);
                                ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), (CCodeExpression) expr.ccodenode));
 
                                var initiallyunowned_ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_INITIALLY_UNOWNED"));
index e2b0de89a91d885a74a20184f61b015b606292bf..8b90ef4c063650a6bc8a7ed8c0fc66e75f496172 100644 (file)
@@ -164,7 +164,7 @@ public class Vala.GSignalModule : GObjectModule {
                }
 
                var detail_decl = get_temp_variable (detail_expr.value_type, true, node);
-               temp_vars.insert (0, detail_decl);
+               emit_temp_var (detail_decl);
                temp_ref_vars.insert (0, detail_decl);
 
                var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
@@ -679,7 +679,7 @@ public class Vala.GSignalModule : GObjectModule {
                        // get signal id
                        ccomma = new CCodeCommaExpression ();
                        var temp_decl = get_temp_variable (uint_type);
-                       temp_vars.add (temp_decl);
+                       emit_temp_var (temp_decl);
                        var parse_call = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_parse_name"));
                        parse_call.add_argument (signal_name_cexpr);
                        var decl_type = (TypeSymbol) sig.parent_symbol;
@@ -691,7 +691,7 @@ public class Vala.GSignalModule : GObjectModule {
                                parse_call.add_argument (new CCodeConstant ("FALSE"));
                        } else {
                                detail_temp_decl = get_temp_variable (gquark_type);
-                               temp_vars.add (detail_temp_decl);
+                               emit_temp_var (detail_temp_decl);
                                parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (detail_temp_decl.name)));
                                parse_call.add_argument (new CCodeConstant ("TRUE"));
                        }
index a6c1ebd4a95550b409a21d05490f65aeaeae2b33..d6da086183f317ef68a19a123dcbff4a1ad9296d 100644 (file)
@@ -516,12 +516,12 @@ public class Vala.GTypeModule : GErrorModule {
 
                var old_param_spec_struct = param_spec_struct;
                var old_prop_enum = prop_enum;
-               var old_class_init_fragment = class_init_fragment;
-               var old_base_init_fragment = base_init_fragment;
-               var old_class_finalize_fragment = class_finalize_fragment;
-               var old_base_finalize_fragment = base_finalize_fragment;
-               var old_instance_init_fragment = instance_init_fragment;
-               var old_instance_finalize_fragment = instance_finalize_fragment;
+               var old_class_init_context = class_init_context;
+               var old_base_init_context = base_init_context;
+               var old_class_finalize_context = class_finalize_context;
+               var old_base_finalize_context = base_finalize_context;
+               var old_instance_init_context = instance_init_context;
+               var old_instance_finalize_context = instance_finalize_context;
 
                bool is_gtypeinstance = !cl.is_compact;
                bool is_fundamental = is_gtypeinstance && cl.base_class == null;
@@ -534,12 +534,12 @@ public class Vala.GTypeModule : GErrorModule {
 
                prop_enum = new CCodeEnum ();
                prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
-               class_init_fragment = new CCodeFragment ();
-               base_init_fragment = new CCodeFragment ();
-               class_finalize_fragment = new CCodeFragment ();
-               base_finalize_fragment = new CCodeFragment ();
-               instance_init_fragment = new CCodeFragment ();
-               instance_finalize_fragment = new CCodeFragment ();
+               class_init_context = new EmitContext (cl);
+               base_init_context = new EmitContext (cl);
+               class_finalize_context = new EmitContext (cl);
+               base_finalize_context = new EmitContext (cl);
+               instance_init_context = new EmitContext (cl);
+               instance_finalize_context = new EmitContext (cl);
 
 
                generate_class_struct_declaration (cl, cfile);
@@ -552,6 +552,21 @@ public class Vala.GTypeModule : GErrorModule {
                        generate_class_struct_declaration (cl, internal_header_file);
                }
 
+               if (is_gtypeinstance) {
+                       begin_base_init_function (cl);
+                       begin_class_init_function (cl);
+                       begin_instance_init_function (cl);
+
+                       begin_base_finalize_function (cl);
+                       begin_class_finalize_function (cl);
+                       begin_finalize_function (cl);
+               } else {
+                       if (cl.base_class == null) {
+                               begin_instance_init_function (cl);
+                               begin_finalize_function (cl);
+                       }
+               }
+
                cl.accept_children (this);
 
                if (is_gtypeinstance) {
@@ -577,7 +592,7 @@ public class Vala.GTypeModule : GErrorModule {
                                add_g_value_take_function (cl);
 
                                var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
-                               instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
+                               instance_init_context.ccode.add_expression (ref_count);
                        }
 
 
@@ -672,41 +687,18 @@ public class Vala.GTypeModule : GErrorModule {
                        if (cl.base_class == null) {
                                // derived compact classes do not have fields
                                add_instance_init_function (cl);
-
-                               var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
-                               if (cl.access == SymbolAccessibility.PRIVATE) {
-                                       function.modifiers = CCodeModifiers.STATIC;
-                               }
-
-                               function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
-
-                               var cblock = new CCodeBlock ();
-
-                               if (cl.destructor != null) {
-                                       cblock.add_statement (cl.destructor.ccodenode);
-                               }
-
-                               cblock.add_statement (instance_finalize_fragment);
-
-                               var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
-                               ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
-                               ccall.add_argument (new CCodeIdentifier ("self"));
-                               cblock.add_statement (new CCodeExpressionStatement (ccall));
-
-                               function.block = cblock;
-
-                               cfile.add_function (function);
+                               add_finalize_function (cl);
                        }
                }
 
                param_spec_struct = old_param_spec_struct;
                prop_enum = old_prop_enum;
-               class_init_fragment = old_class_init_fragment;
-               base_init_fragment = old_base_init_fragment;
-               class_finalize_fragment = old_class_finalize_fragment;
-               base_finalize_fragment = old_base_finalize_fragment;
-               instance_init_fragment = old_instance_init_fragment;
-               instance_finalize_fragment = old_instance_finalize_fragment;
+               class_init_context = old_class_init_context;
+               base_init_context = old_base_init_context;
+               class_finalize_context = old_class_finalize_context;
+               base_finalize_context = old_base_finalize_context;
+               instance_init_context = old_instance_init_context;
+               instance_finalize_context = old_instance_finalize_context;
 
                pop_context ();
        }
@@ -1133,31 +1125,31 @@ public class Vala.GTypeModule : GErrorModule {
                cfile.add_function (function);
        }
 
-       private void add_base_init_function (Class cl) {
+       private void begin_base_init_function (Class cl) {
+               push_context (base_init_context);
+
                var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
                base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
                base_init.modifiers = CCodeModifiers.STATIC;
 
-               var init_block = new CCodeBlock ();
-               base_init.block = init_block;
+               push_function (base_init);
 
                if (!context.require_glib_version (2, 24) && cl.has_class_private_fields) {
-                       var block = new CCodeBlock ();
                        var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
                        cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
-                       block.add_statement (cdecl);
+                       ccode.add_statement (cdecl);
                        cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
                        cdecl.add_declarator (new CCodeVariableDeclarator ("parent_priv", new CCodeConstant ("NULL")));
-                       block.add_statement (cdecl);
+                       ccode.add_statement (cdecl);
                        cdecl = new CCodeDeclaration ("GType");
                        cdecl.add_declarator (new CCodeVariableDeclarator ("parent_type"));
-                       block.add_statement (cdecl);
+                       ccode.add_statement (cdecl);
 
                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_parent"));
                        var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
                        ccall2.add_argument (new CCodeIdentifier ("klass"));
                        ccall.add_argument (ccall2);
-                       block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall)));
+                       ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall)));
 
                        var iftrue = new CCodeBlock ();
                        ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
@@ -1165,12 +1157,12 @@ public class Vala.GTypeModule : GErrorModule {
                        ccall2.add_argument (new CCodeIdentifier ("parent_type"));
                        ccall.add_argument (ccall2);
                        iftrue.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_priv"), ccall)));
-                       block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue));
+                       ccode.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue));
 
                        ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
                        ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf(cl.get_cname())));
 
-                       block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
+                       ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
 
                        cfile.add_include ("string.h");
 
@@ -1181,7 +1173,7 @@ public class Vala.GTypeModule : GErrorModule {
                        ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname())));
                        iftrue.add_statement (new CCodeExpressionStatement (ccall));
 
-                       block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue));
+                       ccode.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue));
 
                        ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata"));
                        ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS"));
@@ -1189,42 +1181,26 @@ public class Vala.GTypeModule : GErrorModule {
                        ccall.add_argument (ccall2);
                        ccall.add_argument (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ())));
                        ccall.add_argument (new CCodeIdentifier ("priv"));
-                       block.add_statement (new CCodeExpressionStatement (ccall));
-
-                       init_block.add_statement (block);
-
-                       block = new CCodeBlock ();
-                       cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
-                       cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
-                       block.add_statement (cdecl);
-
-                       ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
-                       ccall.add_argument (new CCodeConstant ("klass"));
-                       block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
-
-                       ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
-                       ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ())));
-                       ccall.add_argument (new CCodeIdentifier ("priv"));
-                       block.add_statement (new CCodeExpressionStatement (ccall));
-                       base_finalize_fragment.append (block);
+                       ccode.add_statement (new CCodeExpressionStatement (ccall));
                }
 
-               init_block.add_statement (base_init_fragment);
+               pop_context ();
+       }
 
-               cfile.add_function (base_init);
+       private void add_base_init_function (Class cl) {
+               cfile.add_function (base_init_context.ccode);
        }
 
-       public virtual void generate_class_init (Class cl, CCodeBlock init_block) {
+       public virtual void generate_class_init (Class cl) {
        }
 
-       private void add_class_init_function (Class cl) {
-               var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void");
-               class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
-               class_init.modifiers = CCodeModifiers.STATIC;
+       private void begin_class_init_function (Class cl) {
+               push_context (class_init_context);
+
+               var func = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)));
+               func.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
+               func.modifiers = CCodeModifiers.STATIC;
 
-               var init_block = new CCodeBlock ();
-               class_init.block = init_block;
-               
                CCodeFunctionCall ccall;
                
                /* save pointer to parent class */
@@ -1234,10 +1210,13 @@ public class Vala.GTypeModule : GErrorModule {
                parent_decl.add_declarator (parent_var_decl);
                parent_decl.modifiers = CCodeModifiers.STATIC;
                cfile.add_type_member_declaration (parent_decl);
+
+               push_function (func);
+
                ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
                ccall.add_argument (new CCodeIdentifier ("klass"));
                var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall);
-               init_block.add_statement (new CCodeExpressionStatement (parent_assignment));
+               ccode.add_expression (parent_assignment);
                
 
                if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
@@ -1250,7 +1229,7 @@ public class Vala.GTypeModule : GErrorModule {
                        ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null))));
                        ccall.add_argument (new CCodeIdentifier ("klass"));
                        var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize"));
-                       init_block.add_statement (new CCodeExpressionStatement (finalize_assignment));
+                       ccode.add_expression (finalize_assignment);
                }
 
                /* add struct for private fields */
@@ -1258,7 +1237,7 @@ public class Vala.GTypeModule : GErrorModule {
                        ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private"));
                        ccall.add_argument (new CCodeIdentifier ("klass"));
                        ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ())));
-                       init_block.add_statement (new CCodeExpressionStatement (ccall));
+                       ccode.add_expression (ccall);
                }
 
                /* connect overridden methods */
@@ -1273,10 +1252,10 @@ public class Vala.GTypeModule : GErrorModule {
                                var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
                                ccast.add_argument (new CCodeIdentifier ("klass"));
 
-                               init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ())));
 
                                if (m.coroutine) {
-                                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ()))));
+                                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ())));
                                }
                        }
                }
@@ -1288,7 +1267,7 @@ public class Vala.GTypeModule : GErrorModule {
                        }
                        var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
                        ccast.add_argument (new CCodeIdentifier ("klass"));
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))));
+                       ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ())));
                }
 
                /* connect overridden properties */
@@ -1303,30 +1282,33 @@ public class Vala.GTypeModule : GErrorModule {
 
                        if (prop.get_accessor != null) {
                                string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name);
-                               init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)));
                        }
                        if (prop.set_accessor != null) {
                                string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name);
-                               init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname))));
+                               ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)));
                        }
                }
 
-               generate_class_init (cl, init_block);
+               generate_class_init (cl);
 
                if (!cl.is_compact) {
                        /* create signals */
                        foreach (Signal sig in cl.get_signals ()) {
                                if (sig.comment != null) {
-                                       init_block.add_statement (new CCodeComment (sig.comment.content));
+                                       ccode.add_statement (new CCodeComment (sig.comment.content));
                                }
-                               init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, cl)));
+                               ccode.add_expression (get_signal_creation (sig, cl));
                        }
                }
 
-               init_block.add_statement (register_dbus_info (cl));
-               init_block.add_statement (class_init_fragment);
+               register_dbus_info (cl);
 
-               cfile.add_function (class_init);
+               pop_context ();
+       }
+
+       private void add_class_init_function (Class cl) {
+               cfile.add_function (class_init_context.ccode);
        }
        
        private void add_interface_init_function (Class cl, Interface iface) {
@@ -1540,111 +1522,167 @@ public class Vala.GTypeModule : GErrorModule {
                return new CCodeCastExpression (cfunc, cast);
        }
 
-       private void add_instance_init_function (Class cl) {
-               var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void");
-               instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ())));
-               instance_init.modifiers = CCodeModifiers.STATIC;
-               
+       private void begin_instance_init_function (Class cl) {
+               push_context (instance_init_context);
+
+               var func = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)));
+               func.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ())));
+               func.modifiers = CCodeModifiers.STATIC;
+
+               push_function (func);
+
                if (cl.is_compact) {
                        // Add declaration, since the instance_init function is explicitly called
                        // by the creation methods
-                       cfile.add_function_declaration (instance_init);
+                       cfile.add_function_declaration (func);
                }
 
-               var init_block = new CCodeBlock ();
-               instance_init.block = init_block;
-               
                if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) {
                        var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null))));
                        ccall.add_argument (new CCodeIdentifier ("self"));
-                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
+                       func.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall));
                }
-               
-               init_block.add_statement (instance_init_fragment);
 
-               cfile.add_function (instance_init);
+               pop_context ();
        }
 
-       private void add_class_finalize_function (Class cl) {
+       private void add_instance_init_function (Class cl) {
+               cfile.add_function (instance_init_context.ccode);
+       }
+
+       private void begin_class_finalize_function (Class cl) {
+               push_context (class_finalize_context);
+
                var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void");
                function.modifiers = CCodeModifiers.STATIC;
 
                function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *"));
-               cfile.add_function_declaration (function);
-               
-               var cblock = new CCodeBlock ();
+
+               push_function (function);
 
                if (cl.class_destructor != null) {
-                       cblock.add_statement (cl.class_destructor.ccodenode);
+                       cl.class_destructor.body.emit (this);
                }
 
-               cblock.add_statement (class_finalize_fragment);
+               pop_context ();
+       }
 
-               function.block = cblock;
-               cfile.add_function (function);
+       private void add_class_finalize_function (Class cl) {
+               cfile.add_function_declaration (class_finalize_context.ccode);
+               cfile.add_function (class_finalize_context.ccode);
        }
 
-       private void add_base_finalize_function (Class cl) {
+       private void begin_base_finalize_function (Class cl) {
+               push_context (base_finalize_context);
+
                var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void");
                function.modifiers = CCodeModifiers.STATIC;
 
                function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *"));
-               cfile.add_function_declaration (function);
-               
-               var cblock = new CCodeBlock ();
+
+               push_function (function);
 
                if (cl.class_destructor != null) {
-                       cblock.add_statement (cl.class_destructor.ccodenode);
+                       cl.class_destructor.body.emit (this);
                }
 
-               cblock.add_statement (base_finalize_fragment);
-
-               function.block = cblock;
-               cfile.add_function (function);
+               pop_context ();
        }
 
-       private void add_finalize_function (Class cl) {
-               var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void");
-               function.modifiers = CCodeModifiers.STATIC;
+       private void add_base_finalize_function (Class cl) {
+               push_context (base_finalize_context);
+
+               if (!context.require_glib_version (2, 24) && cl.has_class_private_fields) {
+                       ccode.open_block ();
+
+                       var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ()));
+                       cdecl.add_declarator (new CCodeVariableDeclarator ("priv"));
+                       ccode.add_statement (cdecl);
+
+                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null))));
+                       ccall.add_argument (new CCodeConstant ("klass"));
+                       ccode.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall)));
+
+                       ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
+                       ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ())));
+                       ccall.add_argument (new CCodeIdentifier ("priv"));
+                       ccode.add_statement (new CCodeExpressionStatement (ccall));
 
-               var fundamental_class = cl;
-               while (fundamental_class.base_class != null) {
-                       fundamental_class = fundamental_class.base_class;
+                       ccode.close ();
                }
 
-               function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
+               cfile.add_function_declaration (ccode);
+               cfile.add_function (ccode);
 
-               cfile.add_function_declaration (function);
+               pop_context ();
+       }
 
+       private void begin_finalize_function (Class cl) {
+               push_context (instance_finalize_context);
 
-               var cblock = new CCodeBlock ();
+               if (!cl.is_compact) {
+                       var fundamental_class = cl;
+                       while (fundamental_class.base_class != null) {
+                               fundamental_class = fundamental_class.base_class;
+                       }
 
-               CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
+                       var func = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)));
+                       func.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
+                       func.modifiers = CCodeModifiers.STATIC;
 
-               var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-               cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall));
-               
-               cblock.add_statement (cdecl);
+                       push_function (func);
 
-               if (cl.destructor != null) {
-                       cblock.add_statement (cl.destructor.ccodenode);
-               }
+                       CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
 
-               cblock.add_statement (instance_finalize_fragment);
+                       ccode.add_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+                       ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall));
 
-               // chain up to finalize function of the base class
-               if (cl.base_class != null) {
-                       var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ())));
-                       ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
-                       ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
-                       ccall.add_argument (new CCodeIdentifier ("obj"));
-                       cblock.add_statement (new CCodeExpressionStatement (ccall));
+                       if (cl.destructor != null) {
+                               cl.destructor.body.emit (this);
+                       }
+               } else {
+                       var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void");
+                       if (cl.access == SymbolAccessibility.PRIVATE) {
+                               function.modifiers = CCodeModifiers.STATIC;
+                       }
+
+                       function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
+
+                       push_function (function);
+
+                       if (cl.destructor != null) {
+                               cl.destructor.body.emit (this);
+                       }
                }
 
+               pop_context ();
+       }
 
-               function.block = cblock;
+       private void add_finalize_function (Class cl) {
+               if (!cl.is_compact) {
+                       var fundamental_class = cl;
+                       while (fundamental_class.base_class != null) {
+                               fundamental_class = fundamental_class.base_class;
+                       }
 
-               cfile.add_function (function);
+                       // chain up to finalize function of the base class
+                       if (cl.base_class != null) {
+                               var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ())));
+                               ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))));
+                               var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
+                               ccall.add_argument (new CCodeIdentifier ("obj"));
+                               instance_finalize_context.ccode.add_expression (ccall);
+                       }
+
+                       cfile.add_function_declaration (instance_finalize_context.ccode);
+               } else {
+                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
+                       ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
+                       ccall.add_argument (new CCodeIdentifier ("self"));
+                       instance_finalize_context.ccode.add_expression (ccall);
+               }
+
+               cfile.add_function (instance_finalize_context.ccode);
        }
 
        public override CCodeFunctionCall get_param_spec (Property prop) {
@@ -1687,7 +1725,7 @@ public class Vala.GTypeModule : GErrorModule {
                        }
 
                        if (prop.initializer != null) {
-                               cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                               cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                        } else {
                                cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ()));
                        }
@@ -1698,7 +1736,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("G_MININT"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
@@ -1707,7 +1745,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0U"));
                                }
@@ -1716,7 +1754,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("G_MININT64"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT64"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
@@ -1725,7 +1763,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT64"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0U"));
                                }
@@ -1734,7 +1772,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("G_MINLONG"));
                                cspec.add_argument (new CCodeConstant ("G_MAXLONG"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0L"));
                                }
@@ -1743,14 +1781,14 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXULONG"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0UL"));
                                }
                        } else if (st.get_type_id () == "G_TYPE_BOOLEAN") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_boolean");
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("FALSE"));
                                }
@@ -1759,7 +1797,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("G_MININT8"));
                                cspec.add_argument (new CCodeConstant ("G_MAXINT8"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
@@ -1768,7 +1806,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("0"));
                                cspec.add_argument (new CCodeConstant ("G_MAXUINT8"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0"));
                                }
@@ -1777,7 +1815,7 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT"));
                                cspec.add_argument (new CCodeConstant ("G_MAXFLOAT"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0.0F"));
                                }
@@ -1786,14 +1824,14 @@ public class Vala.GTypeModule : GErrorModule {
                                cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE"));
                                cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE"));
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("0.0"));
                                }
                        } else if (st.get_type_id () == "G_TYPE_GTYPE") {
                                cspec.call = new CCodeIdentifier ("g_param_spec_gtype");
                                if (prop.initializer != null) {
-                                       cspec.add_argument ((CCodeExpression) prop.initializer.ccodenode);
+                                       cspec.add_argument ((CCodeExpression) get_ccodenode (prop.initializer));
                                } else {
                                        cspec.add_argument (new CCodeConstant ("G_TYPE_NONE"));
                                }
@@ -2065,7 +2103,7 @@ public class Vala.GTypeModule : GErrorModule {
 
                var ccomma = new CCodeCommaExpression ();
                var temp_var = get_temp_variable (new CType ("GEnumValue*"), false, expr, false);
-               temp_vars.add (temp_var);
+               emit_temp_var (temp_var);
 
                var class_ref = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_ref"));
                class_ref.add_argument (new CCodeIdentifier (ma.inner.value_type.get_type_id ()));
index 64cbfaab73f05009a1a49c8c9f25c268a62da4c2..d7b35f28f8f5f52b93669b0f3678ad8ba8150f8e 100644 (file)
@@ -165,6 +165,7 @@ public class Vala.Block : Symbol, Statement {
                                for (int j = 0; j < stmt_list.length; j++) {
                                        if (stmt_list.get (j) == stmt) {
                                                stmt_list.insert (j, new_stmt);
+                                               new_stmt.parent_node = this;
                                                break;
                                        }
                                }
@@ -173,6 +174,7 @@ public class Vala.Block : Symbol, Statement {
                                stmt_list.add (new_stmt);
                                stmt_list.add (stmt);
                                statement_list[i] = stmt_list;
+                               new_stmt.parent_node = this;
                        }
                }
        }
@@ -184,11 +186,13 @@ public class Vala.Block : Symbol, Statement {
                                for (int j = 0; j < stmt_list.length; j++) {
                                        if (stmt_list.get (j) == old_stmt) {
                                                stmt_list.set (j, new_stmt);
+                                               new_stmt.parent_node = this;
                                                break;
                                        }
                                }
                        } else if (statement_list[i] == old_stmt) {
                                statement_list[i] = new_stmt;
+                               new_stmt.parent_node = this;
                                break;
                        }
                }
index 23c01e2910a4b0de0bb3795d104af4684951dde8..eafb202d8c055338198b3508148af32f006f3fcd 100644 (file)
@@ -1,6 +1,6 @@
 /* valaexpression.vala
  *
- * Copyright (C) 2006-2009  Jürg Billeter
+ * Copyright (C) 2006-2010  Jürg Billeter
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -55,14 +55,6 @@ public abstract class Vala.Expression : CodeNode {
         */
        public bool lvalue { get; set; }
 
-       /**
-        * Contains all temporary variables this expression requires for
-        * execution.
-        *
-        * The code generator sets and uses them for memory management.
-        */
-       public ArrayList<LocalVariable> temp_vars;
-
        private List<CCodeExpression> array_sizes;
 
        public CCodeExpression? delegate_target { get; set; }
@@ -89,13 +81,6 @@ public abstract class Vala.Expression : CodeNode {
                return false;
        }
 
-       public void add_temp_var (LocalVariable local) {
-               if (temp_vars == null) {
-                       temp_vars = new ArrayList<LocalVariable> ();
-               }
-               temp_vars.add (local);
-       }
-
        /**
         * Add an array size C code expression.
         */
index a29ab05921485bb3a295a97012a6cf15af1fa24e..bc6510e2339b9609c540b5cac4911406704dc6f1 100644 (file)
@@ -233,6 +233,8 @@ public class Vala.Method : Symbol {
 
        public bool is_async_callback { get; set; }
 
+       public int yield_count { get; set; }
+
        private List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
        private string cname;
        private string finish_name;
index a493c56cd0c7feda28d3bbd5af80bbf8a0cb13a8..23a109a49e6de3605194b039a2a45d4a93fa0e45 100644 (file)
@@ -538,6 +538,7 @@ public class Vala.MethodCall : Expression {
                                        error = true;
                                        Report.error (source_reference, "yield expression not available outside async method");
                                }
+                               analyzer.current_method.yield_count++;
                        }
                        if (m != null && m.coroutine && !is_yield_expression && ((MemberAccess) call).member_name != "end") {
                                // .begin call of async method, no error can happen here
index be526a1dea6152e11b7fcc69015fb2d020f8d4d4..0fd6e34545a18a54354725a63c1b008c07024652 100644 (file)
@@ -75,6 +75,8 @@ public class Vala.YieldStatement : CodeNode, Statement {
                        error = yield_expression.error;
                }
 
+               analyzer.current_method.yield_count++;
+
                return !error;
        }