[vala/emit: 4/4] WIP: Add CCodeBuilder



commit fc9eaa3501ce181b0a81763095f11381ae4bd995
Author: Jürg Billeter <j bitron ch>
Date:   Sun Aug 8 20:26:48 2010 +0200

    WIP: Add CCodeBuilder

 ccode/Makefile.am                        |    2 +
 ccode/valaccodebuilder.vala              |  104 +++++
 ccode/valaccodedeclaration.vala          |   65 +---
 ccode/valaccodefilewriter.vala           |  128 ++++++
 ccode/valaccodefunction.vala             |    4 +-
 ccode/valaccodewriter.vala               |  408 +++++++++++++------
 codegen/valaccodearraymodule.vala        |   88 ++---
 codegen/valaccodeassignmentmodule.vala   |    4 +-
 codegen/valaccodebasemodule.vala         |  626 +++++++++++++-----------------
 codegen/valaccodecontrolflowmodule.vala  |  219 ++++-------
 codegen/valaccodememberaccessmodule.vala |   12 +-
 codegen/valaccodemethodcallmodule.vala   |   44 +--
 codegen/valaccodemethodmodule.vala       |  406 +++++++++++++-------
 codegen/valaccodestructmodule.vala       |   11 +-
 codegen/valadovaarraymodule.vala         |    2 +-
 codegen/valadovaassignmentmodule.vala    |    4 +-
 codegen/valadovabasemodule.vala          |   25 +-
 codegen/valadovamemberaccessmodule.vala  |    2 +-
 codegen/valadovamethodcallmodule.vala    |   10 +-
 codegen/valadovavaluemodule.vala         |   14 +-
 codegen/valagasyncmodule.vala            |  129 +++----
 codegen/valagerrormodule.vala            |  187 ++++------
 codegen/valagobjectmodule.vala           |   36 +-
 codegen/valagsignalmodule.vala           |    4 +-
 codegen/valagtypemodule.vala             |  210 ++++++-----
 25 files changed, 1476 insertions(+), 1268 deletions(-)
---
diff --git a/ccode/Makefile.am b/ccode/Makefile.am
index 1fd4a0d..f53f38f 100644
--- a/ccode/Makefile.am
+++ b/ccode/Makefile.am
@@ -17,6 +17,7 @@ libvalaccode_la_VALASOURCES = \
 	valaccodebinaryexpression.vala \
 	valaccodeblock.vala \
 	valaccodebreakstatement.vala \
+	valaccodebuilder.vala \
 	valaccodecasestatement.vala \
 	valaccodecastexpression.vala \
 	valaccodecommaexpression.vala \
@@ -32,6 +33,7 @@ libvalaccode_la_VALASOURCES = \
 	valaccodeenumvalue.vala \
 	valaccodeexpression.vala \
 	valaccodeexpressionstatement.vala \
+	valaccodefilewriter.vala \
 	valaccodeformalparameter.vala \
 	valaccodeforstatement.vala \
 	valaccodefragment.vala \
diff --git a/ccode/valaccodebuilder.vala b/ccode/valaccodebuilder.vala
new file mode 100644
index 0000000..c66918b
--- /dev/null
+++ b/ccode/valaccodebuilder.vala
@@ -0,0 +1,104 @@
+/* valaccodebuilder.vala
+ *
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Jürg Billeter <j bitron ch>
+ */
+
+public class Vala.CCodeBuilder : CCodeWriter {
+	class Context {
+		public StringBuilder decl_string = new StringBuilder ();
+		public StringBuilder code_string = new StringBuilder ();
+	}
+
+	class Node : CCodeNode {
+		public string str;
+
+		public Node (string str) {
+			this.str = str;
+		}
+
+		public override void write (CCodeWriter writer) {
+			writer.write_string (str);
+		}
+	}
+
+	List<Context> context_stack = new ArrayList<Context> ();
+	Context context = new Context ();
+
+	public CCodeBuilder () {
+	}
+
+	void push_context () {
+		context_stack.add (context);
+		context = new Context ();
+	}
+
+	void pop_context () {
+		context = context_stack[context_stack.size - 1];
+		context_stack.remove_at (context_stack.size - 1);
+	}
+
+	public override void write_begin_block () {
+		base.write_begin_block ();
+
+		push_context ();
+	}
+
+	public override void write_end_block () {
+		var block = context;
+		pop_context ();
+
+		var old_bol = bol;
+		bol = true;
+
+		write_string (block.decl_string.str);
+		write_string (block.code_string.str);
+
+		bol = old_bol;
+
+		base.write_end_block ();
+	}
+
+	public override void write_string (string s) {
+		if (writing_code) {
+			context.code_string.append (s);
+		} else {
+			context.decl_string.append (s);
+		}
+		bol = false;
+	}
+
+	public void append (CCodeNode node) {
+		node.write (this);
+	}
+
+	public CCodeNode get_node () {
+		if (!bol) {
+			write_newline ();
+		}
+		write_newline ();
+		return new Node (context.code_string.str);
+	}
+
+	public CCodeBlock get_block () {
+		var result = new CCodeBlock ();
+		result.add_statement (get_node ());
+		return result;
+	}
+}
diff --git a/ccode/valaccodedeclaration.vala b/ccode/valaccodedeclaration.vala
index 95216f8..60aa6c4 100644
--- a/ccode/valaccodedeclaration.vala
+++ b/ccode/valaccodedeclaration.vala
@@ -59,72 +59,9 @@ public class Vala.CCodeDeclaration : CCodeStatement {
 		}
 	}
 
-	private bool has_initializer () {
-		foreach (CCodeDeclarator decl in declarators) {
-			var var_decl = decl as CCodeVariableDeclarator;
-			if (var_decl != null && var_decl.initializer == null) {
-				return false;
-			}
-		}
-		return true;
-	}
-
 	public override void write_declaration (CCodeWriter writer) {
-		if ((modifiers & (CCodeModifiers.STATIC | CCodeModifiers.EXTERN)) != 0) {
-			// combined declaration and initialization for static and extern variables
-			writer.write_indent (line);
-			if ((modifiers & CCodeModifiers.STATIC) != 0) {
-				writer.write_string ("static ");
-			}
-			if ((modifiers & CCodeModifiers.VOLATILE) != 0) {
-				writer.write_string ("volatile ");
-			}
-			if ((modifiers & CCodeModifiers.EXTERN) != 0 && !has_initializer ()) {
-				writer.write_string ("extern ");
-			}
-			if ((modifiers & CCodeModifiers.THREAD_LOCAL) != 0) {
-				writer.write_string ("thread_local ");
-			}
-			writer.write_string (type_name);
-			writer.write_string (" ");
-
-			bool first = true;
-			foreach (CCodeDeclarator decl in declarators) {
-				if (!first) {
-					writer.write_string (", ");
-				} else {
-					first = false;
-				}
-				decl.write (writer);
-			}
-
-			if (CCodeModifiers.DEPRECATED in modifiers) {
-				writer.write_string (" G_GNUC_DEPRECATED");
-			}
-
-			writer.write_string (";");
-			writer.write_newline ();
-			return;
-		}
-
-		writer.write_indent ();
-		if ((modifiers & CCodeModifiers.REGISTER) == CCodeModifiers.REGISTER) {
-			writer.write_string ("register ");
-		}
-		writer.write_string (type_name);
-		writer.write_string (" ");
-	
-		bool first = true;
 		foreach (CCodeDeclarator decl in declarators) {
-			if (!first) {
-				writer.write_string (", ");
-			} else {
-				first = false;
-			}
-			decl.write_declaration (writer);
+			writer.write_declaration (type_name, decl, modifiers);
 		}
-
-		writer.write_string (";");
-		writer.write_newline ();
 	}
 }
