[vala] codegen: Use builder API



commit 7a429688cdf0fd16cc1503a7666681792e309da8
Author: Jürg Billeter <j bitron ch>
Date:   Sat Aug 14 15:24:18 2010 +0200

    codegen: Use builder API

 codegen/valaccodearraymodule.vala        |   84 ++---
 codegen/valaccodeassignmentmodule.vala   |    4 +-
 codegen/valaccodebasemodule.vala         |  634 +++++++++++-------------------
 codegen/valaccodecontrolflowmodule.vala  |  295 +++++---------
 codegen/valaccodememberaccessmodule.vala |   12 +-
 codegen/valaccodemethodcallmodule.vala   |   47 +--
 codegen/valaccodemethodmodule.vala       |  345 ++++++++---------
 codegen/valaccodestructmodule.vala       |   25 +-
 codegen/valadovaarraymodule.vala         |    2 +-
 codegen/valadovaassignmentmodule.vala    |    4 +-
 codegen/valadovabasemodule.vala          |  409 ++++++--------------
 codegen/valadovacontrolflowmodule.vala   |   54 +--
 codegen/valadovaerrormodule.vala         |  153 +++-----
 codegen/valadovamemberaccessmodule.vala  |    2 +-
 codegen/valadovamethodcallmodule.vala    |   10 +-
 codegen/valadovaobjectmodule.vala        |  142 ++++---
 codegen/valadovastructmodule.vala        |    5 -
 codegen/valadovavaluemodule.vala         |   17 +-
 codegen/valagasyncmodule.vala            |  221 ++++-------
 codegen/valagerrormodule.vala            |  187 ++++------
 codegen/valagobjectmodule.vala           |   94 ++---
 codegen/valagsignalmodule.vala           |    6 +-
 codegen/valagtypemodule.vala             |  372 ++++++++++--------
 vala/valablock.vala                      |    4 +
 vala/valaexpression.vala                 |   17 +-
 vala/valamethod.vala                     |    2 +
 vala/valamethodcall.vala                 |    1 +
 vala/valayieldstatement.vala             |    2 +
 28 files changed, 1268 insertions(+), 1882 deletions(-)
---
diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala
index 1a5f239..6db8f30 100644
--- a/codegen/valaccodearraymodule.vala
+++ b/codegen/valaccodearraymodule.vala
@@ -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;
 	}
 
diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala
index 20ed409..a403ada 100644
--- a/codegen/valaccodeassignmentmodule.vala
+++ b/codegen/valaccodeassignmentmodule.vala
@@ -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 */
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index c23ebe2..4015c00 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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) {
 	}
 }
 
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index 49d868b..0793d33 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -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 ();
 	}
 }
 
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index bbe085f..fbdbbe5 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -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);
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index 5a01c91..f1dd342 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -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");
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 4a6e805..89d216f 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -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);
-		}
 	}
 }
 
diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala
index 04b831c..51e5d7f 100644
--- a/codegen/valaccodestructmodule.vala
+++ b/codegen/valaccodestructmodule.vala
@@ -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);
 	}
 }
 
diff --git a/codegen/valadovaarraymodule.vala b/codegen/valadovaarraymodule.vala
index 93978f1..182ffce 100644
--- a/codegen/valadovaarraymodule.vala
+++ b/codegen/valadovaarraymodule.vala
@@ -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);
 
diff --git a/codegen/valadovaassignmentmodule.vala b/codegen/valadovaassignmentmodule.vala
index 3d21f33..1219a44 100644
--- a/codegen/valadovaassignmentmodule.vala
+++ b/codegen/valadovaassignmentmodule.vala
@@ -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 */
diff --git a/codegen/valadovabasemodule.vala b/codegen/valadovabasemodule.vala
index 28aaeff..8c5fe91 100644
--- a/codegen/valadovabasemodule.vala
+++ b/codegen/valadovabasemodule.vala
@@ -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) {
 	}
 }
diff --git a/codegen/valadovacontrolflowmodule.vala b/codegen/valadovacontrolflowmodule.vala
index 0fddf3f..93894ed 100644
--- a/codegen/valadovacontrolflowmodule.vala
+++ b/codegen/valadovacontrolflowmodule.vala
@@ -22,51 +22,29 @@
 
 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 ();
 	}
 }
 
diff --git a/codegen/valadovaerrormodule.vala b/codegen/valadovaerrormodule.vala
index f38bafd..be2fcaf 100644
--- a/codegen/valadovaerrormodule.vala
+++ b/codegen/valadovaerrormodule.vala
@@ -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);
 	}
 }
 
diff --git a/codegen/valadovamemberaccessmodule.vala b/codegen/valadovamemberaccessmodule.vala
index 3e7b102..3e87b05 100644
--- a/codegen/valadovamemberaccessmodule.vala
+++ b/codegen/valadovamemberaccessmodule.vala
@@ -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;
diff --git a/codegen/valadovamethodcallmodule.vala b/codegen/valadovamethodcallmodule.vala
index 7a245b0..958aa26 100644
--- a/codegen/valadovamethodcallmodule.vala
+++ b/codegen/valadovamethodcallmodule.vala
@@ -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 {
diff --git a/codegen/valadovaobjectmodule.vala b/codegen/valadovaobjectmodule.vala
index fca759d..4d65c26 100644
--- a/codegen/valadovaobjectmodule.vala
+++ b/codegen/valadovaobjectmodule.vala
@@ -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));
+		}
+	}
 }
diff --git a/codegen/valadovastructmodule.vala b/codegen/valadovastructmodule.vala
index b7a99cd..2c6cdf2 100644
--- a/codegen/valadovastructmodule.vala
+++ b/codegen/valadovastructmodule.vala
@@ -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 ();
 	}
 }
diff --git a/codegen/valadovavaluemodule.vala b/codegen/valadovavaluemodule.vala
index e876869..9436925 100644
--- a/codegen/valadovavaluemodule.vala
+++ b/codegen/valadovavaluemodule.vala
@@ -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));
 			}
diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala
index a62167d..02846d2 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -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) {
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 19db146..ae406e1 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -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);
 	}
 }
 
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index ef7e11f..d181108 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -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"));
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index e2b0de8..8b90ef4 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -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"));
 			}
diff --git a/codegen/valagtypemodule.vala b/codegen/valagtypemodule.vala
index a6c1ebd..d6da086 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -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 ()));
diff --git a/vala/valablock.vala b/vala/valablock.vala
index 64cbfaa..d7b35f2 100644
--- a/vala/valablock.vala
+++ b/vala/valablock.vala
@@ -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;
 			}
 		}
diff --git a/vala/valaexpression.vala b/vala/valaexpression.vala
index 23c01e2..eafb202 100644
--- a/vala/valaexpression.vala
+++ b/vala/valaexpression.vala
@@ -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.
 	 */
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index a29ab05..bc6510e 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -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;
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index a493c56..23a109a 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -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
diff --git a/vala/valayieldstatement.vala b/vala/valayieldstatement.vala
index be526a1..0fd6e34 100644
--- a/vala/valayieldstatement.vala
+++ b/vala/valayieldstatement.vala
@@ -75,6 +75,8 @@ public class Vala.YieldStatement : CodeNode, Statement {
 			error = yield_expression.error;
 		}
 
+		analyzer.current_method.yield_count++;
+
 		return !error;
 	}
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]