diff --git a/ccode/valaccodefilewriter.vala b/ccode/valaccodefilewriter.vala
new file mode 100644
index 0000000..cac80f4
--- /dev/null
+++ b/ccode/valaccodefilewriter.vala
@@ -0,0 +1,128 @@
+/* valaccodefilewriter.vala
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Jürg Billeter <j bitron ch>
+ */
+
+using GLib;
+
+/**
+ * Represents a writer to write C source files.
+ */
+public class Vala.CCodeFileWriter : CCodeWriter {
+	/**
+	 * Specifies the file to be written.
+	 */
+	public string filename { get; set; }
+
+	/**
+	 * Specifies the source file used to generate this one.
+	 */
+	private string source_filename;
+
+	private string temp_filename;
+	private bool file_exists;
+
+	private FileStream? stream;
+	
+	public CCodeFileWriter (string filename, string? source_filename = null) {
+		this.filename = filename;
+		this.source_filename = source_filename;
+	}
+
+	/**
+	 * Opens the file.
+	 *
+	 * @return true if the file has been opened successfully,
+	 *         false otherwise
+	 */
+	public bool open (bool write_version) {
+		file_exists = FileUtils.test (filename, FileTest.EXISTS);
+		if (file_exists) {
+			temp_filename = "%s.valatmp".printf (filename);
+			stream = FileStream.open (temp_filename, "w");
+		} else {
+			/*
+			 * File doesn't exist. In case of a particular destination (-d flag),
+			 * check and create the directory structure.
+			 */
+			var dirname = Path.get_dirname (filename);
+			DirUtils.create_with_parents (dirname, 0755);
+			stream = FileStream.open (filename, "w");
+		}
+
+		if (stream == null) {
+			return false;
+		}
+
+		var opening = write_version ?
+			"/* %s generated by valac %s, the Vala compiler".printf (Path.get_basename (filename), Config.BUILD_VERSION) :
+			"/* %s generated by valac, the Vala compiler".printf (Path.get_basename (filename));
+		write_string (opening);
+
+		// Write the file name if known
+		if (source_filename != null) {
+			write_newline ();
+			write_string (" * generated from %s".printf (Path.get_basename (source_filename)));
+		}
+
+		write_string (", do not modify */");
+		write_newline ();
+		write_newline ();
+
+		return true;
+	}
+
+	/**
+	 * Closes the file.
+	 */
+	public void close () {
+		stream = null;
+		
+		if (file_exists) {
+			var changed = true;
+
+			try {
+				var old_file = new MappedFile (filename, false);
+				var new_file = new MappedFile (temp_filename, false);
+				var len = old_file.get_length ();
+				if (len == new_file.get_length ()) {
+					if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
+						changed = false;
+					}
+				}
+				old_file = null;
+				new_file = null;
+			} catch (FileError e) {
+				// assume changed if mmap comparison doesn't work
+			}
+			
+			if (changed) {
+				FileUtils.rename (temp_filename, filename);
+			} else {
+				FileUtils.unlink (temp_filename);
+			}
+		}
+	}
+
+	public override void write_string (string s) {
+		stream.puts (s);
+		bol = false;
+	}
+}
diff --git a/ccode/valaccodefunction.vala b/ccode/valaccodefunction.vala
index d414fb2..87a8d02 100644
--- a/ccode/valaccodefunction.vala
+++ b/ccode/valaccodefunction.vala
@@ -43,12 +43,14 @@ public class Vala.CCodeFunction : CCodeNode {
 
 	public string attributes { get; set; }
 
+	public List<CCodeFormalParameter> parameters { get { return _parameters; } }
+
 	/**
 	 * The function body.
 	 */
 	public CCodeBlock block { get; set; }
 
-	private List<CCodeFormalParameter> parameters = new ArrayList<CCodeFormalParameter> ();
+	private List<CCodeFormalParameter> _parameters = new ArrayList<CCodeFormalParameter> ();
 	
 	public CCodeFunction (string name, string return_type = "void") {
 		this.name = name;
diff --git a/ccode/valaccodewriter.vala b/ccode/valaccodewriter.vala
index 93f4a42..48d8fd5 100644
--- a/ccode/valaccodewriter.vala
+++ b/ccode/valaccodewriter.vala
@@ -1,6 +1,6 @@
 /* valaccodewriter.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
@@ -20,22 +20,7 @@
  * 	Jürg Billeter <j bitron ch>
  */
 
-using GLib;
-
-/**
- * Represents a writer to write C source files.
- */
-public class Vala.CCodeWriter {
-	/**
-	 * Specifies the file to be written.
-	 */
-	public string filename { get; set; }
-
-	/**
-	 * Specifies the source file used to generate this one.
-	 */
-	private string source_filename;
-
+public abstract class Vala.CCodeWriter {
 	/**
 	 * Specifies whether to emit line directives.
 	 */
@@ -45,114 +30,46 @@ public class Vala.CCodeWriter {
 	 * Specifies whether the output stream is at the beginning of a line.
 	 */
 	public bool bol {
-		get { return _bol; }
+		get {
+			if (writing_code) {
+				return code_bol;
+			} else {
+				return decl_bol;
+			}
+		}
+		set {
+			if (writing_code) {
+				code_bol = value;
+			} else {
+				decl_bol = value;
+			}
+		}
 	}
 
-	private string temp_filename;
-	private bool file_exists;
-
-	private FileStream? stream;
-	
 	private int indent;
 	private int current_line_number = 1;
-	private bool using_line_directive;
-
-	/* at begin of line */
-	private bool _bol = true;
-	
-	public CCodeWriter (string filename, string? source_filename = null) {
-		this.filename = filename;
-		this.source_filename = source_filename;
-	}
-
-	/**
-	 * Opens the file.
-	 *
-	 * @return true if the file has been opened successfully,
-	 *         false otherwise
-	 */
-	public bool open (bool write_version) {
-		file_exists = FileUtils.test (filename, FileTest.EXISTS);
-		if (file_exists) {
-			temp_filename = "%s.valatmp".printf (filename);
-			stream = FileStream.open (temp_filename, "w");
-		} else {
-			/*
-			 * File doesn't exist. In case of a particular destination (-d flag),
-			 * check and create the directory structure.
-			 */
-			var dirname = Path.get_dirname (filename);
-			DirUtils.create_with_parents (dirname, 0755);
-			stream = FileStream.open (filename, "w");
-		}
 
-		if (stream == null) {
-			return false;
-		}
+	bool decl_bol = true;
+	bool code_bol = true;
 
-		var opening = write_version ?
-			"/* %s generated by valac %s, the Vala compiler".printf (Path.get_basename (filename), Config.BUILD_VERSION) :
-			"/* %s generated by valac, the Vala compiler".printf (Path.get_basename (filename));
-		write_string (opening);
+	public CCodeLineDirective? line { get; set; }
 
-		// Write the file name if known
-		if (source_filename != null) {
-			write_newline ();
-			write_string (" * generated from %s".printf (Path.get_basename (source_filename)));
-		}
-
-		write_string (", do not modify */");
-		write_newline ();
-		write_newline ();
+	public bool writing_code { get; set; default = true; }
 
-		return true;
+	public CCodeWriter () {
 	}
 
 	/**
-	 * Closes the file.
-	 */
-	public void close () {
-		stream = null;
-		
-		if (file_exists) {
-			var changed = true;
-
-			try {
-				var old_file = new MappedFile (filename, false);
-				var new_file = new MappedFile (temp_filename, false);
-				var len = old_file.get_length ();
-				if (len == new_file.get_length ()) {
-					if (Memory.cmp (old_file.get_contents (), new_file.get_contents (), len) == 0) {
-						changed = false;
-					}
-				}
-				old_file = null;
-				new_file = null;
-			} catch (FileError e) {
-				// assume changed if mmap comparison doesn't work
-			}
-			
-			if (changed) {
-				FileUtils.rename (temp_filename, filename);
-			} else {
-				FileUtils.unlink (temp_filename);
-			}
-		}
-	}
-	
-	/**
 	 * Writes tabs according to the current indent level.
 	 */
 	public void write_indent (CCodeLineDirective? line = null) {
 		if (line_directives) {
 			if (line != null) {
-				line.write (this);
-				using_line_directive = true;
-			} else if (using_line_directive) {
-				// no corresponding Vala line, emit line directive for C line
-				write_string ("#line %d \"%s\"".printf (current_line_number + 1, Path.get_basename (filename)));
-				write_newline ();
-				using_line_directive = false;
+				this.line = line;
+			}
+
+			if (this.line != null) {
+				this.line.write (this);
 			}
 		}
 
@@ -161,10 +78,10 @@ public class Vala.CCodeWriter {
 		}
 		
 		for (int i = 0; i < indent; i++) {
-			stream.putc ('\t');
+			write_string ("\t");
 		}
 		
-		_bol = false;
+		bol = false;
 	}
 	
 	/**
@@ -172,45 +89,46 @@ public class Vala.CCodeWriter {
 	 *
 	 * @param s a string
 	 */
-	public void write_string (string s) {
-		stream.puts (s);
-		_bol = false;
-	}
-	
+	public abstract void write_string (string s);
+
 	/**
 	 * Writes a newline.
 	 */
 	public void write_newline () {
-		stream.putc ('\n');
+		write_string ("\n");
 		current_line_number++;
-		_bol = true;
+		bol = true;
 	}
 	
 	/**
 	 * Opens a new block, increasing the indent level.
 	 */
-	public void write_begin_block () {
+	public virtual void write_begin_block () {
 		if (!bol) {
-			stream.putc (' ');
+			write_string (" ");
 		} else {
 			write_indent ();
 		}
-		stream.putc ('{');
+		write_string ("{");
 		write_newline ();
 		indent++;
 	}
-	
+
 	/**
 	 * Closes the current block, decreasing the indent level.
 	 */
-	public void write_end_block () {
+	public virtual void write_end_block () {
 		assert (indent > 0);
-		
+
 		indent--;
 		write_indent ();
-		stream.putc ('}');
+		write_string ("}");
 	}
-	
+
+	public void close () {
+		write_end_block ();
+	}
+
 	/**
 	 * Writes the specified text as comment.
 	 *
@@ -219,7 +137,7 @@ public class Vala.CCodeWriter {
 	public void write_comment (string text) {
 		try {
 			write_indent ();
-			stream.puts ("/*");
+			write_string ("/*");
 			bool first = true;
 
 			// discard tabs at beginning of line
@@ -238,16 +156,246 @@ public class Vala.CCodeWriter {
 				var lineparts = regex.replace_literal (line, -1, 0, "").split ("*/");
 
 				for (int i = 0; lineparts[i] != null; i++) {
-					stream.puts (lineparts[i]);
+					write_string (lineparts[i]);
 					if (lineparts[i+1] != null) {
-						stream.puts ("* /");
+						write_string ("* /");
 					}
 				}
 			}
-			stream.puts ("*/");
+			write_string ("*/");
 			write_newline ();
 		} catch (RegexError e) {
 			// ignore
 		}
 	}
+
+	/* TODO: also write expressions without creating CCodeNodes using stack/RPN logic
+	   return writer object to allow chaining
+	   writer.load_integer (42).load_integer (23).add ().call ("sqrt");
+	 */
+
+	public void write_expression (CCodeNode expression) {
+		var comma = expression as CCodeCommaExpression;
+		if (comma != null) {
+			foreach (var inner in comma.get_inner ()) {
+				write_indent ();
+				inner.write (this);
+				write_string (";");
+			}
+			return;
+		}
+
+		write_indent ();
+		expression.write (this);
+		write_string (";");
+		write_newline ();
+	}
+
+	public void open_function (string name, string return_type, List<CCodeFormalParameter> parameters, CCodeModifiers modifiers = 0, string? attributes = null) {
+		write_function (name, return_type, parameters, modifiers, attributes);
+		write_begin_block ();
+	}
+
+	void write_function (string name, string return_type, List<CCodeFormalParameter> parameters, CCodeModifiers modifiers = 0, string? attributes = null) {
+		write_indent ();
+		if (CCodeModifiers.STATIC in modifiers) {
+			write_string ("static ");
+		}
+		if (CCodeModifiers.INLINE in modifiers) {
+			write_string ("inline ");
+		}
+		write_string (return_type);
+		write_string (" ");
+		write_string (name);
+		write_string (" (");
+
+		bool first = true;
+		foreach (CCodeFormalParameter param in parameters) {
+			if (!first) {
+				write_string (", ");
+			} else {
+				first = false;
+			}
+			param.write (this);
+		}
+		if (first) {
+			write_string ("void");
+		}
+
+		write_string (")");
+
+		if (CCodeModifiers.DEPRECATED in modifiers) {
+			write_string (" G_GNUC_DEPRECATED");
+		}
+
+		if (attributes != null) {
+			write_string (" ");
+			write_string (attributes);
+		}
+	}
+
+	public void write_function_declaration (string name, string return_type, List<CCodeFormalParameter> parameters, CCodeModifiers modifiers = 0, string attributes = "") {
+		write_function (name, return_type, parameters, modifiers, attributes);
+		write_string (";");
+		write_newline ();
+	}
+
+	public void write_declaration (string type_name, CCodeDeclarator declarator, CCodeModifiers modifiers = 0) {
+		writing_code = false;
+
+		bool has_initializer = declarator is CCodeVariableDeclarator &&
+		                       ((CCodeVariableDeclarator) declarator).initializer != null;
+
+		if ((modifiers & (CCodeModifiers.STATIC | CCodeModifiers.EXTERN)) != 0) {
+			// combined declaration and initialization for static and extern variables
+			write_indent ();
+			if ((modifiers & CCodeModifiers.STATIC) != 0) {
+				write_string ("static ");
+			}
+			if ((modifiers & CCodeModifiers.VOLATILE) != 0) {
+				write_string ("volatile ");
+			}
+			if ((modifiers & CCodeModifiers.EXTERN) != 0 && !has_initializer) {
+				write_string ("extern ");
+			}
+			if ((modifiers & CCodeModifiers.THREAD_LOCAL) != 0) {
+				write_string ("thread_local ");
+			}
+			write_string (type_name);
+			write_string (" ");
+
+			declarator.write (this);
+
+			if (CCodeModifiers.DEPRECATED in modifiers) {
+				write_string (" G_GNUC_DEPRECATED");
+			}
+
+			write_string (";");
+			write_newline ();
+
+			writing_code = true;
+			return;
+		}
+
+		write_indent ();
+		if ((modifiers & CCodeModifiers.REGISTER) == CCodeModifiers.REGISTER) {
+			write_string ("register ");
+		}
+		write_string (type_name);
+		write_string (" ");
+	
+		declarator.write_declaration (this);
+
+		write_string (";");
+		write_newline ();
+
+		writing_code = true;
+	}
+
+	public void open_if (CCodeNode condition) {
+		write_indent ();
+		write_string ("if (");
+		condition.write (this);
+		write_string (")");
+		write_begin_block ();
+	}
+
+	public void add_else () {
+		write_end_block ();
+		write_string (" else");
+		write_begin_block ();
+	}
+
+	public void open_switch (CCodeNode condition) {
+		write_indent ();
+		write_string ("switch (");
+		condition.write (this);
+		write_string (")");
+		write_begin_block ();
+	}
+
+	public void add_default () {
+		write_indent ();
+		write_string ("default:");
+		write_newline ();
+	}
+
+	public void add_case (CCodeNode expression) {
+		write_indent ();
+		write_string ("case ");
+		expression.write (this);
+		write_string (":");
+		write_newline ();
+	}
+
+	public void add_label (string label) {
+		write_indent ();
+		write_string (label);
+		write_string (":");
+		write_newline ();
+	}
+
+	public void write_goto (string target) {
+		write_indent ();
+		write_string ("goto ");
+		write_string (target);
+		write_string (";");
+		write_newline ();
+	}
+
+	public void open_while (CCodeNode condition) {
+		write_indent ();
+		write_string ("while (");
+		condition.write (this);
+		write_string (")");
+		write_begin_block ();
+	}
+
+	public void open_for (CCodeNode initializer, CCodeNode condition, CCodeNode iterator) {
+		write_indent ();
+		write_string ("for (");
+		initializer.write (this);
+		write_string ("; ");
+		condition.write (this);
+		write_string ("; ");
+		iterator.write (this);
+		write_string (")");
+		write_begin_block ();
+	}
+
+	public void write_return (CCodeNode? expression = null) {
+		write_indent ();
+		if (expression == null) {
+			write_string ("return;");
+		} else {
+			write_string ("return ");
+			expression.write (this);
+			write_string (";");
+		}
+		write_newline ();
+	}
+
+	public void add_break () {
+		write_indent ();
+		write_string ("break;");
+		write_newline ();
+	}
+
+	public void add_continue () {
+		write_indent ();
+		write_string ("continue;");
+		write_newline ();
+	}
+
+	public List<CCodeFormalParameter> parameters (CCodeFormalParameter? parameter = null, ...) {
+		var args = va_list ();
+
+		var list = new ArrayList<CCodeFormalParameter> ();
+		while (parameter != null) {
+			list.add (parameter);
+			parameter = args.arg ();
+		}
+
+		return list;
+	}
 }
diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala
index a0a6ab4..edf17d6 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));
 
@@ -442,15 +442,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);
@@ -688,7 +688,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);
 
@@ -766,14 +766,12 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
 		// definition
 
-		var block = new CCodeBlock ();
+		push_context (new EmitContext ());
 
-		if (requires_copy (array_type.element_type)) {
-			push_context (new EmitContext ());
+		ccode.write_begin_block ();
 
-			var cdecl = new CCodeDeclaration (array_type.get_cname ());
+		if (requires_copy (array_type.element_type)) {
 			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 ()));
 
@@ -785,27 +783,18 @@ 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);
+			ccode.write_declaration (array_type.get_cname (), cvardecl);
 
-			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.write_declaration ("int", new CCodeVariableDeclarator ("i"));
 
-			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.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")));
 
-			block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+			ccode.write_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 ();
 
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			block.add_statement (cfrag);
-
-			pop_context ();
+			ccode.write_return (new CCodeIdentifier ("result"));
 		} else {
 			var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
 			dup_call.add_argument (new CCodeIdentifier ("self"));
@@ -814,16 +803,20 @@ 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.write_return (dup_call);
 		}
 
+		ccode.write_end_block ();
+
 		// append to file
 
 		source_declarations.add_type_member_declaration (function.copy ());
 
-		function.block = block;
+		function.block = ccode.get_block ();
 		source_type_member_definition.append (function);
 
+		pop_context ();
+
 		return dup_func;
 	}
 
@@ -845,28 +838,21 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
 
 		// definition
 
-		var block = new CCodeBlock ();
+		push_context (new EmitContext ());
 
-		if (requires_copy (array_type.element_type)) {
-			push_context (new EmitContext ());
+		ccode.write_begin_block ();
 
-			var idx_decl = new CCodeDeclaration ("int");
-			idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
-			block.add_statement (idx_decl);
+		if (requires_copy (array_type.element_type)) {
+			ccode.write_declaration ("int", new CCodeVariableDeclarator ("i"));
 
-			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.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 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);
 
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			block.add_statement (cfrag);
+			ccode.write_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)));
 
-			pop_context ();
+			ccode.close ();
 		} else {
 			source_declarations.add_include ("string.h");
 
@@ -878,16 +864,20 @@ 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.write_expression (dup_call);
 		}
 
+		ccode.write_end_block ();
+
 		// append to file
 
 		source_declarations.add_type_member_declaration (function.copy ());
 
-		function.block = block;
+		function.block = ccode.get_block ();
 		source_type_member_definition.append (function);
 
+		pop_context ();
+
 		return dup_func;
 	}
 
diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala
index c1009b2..d3bba10 100644
--- a/codegen/valaccodeassignmentmodule.vala
+++ b/codegen/valaccodeassignmentmodule.vala
@@ -130,13 +130,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 e71fa5b..5939fc1 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 CCodeBuilder ccode = new CCodeBuilder ();
 		public CCodeSwitchStatement state_switch_statement;
-		public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
 		public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
 		public int next_temp_var_id;
 		public bool current_method_inner_error;
@@ -154,12 +154,12 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
 	public CCodeFragment source_signal_marshaller_declaration;
 	public CCodeFragment source_type_member_definition;
-	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 CCodeFragment source_signal_marshaller_definition;
 	
 	public CCodeStruct param_spec_struct;
@@ -167,9 +167,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 	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 CCodeBuilder ccode { get { return emit_context.ccode; } }
 
 	// case statements to be inserted for the couroutine state
 	public CCodeSwitchStatement state_switch_statement {
@@ -177,8 +175,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 		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 */
@@ -446,7 +442,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
 		// generate C header file for public API
 		if (context.header_filename != null) {
-			var writer = new CCodeWriter (context.header_filename);
+			var writer = new CCodeFileWriter (context.header_filename);
 			if (!writer.open (context.version_header)) {
 				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 				return;
@@ -485,7 +481,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
 		// generate C header file for internal API
 		if (context.internal_header_filename != null) {
-			var writer = new CCodeWriter (context.internal_header_filename);
+			var writer = new CCodeFileWriter (context.internal_header_filename);
 			if (!writer.open (context.version_header)) {
 				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 				return;
@@ -672,7 +668,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			source_declarations.add_include ("gobject/gvaluecollector.h");
 		}
 
-		var writer = new CCodeWriter (source_file.get_csource_filename (), source_file.filename);
+		var writer = new CCodeFileWriter (source_file.get_csource_filename (), source_file.filename);
 		if (!writer.open (context.version_header)) {
 			Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 			return;
@@ -809,13 +805,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;
 
@@ -826,14 +822,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.write_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.write_expression (fc);
+				pop_context ();
 			}
 		}
 	}
@@ -977,10 +977,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);
 
@@ -999,9 +995,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.write_expression (new CCodeAssignment (lhs, rhs));
 
 				if (f.variable_type is ArrayType && !f.no_array_length &&
 				    f.initializer is ArrayCreationExpression) {
@@ -1016,30 +1016,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.write_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.write_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.write_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);
 
@@ -1053,7 +1054,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.write_expression (get_unref_expression (lhs, f.variable_type, ma));
+
+				pop_context ();
 			}
 		} else if (f.binding == MemberBinding.CLASS)  {
 			if (!is_gtypeinstance) {
@@ -1071,21 +1074,24 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			}
 
 			if (f.initializer != null) {
-				var rhs = (CCodeExpression) f.initializer.ccodenode;
+				push_context (class_init_context);
 
-				class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+				f.initializer.emit (this);
+
+				var rhs = (CCodeExpression) f.initializer.ccodenode;
 
-				append_temp_decl (class_init_fragment, temp_vars);
+				ccode.write_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.write_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, source_declarations);
@@ -1102,7 +1108,11 @@ 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);
 
+			push_context (class_init_context);
+
 			if (f.initializer != null) {
+				f.initializer.emit (this);
+
 				var init = (CCodeExpression) f.initializer.ccodenode;
 				if (is_constant_ccode_expression (init)) {
 					var_decl.initializer = init;
@@ -1192,9 +1202,9 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 							frag.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, tmp)));
 
 							block.add_statement (frag);
-							class_init_fragment.append (block);
+							ccode.append (block);
 						} else {
-							class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+							ccode.write_expression (new CCodeAssignment (lhs, rhs));
 						}
 
 						if (f.variable_type is ArrayType && !f.no_array_length &&
@@ -1207,12 +1217,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.write_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");
@@ -1220,6 +1227,8 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 					}
 				}
 			}
+
+			pop_context ();
 		}
 	}
 
@@ -1416,10 +1425,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			acc.result_var.accept (this);
 		}
 
-		if (acc.body != null) {
-			acc.body.emit (this);
-		}
-
 		var t = (TypeSymbol) prop.parent_symbol;
 
 		if (acc.construction && !t.is_subtype_of (gobject_type)) {
@@ -1464,6 +1469,76 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			cvalueparam = new CCodeFormalParameter ("value", acc.value_type.get_cname ());
 		}
 
+		bool is_virtual = prop.base_property != null || prop.base_interface_property != null;
+
+		string cname;
+		if (is_virtual) {
+			if (acc.readable) {
+				cname = "%s_real_get_%s".printf (t.get_lower_case_cname (null), prop.name);
+			} else {
+				cname = "%s_real_set_%s".printf (t.get_lower_case_cname (null), prop.name);
+			}
+		} else {
+			cname = acc.get_cname ();
+		}
+
+		string return_type;
+		if (acc.writable || acc.construction || returns_real_struct) {
+			return_type = "void";
+		} else {
+			return_type = acc.value_type.get_cname ();
+		}
+
+		ObjectType base_type = null;
+		if (prop.binding == MemberBinding.INSTANCE) {
+			if (is_virtual) {
+				if (prop.base_property != null) {
+					base_type = new ObjectType ((ObjectTypeSymbol) prop.base_property.parent_symbol);
+				} else if (prop.base_interface_property != null) {
+					base_type = new ObjectType ((ObjectTypeSymbol) prop.base_interface_property.parent_symbol);
+				}
+			}
+		}
+
+
+		var parameters = ccode.parameters ();
+		if (prop.binding == MemberBinding.INSTANCE) {
+			if (is_virtual) {
+				parameters.add (new CCodeFormalParameter ("base", base_type.get_cname ()));
+			} else {
+				parameters.add (cselfparam);
+			}
+		}
+		if (acc.writable || acc.construction || returns_real_struct) {
+			parameters.add (cvalueparam);
+		}
+
+		CCodeModifiers modifiers = 0;
+		if (prop.is_private_symbol () || !(acc.readable || acc.writable) || acc.access == SymbolAccessibility.PRIVATE) {
+			// accessor function should be private if the property is an internal symbol or it's a construct-only setter
+			modifiers = CCodeModifiers.STATIC;
+		}
+
+		ccode.open_function (cname, return_type, parameters, modifiers);
+
+		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) {
+				ccode.write_declaration (acc.value_type.get_cname (), new CCodeVariableDeclarator ("result"));
+			}
+		}
+
+		if (is_virtual) {
+			ccode.write_declaration (this_type.get_cname (), new CCodeVariableDeclarator ("self"));
+			ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("self"), transform_expression (new CCodeIdentifier ("base"), base_type, this_type)));
+		}
+
+		if (acc.body != null) {
+			acc.body.emit (this);
+		}
+
+		ccode.close ();
+
 		if (prop.is_abstract || prop.is_virtual) {
 			if (acc.readable && !returns_real_struct) {
 				function = new CCodeFunction (acc.get_cname (), current_return_type.get_cname ());
@@ -1549,33 +1624,14 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 		}
 
 		if (!prop.is_abstract) {
-			bool is_virtual = prop.base_property != null || prop.base_interface_property != null;
-
-			string cname;
-			if (is_virtual) {
-				if (acc.readable) {
-					cname = "%s_real_get_%s".printf (t.get_lower_case_cname (null), prop.name);
-				} else {
-					cname = "%s_real_set_%s".printf (t.get_lower_case_cname (null), prop.name);
-				}
-			} else {
-				cname = acc.get_cname ();
-			}
-
 			if (acc.writable || acc.construction || returns_real_struct) {
 				function = new CCodeFunction (cname, "void");
 			} else {
 				function = new CCodeFunction (cname, acc.value_type.get_cname ());
 			}
 
-			ObjectType base_type = null;
 			if (prop.binding == MemberBinding.INSTANCE) {
 				if (is_virtual) {
-					if (prop.base_property != null) {
-						base_type = new ObjectType ((ObjectTypeSymbol) prop.base_property.parent_symbol);
-					} else if (prop.base_interface_property != null) {
-						base_type = new ObjectType ((ObjectTypeSymbol) prop.base_interface_property.parent_symbol);
-					}
 					function.modifiers |= CCodeModifiers.STATIC;
 					function.add_parameter (new CCodeFormalParameter ("base", base_type.get_cname ()));
 				} else {
@@ -1608,22 +1664,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 				}
 			}
 
-			function.block = (CCodeBlock) acc.body.ccodenode;
-
-			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)));
-				function.block.prepend_statement (cdecl);
-			}
-
-			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"));
-					function.block.prepend_statement (cdecl);
-				}
-			}
+			function.block = emit_context.ccode.get_block ();
 
 			if (current_method_inner_error) {
 				var cdecl = new CCodeDeclaration ("GError *");
@@ -1653,37 +1694,18 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 				function.block.add_statement (new CCodeExpressionStatement (notify_call));
 			}
 
-			source_type_member_definition.append (function);
+			source_type_member_definition.append (emit_context.ccode.get_node ());
 		}
 
 		pop_context ();
 	}
 
 	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) {
@@ -1695,7 +1717,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, source_declarations);
 
 		var param_type = param.variable_type.copy ();
@@ -1719,20 +1741,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.write_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.write_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.write_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.write_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)))));
 			}
 		}
 
@@ -1757,16 +1779,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.write_begin_block ();
 		}
-		
-		var cblock = new CCodeBlock ();
 
 		if (b.captured) {
 			var parent_block = next_closure_block (b.parent_symbol);
@@ -1842,15 +1859,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)));
+				ccode.write_expression (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.write_declaration (struct_name + "*", new CCodeVariableDeclarator ("_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.write_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);
@@ -1858,14 +1873,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.write_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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call));
 			}
 
 			if (b.parent_symbol is Method) {
@@ -1874,7 +1889,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);
 					}
 				}
 
@@ -1884,24 +1899,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.write_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));
@@ -1939,28 +1944,19 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			source_type_member_definition.append (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.write_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
 			}
 		}
 
@@ -1971,7 +1967,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.write_expression (get_unref_expression (get_variable_cexpression (param.name), param.variable_type, ma));
 				}
 			}
 		}
@@ -1981,10 +1977,12 @@ 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.write_expression (data_unref);
 		}
 
-		b.ccodenode = cblock;
+		if (b.parent_node is Block || b.parent_node is SwitchStatement) {
+			ccode.write_end_block ();
+		}
 
 		emit_context.pop_symbol ();
 	}
@@ -1995,16 +1993,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
 	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) {
@@ -2071,12 +2059,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) {
@@ -2085,10 +2073,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);
 					}
 				}
 			}
@@ -2111,7 +2099,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++) {
@@ -2136,7 +2124,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;
@@ -2185,19 +2173,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.write_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.write_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) {
@@ -2205,9 +2186,9 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 
 			if (local.initializer != null) {
 				if (has_simple_struct_initializer (local)) {
-					cfrag.append (new CCodeExpressionStatement (rhs));
+					ccode.write_expression (rhs);
 				} else {
-					cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
+					ccode.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs));
 				}
 			}
 		} else {
@@ -2222,10 +2203,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) {
@@ -2233,8 +2210,14 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 				cvar.init0 = true;
 			}
 
+			ccode.write_declaration (local.variable_type.get_cname (), cvar);
+
+			if (cvar.initializer != null && !cvar.init0) {
+				ccode.write_expression (new CCodeAssignment (get_variable_cexpression (local.name), rhs));
+			}
+
 			if (post_stmt != null) {
-				cfrag.append (post_stmt);
+				ccode.append (post_stmt);
 			}
 		}
 
@@ -2254,16 +2237,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.write_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;
 	}
 
@@ -2301,7 +2282,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));
 
@@ -3105,19 +3086,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
-		 */
-		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;
@@ -3137,7 +3105,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			}
 
 			full_expr_var = get_temp_variable (expr_type, true, expr, false);
-			expr.temp_vars.add (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));
 		}
@@ -3158,62 +3126,57 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 		temp_ref_vars.clear ();
 	}
 	
-	public void append_temp_decl (CCodeFragment cfrag, List<LocalVariable> temp_vars) {
-		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
-					source_declarations.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
+				source_declarations.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.write_expression (memset_call);
+			} else if (vardecl.initializer != null) {
+				ccode.write_expression (new CCodeAssignment (get_variable_cexpression (local.name), vardecl.initializer));
 			}
+		} else {
+			ccode.write_declaration (local.variable_type.get_cname (), vardecl);
 		}
 	}
 
@@ -3223,62 +3186,26 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			return;
 		}
 
-		stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
+		ccode.write_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.write_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.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 ();
@@ -3289,7 +3216,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.write_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
 			}
 		}
 
@@ -3298,7 +3225,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.write_expression (data_unref);
 		}
 
 		if (stop_at_loop) {
@@ -3310,13 +3237,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 ();
@@ -3326,7 +3253,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.write_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
 			}
 		}
 
@@ -3335,7 +3262,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.write_expression (data_unref);
 		}
 
 		if (sym == current_try.body) {
@@ -3343,32 +3270,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.write_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;
@@ -3427,7 +3345,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			ccomma.append_expression (get_variable_cexpression (return_expr_decl.name));
 
 			stmt.return_expression.ccodenode = ccomma;
-			stmt.return_expression.temp_vars.add (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) {
@@ -3454,52 +3372,37 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 				ccomma.append_expression (get_variable_cexpression (return_expr_decl.name));
 
 				stmt.return_expression.ccodenode = ccomma;
-				stmt.return_expression.temp_vars.add (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.write_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));
+				ccode.append (create_postcondition_statement (postcondition));
 			}
 		}
 
-		CCodeReturnStatement creturn = null;
 		if (current_method is CreationMethod) {
-			creturn = new CCodeReturnStatement (new CCodeIdentifier ("self"));
-			cfrag.append (creturn);
+			ccode.write_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.write_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.write_return (new CCodeIdentifier ("result"));
 		}
 
 		if (return_expression_symbol != null) {
@@ -3668,7 +3571,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 		}
 
 		var regex_var = get_temp_variable (regex_type, true, expr, false);
-		expr.temp_vars.add (regex_var);
+		emit_temp_var (regex_var);
 
 		var cdecl = new CCodeDeclaration ("GRegex*");
 
@@ -3756,7 +3659,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
@@ -3867,7 +3770,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);
 			
@@ -3967,7 +3870,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);
 			
@@ -4190,7 +4093,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));
 			}
@@ -4487,7 +4390,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 					var ccomma = new CCodeCommaExpression ();
 
 					var temp_var = get_temp_variable (param.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)));
 
@@ -4559,7 +4462,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 ()));
@@ -4607,7 +4510,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*"));
@@ -4661,7 +4564,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);
@@ -4725,7 +4628,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));
@@ -4743,7 +4646,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;
@@ -5125,7 +5028,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);
 
@@ -5135,7 +5038,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));
@@ -5145,9 +5048,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));
@@ -5166,7 +5069,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 ();
 
@@ -5258,7 +5161,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));
@@ -5380,7 +5283,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)));
 
@@ -5401,7 +5304,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));
@@ -5455,7 +5358,7 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 		var ccomma = new CCodeCommaExpression ();
 		var temp_decl = get_temp_variable (e.value_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;
@@ -5725,9 +5628,6 @@ public class Vala.CCodeBaseModule : CodeGenerator {
 			}
 		}
 
-		append_temp_decl (cfrag, temp_vars);
-		temp_vars.clear ();
-
 		pop_context ();
 
 		source_declarations.add_type_member_declaration (function.copy ());
@@ -5811,7 +5711,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 00a31a8..0d9d185 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 (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) {
+	/*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.temp_vars.add (temp_var);
+		emit_temp_var (temp_var);
 
 		var ctemp = get_variable_cexpression (temp_var.name);
 		var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
@@ -62,7 +60,7 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 		var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
 
 		temp_var = get_temp_variable (gquark_type);
-		stmt.expression.temp_vars.add (temp_var);
+		emit_temp_var (temp_var);
 
 		int label_count = 0;
 
@@ -92,7 +90,6 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 		cinit = new CCodeAssignment (ctemp, ccond);
 
 		cswitchblock.append (new CCodeExpressionStatement (cinit));
-		create_temp_decl (stmt, stmt.expression.temp_vars);
 
 		if (stmt.expression.value_type.value_owned) {
 			// free owned string
@@ -185,40 +182,24 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 		}
 	
 		cswitchblock.append (ctopstmt);
-	}
+	}*/
 
 	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)) {
+		/*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) {
@@ -226,33 +207,27 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 			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 {
 			source_declarations.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.write_begin_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 +239,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.write_declaration (collection_type.get_cname (), ccolvardecl);
 		}
+		ccode.write_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 +258,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.write_declaration ("int", new CCodeVariableDeclarator (get_array_length_cname (collection_backup.name, 1)));
 			}
+			ccode.write_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.write_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 +283,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.write_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name));
 			}
+			ccode.write_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 +296,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.write_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.write_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 +314,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.write_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 +336,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.write_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.write_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr));
+
+			stmt.body.emit (this);
 
-			cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
-			cblock.add_statement (cfor);
+			ccode.close ();
 		} else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
 			// iterating over a GValueArray
 
@@ -414,14 +354,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.write_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 +373,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.write_declaration (stmt.type_reference.get_cname (), new CCodeVariableDeclarator (stmt.variable_name));
 			}
+			ccode.write_expression (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr));
 
-			cbody.add_statement (stmt.body.ccodenode);
+			stmt.body.emit (this);
 
-			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")));
-
-			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.write_expression (get_unref_expression (get_variable_cexpression (local.name), local.variable_type, ma));
 			}
 		}
+
+		ccode.write_end_block ();
 	}
 
 	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 d96a8a7..d18c5bc 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 c3a03e7..0543d07 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -195,7 +195,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)));
 
@@ -348,14 +348,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);
 									}
 
@@ -425,7 +425,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);
@@ -446,7 +446,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) {
@@ -463,14 +463,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)));
 
@@ -530,7 +530,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);
 
@@ -549,7 +549,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));
 
@@ -565,7 +565,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));
 
@@ -575,7 +575,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));
 
@@ -594,7 +594,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);
 
@@ -607,7 +607,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));
 
@@ -623,7 +623,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));
 
@@ -680,7 +680,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));
 
@@ -738,20 +738,16 @@ 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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())));
+			ccode.write_expression (async_call);
+			ccode.write_return (new CCodeConstant ("FALSE"));
+			ccode.add_label ("_state_%d".printf (state));
 		}
 
 		if (m is ArrayResizeMethod) {
@@ -763,7 +759,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 */
 			source_declarations.add_include ("string.h");
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 747631d..df716a7 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -307,6 +307,30 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 			m.result_var.accept (this);
 		}
 
+
+		function = new CCodeFunction (m.get_real_cname ());
+
+		if (m.is_inline) {
+			function.modifiers |= CCodeModifiers.INLINE;
+		}
+
+		if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
+			if (!m.coroutine) {
+				if (m.base_method != null || m.base_interface_method != null) {
+					// declare *_real_* function
+					function.modifiers |= CCodeModifiers.STATIC;
+				} else if (m.is_private_symbol ()) {
+					function.modifiers |= CCodeModifiers.STATIC;
+				}
+			}
+		}
+
+		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+		generate_cparameters (m, source_declarations, cparam_map, function);
+
+		ccode.open_function (function.name, function.return_type, function.parameters, function.modifiers);
+
 		foreach (Expression precondition in m.get_preconditions ()) {
 			precondition.emit (this);
 		}
@@ -316,29 +340,256 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		if (m.body != null) {
-			m.body.emit (this);
-		}
+#if 0
+			if (m.coroutine) {
+				var co_function = new CCodeFunction (m.get_real_cname () + "_co", "gboolean");
 
+				// data struct to hold parameters, local variables, and the return value
+				co_function.add_parameter (new CCodeFormalParameter ("data", Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data*"));
 
-		in_static_or_class_context = false;
+				co_function.modifiers |= CCodeModifiers.STATIC;
+				source_declarations.add_type_member_declaration (co_function.copy ());
 
-		if (m is CreationMethod) {
-			if (in_gobject_creation_method && m.body != null) {
-				var cblock = (CCodeBlock) m.body.ccodenode;
+				// 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"))));
+
+				co_function.block = new CCodeBlock ();
+				co_function.block.add_statement (current_state_switch);
+
+				// coroutine body
+				co_function.block.add_statement (new CCodeLabel ("_state_0"));
+				co_function.block.add_statement (function.block);
+
+				// epilogue
+				co_function.block.add_statement (complete_async ());
+
+				source_type_member_definition.append (co_function);
+			}
+#endif
+
+			if (m.closure) {
+				// add variables for parent closure blocks
+				// as closures only have one parameter for the innermost closure block
+				var closure_block = current_closure_block;
+				int block_id = get_block_id (closure_block);
+				while (true) {
+					var parent_closure_block = next_closure_block (closure_block.parent_symbol);
+					if (parent_closure_block == null) {
+						break;
+					}
+					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));
+					ccode.write_declaration ("Block%dData*".printf (parent_block_id), new CCodeVariableDeclarator ("_data%d_".printf (parent_block_id)));
+					ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("_data%d_".printf (parent_block_id)), parent_data));
+
+					closure_block = parent_closure_block;
+					block_id = parent_block_id;
+				}
+
+				// add self variable for closures
+				// as closures have block data parameter
+				if (m.binding == MemberBinding.INSTANCE) {
+					var cself = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self");
+					ccode.write_declaration ("%s *".printf (current_class.get_cname ()), new CCodeVariableDeclarator ("self"));
+					ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself));
+				}
+			} else if (m.parent_symbol is Class && !m.coroutine) {
+				var cl = (Class) m.parent_symbol;
+				if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
+					Method base_method;
+					ReferenceType base_expression_type;
+					if (m.overrides) {
+						base_method = m.base_method;
+						base_expression_type = new ObjectType ((Class) base_method.parent_symbol);
+					} else {
+						base_method = m.base_interface_method;
+						base_expression_type = new ObjectType ((Interface) base_method.parent_symbol);
+					}
+					var self_target_type = new ObjectType (cl);
+					CCodeExpression cself = transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
+
+					ccode.write_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+					ccode.write_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;
+						ccode.append (ccheckstmt);
+					}
+				}
+			}
+
+			foreach (FormalParameter param in m.get_parameters ()) {
+				if (param.ellipsis) {
+					break;
+				}
+
+				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;
+							ccode.append (type_check);
+						}
+					}
+				} else if (!m.coroutine) {
+					var t = param.variable_type.data_type;
+					if ((t != null && t.is_reference_type ()) || param.variable_type is ArrayType) {
+						// ensure that the passed reference for output parameter is cleared
+						var a = new CCodeAssignment (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (param.name)), new CCodeConstant ("NULL"));
+						var cblock = new CCodeBlock ();
+						cblock.add_statement (new CCodeExpressionStatement (a));
+
+						var condition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (param.name), new CCodeConstant ("NULL"));
+						var if_statement = new CCodeIfStatement (condition, cblock);
+						ccode.append (if_statement);
+					}
+				}
+			}
+
+			if (!(m.return_type is VoidType) && !m.return_type.is_real_non_null_struct_type () && !m.coroutine) {
+				var vardecl =  new CCodeVariableDeclarator ("result", default_value_for_type (m.return_type, true));
+				vardecl.init0 = true;
+				ccode.write_declaration (m.return_type.get_cname (), vardecl);
+			}
+
+			if (m is CreationMethod) {
+				if (in_gobject_creation_method) {
+					if (!((CreationMethod) m).chain_up) {
+						if (current_class.get_type_parameters ().size > 0) {
+							// declare construction parameter array
+							var cparamsinit = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
+							cparamsinit.add_argument (new CCodeIdentifier ("GParameter"));
+							cparamsinit.add_argument (new CCodeConstant ((3 * current_class.get_type_parameters ().size).to_string ()));
+					
+							ccode.write_declaration ("GParameter *", new CCodeVariableDeclarator ("__params"));
+							ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("__params"), cparamsinit));
+
+							ccode.write_declaration ("GParameter *", new CCodeVariableDeclarator ("__params_it"));
+							ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("__params_it"), new CCodeIdentifier ("__params")));
+						}
+
+						/* type, dup func, and destroy func properties for generic types */
+						foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
+							CCodeConstant prop_name;
+							CCodeIdentifier param_name;
+
+							prop_name = new CCodeConstant ("\"%s-type\"".printf (type_param.name.down ()));
+							param_name = new CCodeIdentifier ("%s_type".printf (type_param.name.down ()));
+							ccode.write_expression (get_construct_property_assignment (prop_name, new IntegerType ((Struct) gtype_type), param_name));
+
+							prop_name = new CCodeConstant ("\"%s-dup-func\"".printf (type_param.name.down ()));
+							param_name = new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ()));
+							ccode.write_expression (get_construct_property_assignment (prop_name, new PointerType (new VoidType ()), param_name));
+
+							prop_name = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ()));
+							param_name = new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ()));
+							ccode.write_expression (get_construct_property_assignment (prop_name, new PointerType (new VoidType ()), param_name));
+						}
+					}
+
+					add_object_creation (current_class.get_type_parameters ().size > 0);
+				} else if (is_gtypeinstance_creation_method (m)) {
+					var cl = (Class) m.parent_symbol;
+					ccode.write_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_type_create_instance"));
+						ccall.add_argument (new CCodeIdentifier ("object_type"));
+						ccode.write_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 ()) {
+							CCodeIdentifier param_name;
+							CCodeAssignment assign;
+
+							var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv");
+
+							param_name = new CCodeIdentifier ("%s_type".printf (type_param.name.down ()));
+							assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name);
+							ccode.write_expression (assign);
 
-				if (!((CreationMethod) m).chain_up) {
-					prepend_object_creation (cblock, current_class.get_type_parameters ().size > 0);
+							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);
+							ccode.write_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);
+							ccode.write_expression (assign);
+						}
+					}
+				} else if (current_type_symbol is Class) {
+					var cl = (Class) m.parent_symbol;
+					ccode.write_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 ()));
+						ccode.write_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"));
+						ccode.write_expression (cinitcall);
+					}
 				} else {
-					var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) current_type_symbol).get_cname ()));
-					cdeclaration.add_declarator (new CCodeVariableDeclarator ("self"));
+					var st = (Struct) m.parent_symbol;
+
+					// memset needs string.h
+					source_declarations.add_include ("string.h");
+					var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
+					czero.add_argument (new CCodeIdentifier ("self"));
+					czero.add_argument (new CCodeConstant ("0"));
+					czero.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (st.get_cname ())));
+					ccode.write_expression (czero);
+				}
+			}
+
+			m.body.emit (this);
 
-					cblock.prepend_statement (cdeclaration);
+			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
+				 */
+				if (m.coroutine) {
+					closure_struct.add_field ("GError *", "_inner_error_");
+
+					// no initialization necessary, closure struct is zeroed
+				} else {
+					ccode.write_declaration ("GError *", new CCodeVariableDeclarator.zero ("_inner_error_", new CCodeConstant ("NULL")));
+				}
+			}
+
+			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) {
+					ccode.write_return (new CCodeIdentifier ("result"));
+				}
+			}
+
+			if (m is CreationMethod) {
+				if (current_type_symbol is Class) {
+					ccode.write_return (new CCodeIdentifier ("self"));
 				}
 			}
+
+			ccode.close ();
 		}
 
+
+		in_static_or_class_context = false;
+
 		bool inner_error = current_method_inner_error;
 
+		var method_context = emit_context;
 		pop_context ();
 
 		// do not declare overriding methods and interface implementations
@@ -359,13 +610,12 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 		}
 
 		function = new CCodeFunction (m.get_real_cname ());
-		m.ccodenode = function;
 
 		if (m.is_inline) {
 			function.modifiers |= CCodeModifiers.INLINE;
 		}
 
-		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+		cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
 		generate_cparameters (m, source_declarations, cparam_map, function);
 
@@ -385,97 +635,12 @@ 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 = method_context.ccode.get_block ();
 				function.block.line = function.line;
 
 				var cinit = new CCodeFragment ();
 				function.block.prepend_statement (cinit);
 
-				if (m.coroutine) {
-					var co_function = new CCodeFunction (m.get_real_cname () + "_co", "gboolean");
-
-					// data struct to hold parameters, local variables, and the return value
-					co_function.add_parameter (new CCodeFormalParameter ("data", Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data*"));
-
-					co_function.modifiers |= CCodeModifiers.STATIC;
-					source_declarations.add_type_member_declaration (co_function.copy ());
-
-					// 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"))));
-
-					co_function.block = new CCodeBlock ();
-					co_function.block.add_statement (current_state_switch);
-
-					// coroutine body
-					co_function.block.add_statement (new CCodeLabel ("_state_0"));
-					co_function.block.add_statement (function.block);
-
-					// epilogue
-					co_function.block.add_statement (complete_async ());
-
-					source_type_member_definition.append (co_function);
-				}
-
-				if (m.closure) {
-					// add variables for parent closure blocks
-					// as closures only have one parameter for the innermost closure block
-					var closure_block = current_closure_block;
-					int block_id = get_block_id (closure_block);
-					while (true) {
-						var parent_closure_block = next_closure_block (closure_block.parent_symbol);
-						if (parent_closure_block == null) {
-							break;
-						}
-						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);
-
-						closure_block = parent_closure_block;
-						block_id = parent_block_id;
-					}
-
-					// add self variable for closures
-					// 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);
-					}
-				} else if (m.parent_symbol is Class && !m.coroutine) {
-					var cl = (Class) m.parent_symbol;
-					if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
-						Method base_method;
-						ReferenceType base_expression_type;
-						if (m.overrides) {
-							base_method = m.base_method;
-							base_expression_type = new ObjectType ((Class) base_method.parent_symbol);
-						} else {
-							base_method = m.base_interface_method;
-							base_expression_type = new ObjectType ((Interface) base_method.parent_symbol);
-						}
-						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);
-					} 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);
-						}
-					}
-				}
 				foreach (FormalParameter param in m.get_parameters ()) {
 					if (param.ellipsis) {
 						break;
@@ -505,36 +670,9 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 					}
 				}
 
-				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);
-
-					// 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")));
-					}
-				}
-
-				if (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
-					 */
-					if (m.coroutine) {
-						closure_struct.add_field ("GError *", "_inner_error_");
-
-						// no initialization necessary, closure struct is zeroed
-					} else {
-						var cdecl = new CCodeDeclaration ("GError *");
-						cdecl.add_declarator (new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
-						cinit.append (cdecl);
-					}
-				}
 
 				if (!m.coroutine) {
-					source_type_member_definition.append (function);
+					source_type_member_definition.append (method_context.ccode.get_node ());
 				}
 			
 				if (m is CreationMethod) {
@@ -581,7 +719,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 						cinit.append (cdeclaration);
 
 						if (!((CreationMethod) m).chain_up) {
-							// TODO implicitly chain up to base class as in prepend_object_creation
+							// TODO implicitly chain up to base class as in add_object_creation
 							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 () + "*");
@@ -614,7 +752,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 						cinit.append (cdeclaration);
 
 						if (!((CreationMethod) m).chain_up) {
-							// TODO implicitly chain up to base class as in prepend_object_creation
+							// 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;
@@ -1027,14 +1165,13 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 		return null;
 	}
 
-	private void prepend_object_creation (CCodeBlock b, bool has_params) {
+	private void add_object_creation (bool has_params) {
 		var cl = (Class) current_type_symbol;
 
 		if (!has_params && cl.base_class != gobject_type) {
 			// possibly report warning or error about missing base call
 		}
 
-		var cdecl = new CCodeVariableDeclarator ("self");
 		var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
 		ccall.add_argument (new CCodeIdentifier ("object_type"));
 		if (has_params) {
@@ -1044,12 +1181,9 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
 			ccall.add_argument (new CCodeConstant ("0"));
 			ccall.add_argument (new CCodeConstant ("NULL"));
 		}
-		cdecl.initializer = ccall;
-		
-		var cdeclaration = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-		cdeclaration.add_declarator (cdecl);
 		
-		b.prepend_statement (cdeclaration);
+		ccode.write_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+		ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall));
 	}
 
 	public override void visit_creation_method (CreationMethod m) {
diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala
index 84697a5..ced8c9c 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, source_declarations);
 
@@ -166,7 +166,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,9 +294,6 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
 			}
 		}
 
-		append_temp_decl (cfrag, temp_vars);
-		temp_vars.clear ();
-
 		function.block = cblock;
 
 		source_type_member_definition.append (function);
@@ -312,7 +309,7 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
 
 		var cblock = new CCodeBlock ();
 
-		cblock.add_statement (instance_finalize_fragment);
+		cblock.add_statement (instance_finalize_context.ccode.get_node ());
 
 		function.block = cblock;
 
diff --git a/codegen/valadovaarraymodule.vala b/codegen/valadovaarraymodule.vala
index 5e3478f..fab04ce 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 dd49e86..cf1ca51 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 01f2b7c..66b4c36 100644
--- a/codegen/valadovabasemodule.vala
+++ b/codegen/valadovabasemodule.vala
@@ -299,7 +299,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 		}
 
 		if (csource_filename != null) {
-			var writer = new CCodeWriter (csource_filename);
+			var writer = new CCodeFileWriter (csource_filename);
 			if (!writer.open (context.version_header)) {
 				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 				return;
@@ -330,7 +330,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 
 		// generate C header file for public API
 		if (context.header_filename != null) {
-			var writer = new CCodeWriter (context.header_filename);
+			var writer = new CCodeFileWriter (context.header_filename);
 			if (!writer.open (context.version_header)) {
 				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 				return;
@@ -379,7 +379,7 @@ public class Vala.DovaBaseModule : CodeGenerator {
 		if (csource_filename == null) {
 			csource_filename = source_file.get_csource_filename ();
 		} else {
-			var writer = new CCodeWriter (source_file.get_csource_filename ());
+			var writer = new CCodeFileWriter (source_file.get_csource_filename ());
 			if (!writer.open (context.version_header)) {
 				Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 				return;
@@ -1297,6 +1297,9 @@ public class Vala.DovaBaseModule : CodeGenerator {
 		temp_ref_vars.clear ();
 	}
 
+	public void emit_temp_var (LocalVariable local) {
+	}
+
 	public void append_temp_decl (CCodeFragment cfrag, List<LocalVariable> temp_vars) {
 		foreach (LocalVariable local in temp_vars) {
 			var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
@@ -1593,7 +1596,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
@@ -1685,7 +1688,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);
 
@@ -1729,7 +1732,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);
 
@@ -1952,7 +1955,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)));
 
@@ -2008,7 +2011,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 ();
@@ -2025,7 +2028,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 ();
@@ -2068,7 +2071,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));
@@ -2216,7 +2219,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);
 			}
diff --git a/codegen/valadovamemberaccessmodule.vala b/codegen/valadovamemberaccessmodule.vala
index 2b8c621..acfccc6 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 40f56b4..213fc86 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/valadovavaluemodule.vala b/codegen/valadovavaluemodule.vala
index 08e2ec7..61e4af1 100644
--- a/codegen/valadovavaluemodule.vala
+++ b/codegen/valadovavaluemodule.vala
@@ -549,7 +549,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 +583,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 +619,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 +629,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 +658,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 +667,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 +691,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 c8fb945..b2034cd 100644
--- a/codegen/valagasyncmodule.vala
+++ b/codegen/valagasyncmodule.vala
@@ -139,7 +139,7 @@ public class Vala.GAsyncModule : GSignalModule {
 	}
 
 	CCodeFunction generate_async_function (Method m) {
-		var asyncblock = new CCodeBlock ();
+		push_context (new EmitContext (m));
 
 		// logic copied from valaccodemethodmodule
 		if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
@@ -156,9 +156,7 @@ 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.write_declaration ("%s *".printf (type_symbol.get_cname ()), new CCodeVariableDeclarator ("self", cself));
 		}
 
 		var dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
@@ -170,10 +168,8 @@ public class Vala.GAsyncModule : GSignalModule {
 
 		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.write_declaration (dataname + "*", new CCodeVariableDeclarator ("_data_"));
+		ccode.write_expression (new CCodeAssignment (data_var, dataalloc));
 
 		var create_result = new CCodeFunctionCall (new CCodeIdentifier ("g_simple_async_result_new"));
 
@@ -201,13 +197,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.write_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.write_expression (set_op_res_call);
 
 		if (m.binding == MemberBinding.INSTANCE) {
 			CCodeExpression self_expr = new CCodeIdentifier ("self");
@@ -219,7 +215,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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "self"), self_expr));
 		}
 
 		foreach (FormalParameter param in m.get_parameters ()) {
@@ -238,34 +234,29 @@ 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.write_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.write_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.write_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.write_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));
+		ccode.write_expression (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"));
@@ -280,7 +271,9 @@ public class Vala.GAsyncModule : GSignalModule {
 			asyncfunc.modifiers |= CCodeModifiers.STATIC;
 		}
 
-		asyncfunc.block = asyncblock;
+		pop_context ();
+
+		asyncfunc.block = ccode.get_block ();
 
 		return asyncfunc;
 	}
@@ -394,20 +387,16 @@ public class Vala.GAsyncModule : GSignalModule {
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
-		var finishblock = new CCodeBlock ();
+		push_context (new EmitContext (m));
 
 		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.write_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.write_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 +406,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.write_return ();
 			} else {
-				errorblock.add_statement (new CCodeReturnStatement (default_value_for_type (return_type, false)));
+				ccode.write_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.write_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.write_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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL")));
 				}
 			}
 		}
@@ -445,30 +435,25 @@ 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.write_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.write_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.write_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.write_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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (data_var, "result"), new CCodeConstant ("NULL")));
 			}
-			finishblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+			ccode.write_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*"));
 
 		generate_cparameters (m, source_declarations, cparam_map, finishfunc, null, null, null, 2);
@@ -477,7 +462,9 @@ public class Vala.GAsyncModule : GSignalModule {
 			finishfunc.modifiers |= CCodeModifiers.STATIC;
 		}
 
-		finishfunc.block = finishblock;
+		pop_context ();
+
+		finishfunc.block = ccode.get_block ();
 
 		return finishfunc;
 	}
@@ -576,68 +563,44 @@ public class Vala.GAsyncModule : GSignalModule {
 			return;
 		}
 
-		stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.yield_expression.ccodenode);
+		ccode.write_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.write_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.write_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));
-
-		var free_locals = new CCodeFragment ();
-		append_local_free (current_symbol, free_locals, false);
-		block.add_statement (free_locals);
+		ccode.write_expression (free_error);
 
-		block.add_statement (complete_async ());
+		append_local_free (current_symbol, false);
 
-		return block;
+		ccode.append (complete_async ());
 	}
 
 	public override void visit_return_statement (ReturnStatement stmt) {
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index dccb21b..e1c043d 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.write_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.write_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.write_expression (unref_call);
+			ccode.write_return (new CCodeConstant ("NULL"));
 		} else if (current_method != null && current_method.coroutine) {
-			cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+			ccode.write_return (new CCodeConstant ("FALSE"));
 		} else if (current_return_type is VoidType) {
-			cerror_block.add_statement (new CCodeReturnStatement ());
+			ccode.write_return ();
 		} else {
-			cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+			ccode.write_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.write_expression (ccritical);
+		ccode.write_expression (cclear);
 
 		if (current_method is CreationMethod) {
-			cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL")));
+			ccode.write_return (new CCodeConstant ("NULL"));
 		} else if (current_method != null && current_method.coroutine) {
-			cerror_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+			ccode.write_return (new CCodeConstant ("FALSE"));
 		} else if (current_return_type is VoidType) {
-			cerror_block.add_statement (new CCodeReturnStatement ());
+			ccode.write_return ();
 		} else if (current_return_type != null) {
-			cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
+			ccode.write_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.write_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.write_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.write_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 ();
 		}
 	}
 
@@ -327,7 +298,11 @@ public class Vala.GErrorModule : CCodeDelegateModule {
 		}
 
 		if (stmt.finally_body != null) {
+			var old_ccode = ccode;
+			emit_context.ccode = new CCodeBuilder ();
 			stmt.finally_body.emit (this);
+			stmt.finally_body.ccodenode = emit_context.ccode.get_node ();
+			emit_context.ccode = old_ccode;
 		}
 
 		is_in_catch = false;
@@ -335,6 +310,7 @@ public class Vala.GErrorModule : CCodeDelegateModule {
 		is_in_catch = true;
 
 		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
+			ccode.write_goto ("__finally%d".printf (this_try_id));
 			clause.emit (this);
 		}
 
@@ -342,24 +318,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);
+			ccode.append (stmt.finally_body.ccodenode);
 		}
 
 		// 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 +336,9 @@ public class Vala.GErrorModule : CCodeDelegateModule {
 			generate_error_domain_declaration (error_type.error_domain, source_declarations);
 		}
 
-		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.write_begin_block ();
 
 		string variable_name;
 		if (clause.variable_name != null) {
@@ -384,31 +347,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.write_declaration ("GError *", new CCodeVariableDeclarator (variable_name));
 			}
+			ccode.write_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.write_expression (cclear);
 		}
-		cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression ("_inner_error_"), new CCodeConstant ("NULL"))));
+		ccode.write_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.write_end_block ();
 	}
 
-	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 +376,10 @@ public class Vala.GErrorModule : CCodeDelegateModule {
 		}
 
 		if (finally_block != null) {
-			cfrag.append (finally_block.ccodenode);
+			ccode.append (finally_block.ccodenode);
 		}
 
-		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 59ef5ee..34e01d8 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 ("%s_get_property".printf (cl.get_lower_case_cname (null))))));
+			ccode.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%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 ("%s_set_property".printf (cl.get_lower_case_cname (null))))));
+			ccode.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%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.write_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.write_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.write_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.write_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.write_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.append (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.write_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.write_expression (cinst);
 			}
 		}
 	}
@@ -536,12 +536,10 @@ public class Vala.GObjectModule : GTypeModule {
 				/* 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);
+				base_init_context.ccode.write_declaration ("GError *", new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
 			}
 
-			base_init_fragment.append (c.body.ccodenode);
+			base_init_context.ccode.append (c.body.ccodenode);
 		} else if (c.binding == MemberBinding.STATIC) {
 			// static class constructor
 			// add to class_init
@@ -556,12 +554,10 @@ public class Vala.GObjectModule : GTypeModule {
 				/* 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);
+				class_init_context.ccode.write_declaration ("GError *", new CCodeVariableDeclarator ("_inner_error_", new CCodeConstant ("NULL")));
 			}
 
-			class_init_fragment.append (c.body.ccodenode);
+			class_init_context.ccode.append (c.body.ccodenode);
 		} else {
 			Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
 		}
@@ -789,7 +785,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 is_floating_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_is_floating"));
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index e36f5f2..89fbb11 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -649,7 +649,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 (sig.get_canonical_cconstant (signal_detail));
 			var decl_type = (TypeSymbol) sig.parent_symbol;
@@ -661,7 +661,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 c989a39..e799257 100644
--- a/codegen/valagtypemodule.vala
+++ b/codegen/valagtypemodule.vala
@@ -496,12 +496,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;
@@ -514,12 +514,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, source_declarations);
@@ -532,6 +532,19 @@ public class Vala.GTypeModule : GErrorModule {
 			generate_class_struct_declaration (cl, internal_header_declarations);
 		}
 
+		if (is_gtypeinstance) {
+			begin_class_init_function (cl);
+			begin_instance_init_function (cl);
+
+			if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
+				begin_finalize_function (cl);
+			}
+		} else {
+			if (cl.base_class == null) {
+				begin_instance_init_function (cl);
+			}
+		}
+
 		cl.accept_children (this);
 
 		if (is_gtypeinstance) {
@@ -557,7 +570,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.write_expression (ref_count);
 			}
 
 
@@ -666,7 +679,7 @@ public class Vala.GTypeModule : GErrorModule {
 					cblock.add_statement (cl.destructor.ccodenode);
 				}
 
-				cblock.add_statement (instance_finalize_fragment);
+				cblock.add_statement (instance_finalize_context.ccode.get_node ());
 
 				var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
 				ccall.add_argument (new CCodeIdentifier (cl.get_cname ()));
@@ -681,12 +694,12 @@ public class Vala.GTypeModule : GErrorModule {
 
 		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 ();
 	}
@@ -1186,25 +1199,23 @@ public class Vala.GTypeModule : GErrorModule {
 			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);
+			base_finalize_context.ccode.append (block);
 		}
 
-		init_block.add_statement (base_init_fragment);
+		init_block.add_statement (base_init_context.ccode.get_node ());
 
 		source_type_member_definition.append (base_init);
 	}
 
-	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 parameters = ccode.parameters (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
+		ccode.open_function ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void", parameters, CCodeModifiers.STATIC);
 
-		var init_block = new CCodeBlock ();
-		class_init.block = init_block;
-		
 		CCodeFunctionCall ccall;
 		
 		/* save pointer to parent class */
@@ -1214,10 +1225,11 @@ public class Vala.GTypeModule : GErrorModule {
 		parent_decl.add_declarator (parent_var_decl);
 		parent_decl.modifiers = CCodeModifiers.STATIC;
 		source_declarations.add_type_member_declaration (parent_decl);
+
 		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.write_expression (parent_assignment);
 		
 
 		if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
@@ -1230,7 +1242,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.write_expression (finalize_assignment);
 		}
 
 		/* add struct for private fields */
@@ -1238,7 +1250,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.write_expression (ccall);
 		}
 
 		/* connect overridden methods */
@@ -1253,10 +1265,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.write_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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.get_finish_vfunc_name ()), new CCodeIdentifier (m.get_finish_real_cname ())));
 				}
 			}
 		}
@@ -1268,7 +1280,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.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ())));
 		}
 
 		/* connect overridden properties */
@@ -1283,30 +1295,35 @@ 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.write_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.write_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.append (new CCodeComment (sig.comment.content));
 				}
-				init_block.add_statement (new CCodeExpressionStatement (get_signal_creation (sig, cl)));
+				ccode.write_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);
+
+		pop_context ();
+	}
+
+	private void add_class_init_function (Class cl) {
+		class_init_context.ccode.close ();
 
-		source_type_member_definition.append (class_init);
+		source_type_member_definition.append (class_init_context.ccode.get_node ());
 	}
 	
 	private void add_interface_init_function (Class cl, Interface iface) {
@@ -1520,29 +1537,35 @@ 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 parameters = ccode.parameters (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ())));
+		ccode.open_function ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void", parameters, CCodeModifiers.STATIC);
+
+		var decl = new CCodeBuilder ();
+		decl.write_function_declaration ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void", parameters, CCodeModifiers.STATIC);
+		source_declarations.add_type_member_declaration (decl.get_node ());
+
 		if (cl.is_compact) {
 			// Add declaration, since the instance_init function is explicitly called
 			// by the creation methods
-			source_declarations.add_type_member_declaration (instance_init.copy ());
+			//source_declarations.add_type_member_declaration (instance_init.copy ());
 		}
 
-		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)));
+			ccode.write_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall));
 		}
-		
-		init_block.add_statement (instance_init_fragment);
 
-		source_type_member_definition.append (instance_init);
+		pop_context ();
+	}
+
+	private void add_instance_init_function (Class cl) {
+		instance_init_context.ccode.close ();
+
+		source_type_member_definition.append (instance_init_context.ccode.get_node ());
 	}
 
 	private void add_class_finalize_function (Class cl) {
@@ -1558,7 +1581,7 @@ public class Vala.GTypeModule : GErrorModule {
 			cblock.add_statement (cl.class_destructor.ccodenode);
 		}
 
-		cblock.add_statement (class_finalize_fragment);
+		cblock.add_statement (class_finalize_context.ccode.get_node ());
 
 		function.block = cblock;
 		source_type_member_definition.append (function);
@@ -1577,54 +1600,57 @@ public class Vala.GTypeModule : GErrorModule {
 			cblock.add_statement (cl.class_destructor.ccodenode);
 		}
 
-		cblock.add_statement (base_finalize_fragment);
+		cblock.add_statement (base_finalize_context.ccode.get_node ());
 
 		function.block = cblock;
 		source_type_member_definition.append (function);
 	}
 
-	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 begin_finalize_function (Class cl) {
+		push_context (instance_finalize_context);
 
 		var fundamental_class = cl;
 		while (fundamental_class.base_class != null) {
 			fundamental_class = fundamental_class.base_class;
 		}
 
-		function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
-
-		source_declarations.add_type_member_declaration (function.copy ());
-
+		var parameters = ccode.parameters (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
+		ccode.open_function ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void", parameters, CCodeModifiers.STATIC);
 
-		var cblock = new CCodeBlock ();
+		var decl = new CCodeBuilder ();
+		decl.write_function_declaration ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void", parameters, CCodeModifiers.STATIC);
+		source_declarations.add_type_member_declaration (decl.get_node ());
 
 		CCodeFunctionCall ccall = generate_instance_cast (new CCodeIdentifier ("obj"), cl);
 
-		var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-		cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall));
-		
-		cblock.add_statement (cdecl);
+		ccode.write_declaration ("%s *".printf (cl.get_cname ()), new CCodeVariableDeclarator ("self"));
+		ccode.write_expression (new CCodeAssignment (new CCodeIdentifier ("self"), ccall));
 
 		if (cl.destructor != null) {
-			cblock.add_statement (cl.destructor.ccodenode);
+			cl.destructor.body.emit (this);
 		}
 
-		cblock.add_statement (instance_finalize_fragment);
+		pop_context ();
+	}
+
+	private void add_finalize_function (Class cl) {
+		var fundamental_class = cl;
+		while (fundamental_class.base_class != null) {
+			fundamental_class = fundamental_class.base_class;
+		}
 
 		// 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"));
+			var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize"));
 			ccall.add_argument (new CCodeIdentifier ("obj"));
-			cblock.add_statement (new CCodeExpressionStatement (ccall));
+			instance_finalize_context.ccode.write_expression (ccall);
 		}
 
+		instance_finalize_context.ccode.close ();
 
-		function.block = cblock;
-
-		source_type_member_definition.append (function);
+		source_type_member_definition.append (instance_finalize_context.ccode.get_node ());
 	}
 
 	public override CCodeFunctionCall get_param_spec (Property prop) {
@@ -1667,7 +1693,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 ()));
 			}
@@ -1678,7 +1704,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"));
 				}
@@ -1687,7 +1713,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"));
 				}
@@ -1696,7 +1722,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"));
 				}
@@ -1705,7 +1731,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"));
 				}
@@ -1714,7 +1740,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"));
 				}
@@ -1723,14 +1749,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"));
 				}
@@ -1739,7 +1765,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"));
 				}
@@ -1748,7 +1774,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"));
 				}
@@ -1757,7 +1783,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"));
 				}
@@ -1766,14 +1792,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"));
 				}
@@ -2043,7 +2069,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 ()));



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