vala r1967 - in trunk: . gobject



Author: juergbi
Date: Mon Nov  3 20:50:43 2008
New Revision: 1967
URL: http://svn.gnome.org/viewvc/vala?rev=1967&view=rev

Log:
2008-11-03  JÃrg Billeter  <j bitron ch>

	* gobject/valaccodearraymodule.vala:
	* gobject/valaccodeassignmentmodule.vala:
	* gobject/valaccodebasemodule.vala:
	* gobject/valaccodedynamicpropertymodule.vala:
	* gobject/valaccodedynamicsignalmodule.vala:
	* gobject/valaccodegenerator.vala:
	* gobject/valaccodeinvocationexpressionmodule.vala:
	* gobject/valaccodememberaccessmodule.vala:
	* gobject/valaccodemethodmodule.vala:
	* gobject/valaccodemodule.vala:
	* gobject/valaccodestructmodule.vala:
	* gobject/valaclassregisterfunction.vala:
	* gobject/valadbusclientmodule.vala:
	* gobject/valadbusservermodule.vala:
	* gobject/valagasyncmodule.vala:
	* gobject/valagerrormodule.vala:
	* gobject/valagirwriter.vala:
	* gobject/valagobjectmodule.vala:
	* gobject/valagsignalmodule.vala:
	* gobject/valagtypemodule.vala:
	* gobject/valainterfaceregisterfunction.vala:
	* gobject/valatyperegisterfunction.vala:

	Move code generation to module


Modified:
   trunk/ChangeLog
   trunk/gobject/valaccodearraymodule.vala
   trunk/gobject/valaccodeassignmentmodule.vala
   trunk/gobject/valaccodebasemodule.vala
   trunk/gobject/valaccodedynamicpropertymodule.vala
   trunk/gobject/valaccodedynamicsignalmodule.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodeinvocationexpressionmodule.vala
   trunk/gobject/valaccodememberaccessmodule.vala
   trunk/gobject/valaccodemethodmodule.vala
   trunk/gobject/valaccodemodule.vala
   trunk/gobject/valaccodestructmodule.vala
   trunk/gobject/valaclassregisterfunction.vala
   trunk/gobject/valadbusclientmodule.vala
   trunk/gobject/valadbusservermodule.vala
   trunk/gobject/valagasyncmodule.vala
   trunk/gobject/valagerrormodule.vala
   trunk/gobject/valagirwriter.vala
   trunk/gobject/valagobjectmodule.vala
   trunk/gobject/valagsignalmodule.vala
   trunk/gobject/valagtypemodule.vala
   trunk/gobject/valainterfaceregisterfunction.vala
   trunk/gobject/valatyperegisterfunction.vala

Modified: trunk/gobject/valaccodearraymodule.vala
==============================================================================
--- trunk/gobject/valaccodearraymodule.vala	(original)
+++ trunk/gobject/valaccodearraymodule.vala	Mon Nov  3 20:50:43 2008
@@ -44,12 +44,12 @@
 		foreach (Expression size in expr.get_sizes ()) {
 			CCodeExpression csize = (CCodeExpression) size.ccodenode;
 
-			if (!codegen.is_pure_ccode_expression (csize)) {
-				var temp_var = codegen.get_temp_variable (codegen.int_type, false, expr);
+			if (!is_pure_ccode_expression (csize)) {
+				var temp_var = get_temp_variable (int_type, false, expr);
 				var name_cnode = new CCodeIdentifier (temp_var.name);
 				size.ccodenode = name_cnode;
 
-				codegen.temp_vars.insert (0, temp_var);
+				temp_vars.insert (0, temp_var);
 
 				csize = new CCodeParenthesizedExpression (new CCodeAssignment (name_cnode, csize));
 			}
@@ -77,11 +77,11 @@
 			}
 
 			var ce = new CCodeCommaExpression ();
-			var temp_var = codegen.get_temp_variable (expr.value_type, true, expr);
+			var temp_var = get_temp_variable (expr.value_type, true, expr);
 			var name_cnode = new CCodeIdentifier (temp_var.name);
 			int i = 0;
 			
-			codegen.temp_vars.insert (0, temp_var);
+			temp_vars.insert (0, temp_var);
 			
 			ce.append_expression (new CCodeAssignment (name_cnode, gnew));
 			
@@ -133,7 +133,7 @@
 		if (array_expr is ArrayCreationExpression) {
 			Gee.List<Expression> size = ((ArrayCreationExpression) array_expr).get_sizes ();
 			var length_expr = size[dim - 1];
-			return (CCodeExpression) codegen.get_ccodenode (length_expr);
+			return (CCodeExpression) get_ccodenode (length_expr);
 		} else if (array_expr is InvocationExpression) {
 			var invocation_expr = (InvocationExpression) array_expr;
 			Gee.List<CCodeExpression> size = invocation_expr.get_array_sizes ();
@@ -176,9 +176,9 @@
 						}
 
 						var length_cname = get_array_length_cname (field.name, dim);
-						var instance_expression_type = codegen.get_data_type_for_symbol (base_type);
-						var instance_target_type = codegen.get_data_type_for_symbol ((TypeSymbol) field.parent_symbol);
-						CCodeExpression typed_inst = (CCodeExpression) codegen.get_ccodenode (ma.inner);
+						var instance_expression_type = get_data_type_for_symbol (base_type);
+						var instance_target_type = get_data_type_for_symbol ((TypeSymbol) field.parent_symbol);
+						CCodeExpression typed_inst = (CCodeExpression) get_ccodenode (ma.inner);
 
 						CCodeExpression inst;
 						if (field.access == SymbolAccessibility.PRIVATE) {
@@ -242,7 +242,7 @@
 				int dim = lit.value.to_int ();
 				expr.ccodenode = head.get_array_length_cexpression (memberaccess.inner, dim + 1);
 			}
-		} else if (container_type == codegen.string_type.data_type) {
+		} else if (container_type == string_type.data_type) {
 			// should be moved to a different module
 
 			// access to unichar in a string
@@ -254,15 +254,15 @@
 			ccall.add_argument (coffsetcall);
 
 			expr.ccodenode = ccall;
-		} else if (container_type != null && codegen.list_type != null && codegen.map_type != null &&
-		           (container_type.is_subtype_of (codegen.list_type) || container_type.is_subtype_of (codegen.map_type))) {
+		} else if (container_type != null && list_type != null && map_type != null &&
+		           (container_type.is_subtype_of (list_type) || container_type.is_subtype_of (map_type))) {
 			// should be moved to a different module
 
 			TypeSymbol collection_iface = null;
-			if (container_type.is_subtype_of (codegen.list_type)) {
-				collection_iface = codegen.list_type;
-			} else if (container_type.is_subtype_of (codegen.map_type)) {
-				collection_iface = codegen.map_type;
+			if (container_type.is_subtype_of (list_type)) {
+				collection_iface = list_type;
+			} else if (container_type.is_subtype_of (map_type)) {
+				collection_iface = map_type;
 			}
 			var get_method = (Method) collection_iface.scope.lookup ("get");
 			Gee.List<FormalParameter> get_params = get_method.get_parameters ();
@@ -272,14 +272,14 @@
 
 			if (get_param.parameter_type.type_parameter != null) {
 				var index_type = SemanticAnalyzer.get_actual_type (expr.container.value_type, get_method, get_param.parameter_type, expr);
-				cindex = codegen.convert_to_generic_pointer (cindex, index_type);
+				cindex = convert_to_generic_pointer (cindex, index_type);
 			}
 
 			var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
 			get_ccall.add_argument (new CCodeCastExpression (ccontainer, collection_iface.get_cname () + "*"));
 			get_ccall.add_argument (cindex);
 
-			expr.ccodenode = codegen.convert_from_generic_pointer (get_ccall, expr.value_type);
+			expr.ccodenode = convert_from_generic_pointer (get_ccall, expr.value_type);
 		} else if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
 			// should be moved to the GSignal module
 
@@ -342,7 +342,7 @@
 		fun.add_parameter (new CCodeFormalParameter ("array", "gpointer"));
 		fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
 		fun.add_parameter (new CCodeFormalParameter ("destroy_func", "GDestroyNotify"));
-		codegen.source_type_member_declaration.append (fun.copy ());
+		source_type_member_declaration.append (fun.copy ());
 
 		var cdofree = new CCodeBlock ();
 
@@ -364,11 +364,11 @@
 		carrfree.add_argument (new CCodeIdentifier ("array"));
 		fun.block.add_statement (new CCodeExpressionStatement (carrfree));
 
-		codegen.source_type_member_definition.append (fun);
+		source_type_member_definition.append (fun);
 	}
 
 	public override void append_vala_array_move () {
-		codegen.string_h_needed = true;
+		string_h_needed = true;
 
 		// assumes that overwritten array elements are null before invocation
 		// FIXME will leak memory if that's not the case
@@ -379,7 +379,7 @@
 		fun.add_parameter (new CCodeFormalParameter ("src", "gint"));
 		fun.add_parameter (new CCodeFormalParameter ("dest", "gint"));
 		fun.add_parameter (new CCodeFormalParameter ("length", "gint"));
-		codegen.source_type_member_declaration.append (fun.copy ());
+		source_type_member_declaration.append (fun.copy ());
 
 		var array = new CCodeCastExpression (new CCodeIdentifier ("array"), "char*");
 		var element_size = new CCodeIdentifier ("element_size");
@@ -414,6 +414,6 @@
 
 		fun.block.add_statement (new CCodeIfStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, src, dest), czeroblock1, czeroblock2));
 
-		codegen.source_type_member_definition.append (fun);
+		source_type_member_definition.append (fun);
 	}
 }

Modified: trunk/gobject/valaccodeassignmentmodule.vala
==============================================================================
--- trunk/gobject/valaccodeassignmentmodule.vala	(original)
+++ trunk/gobject/valaccodeassignmentmodule.vala	Mon Nov  3 20:50:43 2008
@@ -37,14 +37,14 @@
 
 		var prop = (Property) assignment.left.symbol_reference;
 
-		if (prop.set_accessor.construction && codegen.current_type_symbol is Class && codegen.current_class.is_subtype_of (codegen.gobject_type) && codegen.in_creation_method) {
+		if (prop.set_accessor.construction && current_type_symbol is Class && current_class.is_subtype_of (gobject_type) && in_creation_method) {
 			return head.get_construct_property_assignment (prop.get_canonical_cconstant (), prop.property_type, (CCodeExpression) assignment.right.ccodenode);
 		} else {
 			CCodeExpression cexpr = (CCodeExpression) assignment.right.ccodenode;
 
 			if (!prop.no_accessor_method) {
 				if (prop.property_type.is_real_struct_type ()) {
-					cexpr = codegen.get_address_of_expression (assignment.right, cexpr);
+					cexpr = get_address_of_expression (assignment.right, cexpr);
 				}
 			}
 
@@ -71,16 +71,16 @@
 				} else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
 					cop = CCodeBinaryOperator.SHIFT_RIGHT;
 				}
-				cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) codegen.get_ccodenode (assignment.left), new CCodeParenthesizedExpression (cexpr));
+				cexpr = new CCodeBinaryExpression (cop, (CCodeExpression) get_ccodenode (assignment.left), new CCodeParenthesizedExpression (cexpr));
 			}
 			
-			var ccall = codegen.get_property_set_call (prop, ma, cexpr);
+			var ccall = get_property_set_call (prop, ma, cexpr);
 			
 			// assignments are expressions, so return the current property value, except if we're sure that it can't be used
 			if (!(assignment.parent_node is ExpressionStatement)) {
 				var ccomma = new CCodeCommaExpression ();
 				ccomma.append_expression (ccall); // update property
-				ccomma.append_expression ((CCodeExpression) codegen.get_ccodenode (ma)); // current property value
+				ccomma.append_expression ((CCodeExpression) get_ccodenode (ma)); // current property value
 				
 				return ccomma;
 			} else {
@@ -139,7 +139,7 @@
 			ma = (MemberAccess) assignment.left;
 		}
 		if (ma.inner != null) {
-			ccall.add_argument ((CCodeExpression) codegen.get_ccodenode (ma.inner));
+			ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
 		} else {
 			ccall.add_argument (new CCodeIdentifier ("self"));
 		}
@@ -166,8 +166,8 @@
 
 			// get signal id
 			var ccomma = new CCodeCommaExpression ();
-			var temp_decl = codegen.get_temp_variable (codegen.uint_type);
-			codegen.temp_vars.insert (0, temp_decl);
+			var temp_decl = get_temp_variable (uint_type);
+			temp_vars.insert (0, 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;
@@ -176,8 +176,8 @@
 			if (signal_detail == null) {
 				parse_call.add_argument (new CCodeConstant ("NULL"));
 			} else {
-				var detail_temp_decl = codegen.get_temp_variable (codegen.gquark_type);
-				codegen.temp_vars.insert (0, detail_temp_decl);
+				var detail_temp_decl = get_temp_variable (gquark_type);
+				temp_vars.insert (0, detail_temp_decl);
 				parse_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (detail_temp_decl.name)));
 			}
 			parse_call.add_argument (new CCodeConstant ("FALSE"));
@@ -238,17 +238,17 @@
 		Iterator<Expression> indices_it = indices.iterator ();
 		indices_it.next ();
 
-		var ccontainer = (CCodeExpression) codegen.get_ccodenode (expr.container);
-		var cindex = (CCodeExpression) codegen.get_ccodenode (indices_it.get ());
+		var ccontainer = (CCodeExpression) get_ccodenode (expr.container);
+		var cindex = (CCodeExpression) get_ccodenode (indices_it.get ());
 
-		if (container_type != null && codegen.list_type != null && codegen.map_type != null &&
-		    (container_type.is_subtype_of (codegen.list_type) || container_type.is_subtype_of (codegen.map_type))) {
+		if (container_type != null && list_type != null && map_type != null &&
+		    (container_type.is_subtype_of (list_type) || container_type.is_subtype_of (map_type))) {
 			// lookup symbol in interface instead of class as implemented interface methods are not in VAPI files
 			TypeSymbol collection_iface = null;
-			if (container_type.is_subtype_of (codegen.list_type)) {
-				collection_iface = codegen.list_type;
-			} else if (container_type.is_subtype_of (codegen.map_type)) {
-				collection_iface = codegen.map_type;
+			if (container_type.is_subtype_of (list_type)) {
+				collection_iface = list_type;
+			} else if (container_type.is_subtype_of (map_type)) {
+				collection_iface = map_type;
 			}
 			var set_method = (Method) collection_iface.scope.lookup ("set");
 			Gee.List<FormalParameter> set_params = set_method.get_parameters ();
@@ -258,13 +258,13 @@
 
 			if (set_param.parameter_type.type_parameter != null) {
 				var index_type = SemanticAnalyzer.get_actual_type (expr.container.value_type, set_method, set_param.parameter_type, assignment);
-				cindex = codegen.convert_to_generic_pointer (cindex, index_type);
+				cindex = convert_to_generic_pointer (cindex, index_type);
 			}
 
 			var set_ccall = new CCodeFunctionCall (new CCodeIdentifier (set_method.get_cname ()));
 			set_ccall.add_argument (new CCodeCastExpression (ccontainer, collection_iface.get_cname () + "*"));
 			set_ccall.add_argument (cindex);
-			set_ccall.add_argument (codegen.convert_to_generic_pointer (rhs, expr.value_type));
+			set_ccall.add_argument (convert_to_generic_pointer (rhs, expr.value_type));
 
 			return set_ccall;
 		} else {
@@ -277,7 +277,7 @@
 	CCodeExpression emit_simple_assignment (Assignment assignment) {
 		CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
 
-		bool unref_old = codegen.requires_destroy (assignment.left.value_type);
+		bool unref_old = requires_destroy (assignment.left.value_type);
 		bool array = false;
 		bool instance_delegate = false;
 		if (assignment.left.value_type is ArrayType) {
@@ -290,12 +290,12 @@
 		if (unref_old || array || instance_delegate) {
 			var ccomma = new CCodeCommaExpression ();
 			
-			var temp_decl = codegen.get_temp_variable (assignment.left.value_type);
-			codegen.temp_vars.insert (0, temp_decl);
+			var temp_decl = get_temp_variable (assignment.left.value_type);
+			temp_vars.insert (0, temp_decl);
 			ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), rhs));
 			if (unref_old) {
 				/* unref old value */
-				ccomma.append_expression (codegen.get_unref_expression ((CCodeExpression) codegen.get_ccodenode (assignment.left), assignment.left.value_type, assignment.left));
+				ccomma.append_expression (get_unref_expression ((CCodeExpression) get_ccodenode (assignment.left), assignment.left.value_type, assignment.left));
 			}
 			
 			if (array) {
@@ -307,8 +307,8 @@
 				}
 			} else if (instance_delegate) {
 				var delegate_type = (DelegateType) assignment.left.value_type;
-				var lhs_delegate_target = codegen.get_delegate_target_cexpression (assignment.left);
-				var rhs_delegate_target = codegen.get_delegate_target_cexpression (assignment.right);
+				var lhs_delegate_target = get_delegate_target_cexpression (assignment.left);
+				var rhs_delegate_target = get_delegate_target_cexpression (assignment.right);
 				ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
 			}
 			
@@ -340,15 +340,15 @@
 			cop = CCodeAssignmentOperator.SHIFT_RIGHT;
 		}
 	
-		CCodeExpression codenode = new CCodeAssignment ((CCodeExpression) codegen.get_ccodenode (assignment.left), rhs, cop);
+		CCodeExpression codenode = new CCodeAssignment ((CCodeExpression) get_ccodenode (assignment.left), rhs, cop);
 
-		if (unref_old && codegen.get_ccodenode (assignment.left) is CCodeElementAccess) {
+		if (unref_old && get_ccodenode (assignment.left) is CCodeElementAccess) {
 			// ensure that index expression in element access doesn't get evaluated more than once
 			// except when it's a simple expression
-			var cea = (CCodeElementAccess) codegen.get_ccodenode (assignment.left);
+			var cea = (CCodeElementAccess) get_ccodenode (assignment.left);
 			if (!(cea.index is CCodeConstant || cea.index is CCodeIdentifier)) {
-				var index_temp_decl = codegen.get_temp_variable (codegen.int_type);
-				codegen.temp_vars.insert (0, index_temp_decl);
+				var index_temp_decl = get_temp_variable (int_type);
+				temp_vars.insert (0, index_temp_decl);
 				
 				var ccomma = new CCodeCommaExpression ();
 				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (index_temp_decl.name), cea.index));

Modified: trunk/gobject/valaccodebasemodule.vala
==============================================================================
--- trunk/gobject/valaccodebasemodule.vala	(original)
+++ trunk/gobject/valaccodebasemodule.vala	Mon Nov  3 20:50:43 2008
@@ -27,11 +27,184 @@
  * Code visitor generating C Code.
  */
 public class Vala.CCodeBaseModule : CCodeModule {
+	public CodeContext context { get; set; }
+
+	public Symbol root_symbol;
+	public Symbol current_symbol;
+	public TypeSymbol current_type_symbol;
+	public Class current_class;
+	public Method current_method;
+	public DataType current_return_type;
+	public TryStatement current_try;
+	public PropertyAccessor current_property_accessor;
+
+	public CCodeFragment header_begin;
+	public CCodeFragment header_type_declaration;
+	public CCodeFragment header_type_definition;
+	public CCodeFragment header_type_member_declaration;
+	public CCodeFragment header_constant_declaration;
+	public CCodeFragment source_begin;
+	public CCodeFragment source_include_directives;
+	public CCodeFragment source_type_declaration;
+	public CCodeFragment source_type_definition;
+	public CCodeFragment source_type_member_declaration;
+	public CCodeFragment source_constant_declaration;
+	public CCodeFragment source_signal_marshaller_declaration;
+	public CCodeFragment source_type_member_definition;
+	public CCodeFragment class_init_fragment;
+	public CCodeFragment instance_init_fragment;
+	public CCodeFragment instance_finalize_fragment;
+	public CCodeFragment source_signal_marshaller_definition;
+	public CCodeFragment module_init_fragment;
+	
+	public CCodeStruct param_spec_struct;
+	public CCodeStruct instance_struct;
+	public CCodeStruct type_struct;
+	public CCodeStruct instance_priv_struct;
+	public CCodeEnum prop_enum;
+	public CCodeEnum cenum;
+	public CCodeFunction function;
+	public CCodeBlock block;
+	
+	/* all temporary variables */
+	public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
+	/* temporary variables that own their content */
+	public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
+	/* cache to check whether a certain marshaller has been created yet */
+	public Gee.Set<string> user_marshal_set;
+	/* (constant) hash table with all predefined marshallers */
+	public Gee.Set<string> predefined_marshal_set;
+	/* (constant) hash table with all C keywords */
+	public Gee.Set<string> c_keywords;
+	
+	public int next_temp_var_id = 0;
+	private int current_try_id = 0;
+	private int next_try_id = 0;
+	private int next_array_dup_id = 0;
+	public bool in_creation_method = false;
+	private bool in_constructor = false;
+	public bool in_static_or_class_ctor = false;
+	public bool current_method_inner_error = false;
+	int next_coroutine_state = 1;
+
+	public DataType bool_type;
+	public DataType char_type;
+	public DataType uchar_type;
+	public DataType unichar_type;
+	public DataType short_type;
+	public DataType ushort_type;
+	public DataType int_type;
+	public DataType uint_type;
+	public DataType long_type;
+	public DataType ulong_type;
+	public DataType int8_type;
+	public DataType uint8_type;
+	public DataType int32_type;
+	public DataType uint32_type;
+	public DataType int64_type;
+	public DataType uint64_type;
+	public DataType string_type;
+	public DataType float_type;
+	public DataType double_type;
+	public TypeSymbol gtype_type;
+	public TypeSymbol gobject_type;
+	public ErrorType gerror_type;
+	public Class glist_type;
+	public Class gslist_type;
+	public TypeSymbol gstringbuilder_type;
+	public TypeSymbol garray_type;
+	public DataType gquark_type;
+	public Struct mutex_type;
+	public TypeSymbol type_module_type;
+	public Interface iterable_type;
+	public Interface iterator_type;
+	public Interface collection_type;
+	public Interface list_type;
+	public Interface map_type;
+	public TypeSymbol dbus_object_type;
+
+	public Method substring_method;
+
+	public bool in_plugin = false;
+	public string module_init_param_name;
+	
+	public bool string_h_needed;
+	public bool gvaluecollector_h_needed;
+	public bool gio_h_needed;
+	public bool requires_free_checked;
+	public bool requires_array_free;
+	public bool requires_array_move;
+	public bool requires_strcmp0;
+	public bool dbus_glib_h_needed;
+
+	public Set<string> wrappers;
+
 	public CCodeBaseModule (CCodeGenerator codegen, CCodeModule? next) {
 		base (codegen, next);
-	}
 
-	public override void emit (CodeContext context) {
+		predefined_marshal_set = new HashSet<string> (str_hash, str_equal);
+		predefined_marshal_set.add ("VOID:VOID");
+		predefined_marshal_set.add ("VOID:BOOLEAN");
+		predefined_marshal_set.add ("VOID:CHAR");
+		predefined_marshal_set.add ("VOID:UCHAR");
+		predefined_marshal_set.add ("VOID:INT");
+		predefined_marshal_set.add ("VOID:UINT");
+		predefined_marshal_set.add ("VOID:LONG");
+		predefined_marshal_set.add ("VOID:ULONG");
+		predefined_marshal_set.add ("VOID:ENUM");
+		predefined_marshal_set.add ("VOID:FLAGS");
+		predefined_marshal_set.add ("VOID:FLOAT");
+		predefined_marshal_set.add ("VOID:DOUBLE");
+		predefined_marshal_set.add ("VOID:STRING");
+		predefined_marshal_set.add ("VOID:POINTER");
+		predefined_marshal_set.add ("VOID:OBJECT");
+		predefined_marshal_set.add ("STRING:OBJECT,POINTER");
+		predefined_marshal_set.add ("VOID:UINT,POINTER");
+		predefined_marshal_set.add ("BOOLEAN:FLAGS");
+
+		c_keywords = new HashSet<string> (str_hash, str_equal);
+
+		// C99 keywords
+		c_keywords.add ("_Bool");
+		c_keywords.add ("_Complex");
+		c_keywords.add ("_Imaginary");
+		c_keywords.add ("auto");
+		c_keywords.add ("break");
+		c_keywords.add ("case");
+		c_keywords.add ("char");
+		c_keywords.add ("const");
+		c_keywords.add ("continue");
+		c_keywords.add ("default");
+		c_keywords.add ("do");
+		c_keywords.add ("double");
+		c_keywords.add ("else");
+		c_keywords.add ("enum");
+		c_keywords.add ("extern");
+		c_keywords.add ("float");
+		c_keywords.add ("for");
+		c_keywords.add ("goto");
+		c_keywords.add ("if");
+		c_keywords.add ("inline");
+		c_keywords.add ("int");
+		c_keywords.add ("long");
+		c_keywords.add ("register");
+		c_keywords.add ("restrict");
+		c_keywords.add ("return");
+		c_keywords.add ("short");
+		c_keywords.add ("signed");
+		c_keywords.add ("sizeof");
+		c_keywords.add ("static");
+		c_keywords.add ("struct");
+		c_keywords.add ("switch");
+		c_keywords.add ("typedef");
+		c_keywords.add ("union");
+		c_keywords.add ("unsigned");
+		c_keywords.add ("void");
+		c_keywords.add ("volatile");
+		c_keywords.add ("while");
+
+		// MSVC keywords
+		c_keywords.add ("cdecl");
 	}
 
 	public override CCodeIdentifier get_value_setter_function (DataType type_reference) {
@@ -73,7 +246,7 @@
 	}
 
 	private CCodeIncludeDirective get_internal_include (string filename) {
-		return new CCodeIncludeDirective (filename, codegen.context.library == null);
+		return new CCodeIncludeDirective (filename, context.library == null);
 	}
 
 	public virtual void append_vala_array_free () {
@@ -87,7 +260,7 @@
 		fun.modifiers = CCodeModifiers.STATIC;
 		fun.add_parameter (new CCodeFormalParameter ("str1", "const char *"));
 		fun.add_parameter (new CCodeFormalParameter ("str2", "const char *"));
-		codegen.source_type_member_declaration.append (fun.copy ());
+		source_type_member_declaration.append (fun.copy ());
 
 		// (str1 != str2)
 		var cineq = new CCodeParenthesizedExpression (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("str1"), new CCodeIdentifier ("str2")));
@@ -115,46 +288,46 @@
 		// return strcmp (str1, str2);
 		fun.block.add_statement (new CCodeReturnStatement (ccall));
 
-		codegen.source_type_member_definition.append (fun);
+		source_type_member_definition.append (fun);
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
-		codegen.header_begin = new CCodeFragment ();
-		codegen.header_type_declaration = new CCodeFragment ();
-		codegen.header_type_definition = new CCodeFragment ();
-		codegen.header_type_member_declaration = new CCodeFragment ();
-		codegen.header_constant_declaration = new CCodeFragment ();
-		codegen.source_begin = new CCodeFragment ();
-		codegen.source_include_directives = new CCodeFragment ();
-		codegen.source_type_declaration = new CCodeFragment ();
-		codegen.source_type_definition = new CCodeFragment ();
-		codegen.source_type_member_declaration = new CCodeFragment ();
-		codegen.source_constant_declaration = new CCodeFragment ();
-		codegen.source_type_member_definition = new CCodeFragment ();
-		codegen.source_signal_marshaller_definition = new CCodeFragment ();
-		codegen.source_signal_marshaller_declaration = new CCodeFragment ();
-		
-		codegen.user_marshal_set = new HashSet<string> (str_hash, str_equal);
-		
-		codegen.next_temp_var_id = 0;
-		
-		codegen.string_h_needed = false;
-		codegen.gvaluecollector_h_needed = false;
-		codegen.gio_h_needed = false;
-		codegen.dbus_glib_h_needed = false;
-		codegen.requires_free_checked = false;
-		codegen.requires_array_free = false;
-		codegen.requires_array_move = false;
-		codegen.requires_strcmp0 = false;
-
-		codegen.wrappers = new HashSet<string> (str_hash, str_equal);
-
-		codegen.header_begin.append (new CCodeIncludeDirective ("glib.h"));
-		codegen.header_begin.append (new CCodeIncludeDirective ("glib-object.h"));
-		if (codegen.context.basedir != null || codegen.context.library != null) {
-			codegen.source_include_directives.append (new CCodeIncludeDirective (source_file.get_cinclude_filename ()));
+		header_begin = new CCodeFragment ();
+		header_type_declaration = new CCodeFragment ();
+		header_type_definition = new CCodeFragment ();
+		header_type_member_declaration = new CCodeFragment ();
+		header_constant_declaration = new CCodeFragment ();
+		source_begin = new CCodeFragment ();
+		source_include_directives = new CCodeFragment ();
+		source_type_declaration = new CCodeFragment ();
+		source_type_definition = new CCodeFragment ();
+		source_type_member_declaration = new CCodeFragment ();
+		source_constant_declaration = new CCodeFragment ();
+		source_type_member_definition = new CCodeFragment ();
+		source_signal_marshaller_definition = new CCodeFragment ();
+		source_signal_marshaller_declaration = new CCodeFragment ();
+		
+		user_marshal_set = new HashSet<string> (str_hash, str_equal);
+		
+		next_temp_var_id = 0;
+		
+		string_h_needed = false;
+		gvaluecollector_h_needed = false;
+		gio_h_needed = false;
+		dbus_glib_h_needed = false;
+		requires_free_checked = false;
+		requires_array_free = false;
+		requires_array_move = false;
+		requires_strcmp0 = false;
+
+		wrappers = new HashSet<string> (str_hash, str_equal);
+
+		header_begin.append (new CCodeIncludeDirective ("glib.h"));
+		header_begin.append (new CCodeIncludeDirective ("glib-object.h"));
+		if (context.basedir != null || context.library != null) {
+			source_include_directives.append (new CCodeIncludeDirective (source_file.get_cinclude_filename ()));
 		} else {
-			codegen.source_include_directives.append (new CCodeIncludeDirective (source_file.get_cinclude_filename (), true));
+			source_include_directives.append (new CCodeIncludeDirective (source_file.get_cinclude_filename (), true));
 		}
 		
 		Gee.List<string> used_includes = new ArrayList<string> (str_equal);
@@ -164,25 +337,25 @@
 		
 		foreach (string filename in source_file.get_header_external_includes ()) {
 			if (!used_includes.contains (filename)) {
-				codegen.header_begin.append (new CCodeIncludeDirective (filename));
+				header_begin.append (new CCodeIncludeDirective (filename));
 				used_includes.add (filename);
 			}
 		}
 		foreach (string filename in source_file.get_header_internal_includes ()) {
 			if (!used_includes.contains (filename)) {
-				codegen.header_begin.append (get_internal_include (filename));
+				header_begin.append (get_internal_include (filename));
 				used_includes.add (filename);
 			}
 		}
 		foreach (string filename in source_file.get_source_external_includes ()) {
 			if (!used_includes.contains (filename)) {
-				codegen.source_include_directives.append (new CCodeIncludeDirective (filename));
+				source_include_directives.append (new CCodeIncludeDirective (filename));
 				used_includes.add (filename);
 			}
 		}
 		foreach (string filename in source_file.get_source_internal_includes ()) {
 			if (!used_includes.contains (filename)) {
-				codegen.source_include_directives.append (get_internal_include (filename));
+				source_include_directives.append (get_internal_include (filename));
 				used_includes.add (filename);
 			}
 		}
@@ -196,15 +369,15 @@
 				foreach (CodeNode node in cycle_file.get_nodes ()) {
 					if (node is Struct) {
 						var st = (Struct) node;
-						codegen.header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ())));
+						header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (st.get_cname ()), new CCodeVariableDeclarator (st.get_cname ())));
 					} else if (node is Class) {
 						var cl = (Class) node;
-						codegen.header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
-						codegen.header_type_declaration.append (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
+						header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ())));
+						header_type_declaration.append (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
 					} else if (node is Interface) {
 						var iface = (Interface) node;
-						codegen.header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
-						codegen.header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_type_cname ()), new CCodeVariableDeclarator (iface.get_type_cname ())));
+						header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
+						header_type_declaration.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_type_cname ()), new CCodeVariableDeclarator (iface.get_type_cname ())));
 					}
 				}
 			}
@@ -219,33 +392,33 @@
 		var header_define = get_define_for_filename (source_file.get_cinclude_filename ());
 		
 		/* generate hardcoded "well-known" macros */
-		if (codegen.requires_free_checked) {
-			codegen.source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
+		if (requires_free_checked) {
+			source_begin.append (new CCodeMacroReplacement ("VALA_FREE_CHECKED(o,f)", "((o) == NULL ? NULL : ((o) = (f (o), NULL)))"));
 		}
-		if (codegen.requires_array_free) {
+		if (requires_array_free) {
 			append_vala_array_free ();
 		}
-		if (codegen.requires_array_move) {
+		if (requires_array_move) {
 			append_vala_array_move ();
 		}
-		if (codegen.requires_strcmp0) {
+		if (requires_strcmp0) {
 			append_vala_strcmp0 ();
 		}
 		
-		if (codegen.string_h_needed) {
-			codegen.source_include_directives.append (new CCodeIncludeDirective ("string.h"));
+		if (string_h_needed) {
+			source_include_directives.append (new CCodeIncludeDirective ("string.h"));
 		}
 
-		if (codegen.gvaluecollector_h_needed) {
-			codegen.source_include_directives.append (new CCodeIncludeDirective ("gobject/gvaluecollector.h"));
+		if (gvaluecollector_h_needed) {
+			source_include_directives.append (new CCodeIncludeDirective ("gobject/gvaluecollector.h"));
 		}
 
-		if (codegen.gio_h_needed) {
-			codegen.header_begin.append (new CCodeIncludeDirective ("gio/gio.h"));
+		if (gio_h_needed) {
+			header_begin.append (new CCodeIncludeDirective ("gio/gio.h"));
 		}
 
-		if (codegen.dbus_glib_h_needed) {
-			codegen.source_include_directives.append (new CCodeIncludeDirective ("dbus/dbus-glib.h"));
+		if (dbus_glib_h_needed) {
+			source_include_directives.append (new CCodeIncludeDirective ("dbus/dbus-glib.h"));
 		}
 
 		CCodeComment comment = null;
@@ -264,18 +437,18 @@
 		writer.write_newline ();
 		var once = new CCodeOnceSection (header_define);
 		once.append (new CCodeNewline ());
-		once.append (codegen.header_begin);
+		once.append (header_begin);
 		once.append (new CCodeNewline ());
 		once.append (new CCodeIdentifier ("G_BEGIN_DECLS"));
 		once.append (new CCodeNewline ());
 		once.append (new CCodeNewline ());
-		once.append (codegen.header_type_declaration);
+		once.append (header_type_declaration);
 		once.append (new CCodeNewline ());
-		once.append (codegen.header_type_definition);
+		once.append (header_type_definition);
 		once.append (new CCodeNewline ());
-		once.append (codegen.header_type_member_declaration);
+		once.append (header_type_member_declaration);
 		once.append (new CCodeNewline ());
-		once.append (codegen.header_constant_declaration);
+		once.append (header_constant_declaration);
 		once.append (new CCodeNewline ());
 		once.append (new CCodeIdentifier ("G_END_DECLS"));
 		once.append (new CCodeNewline ());
@@ -288,47 +461,47 @@
 			Report.error (null, "unable to open `%s' for writing".printf (writer.filename));
 			return;
 		}
-		writer.line_directives = codegen.context.debug;
+		writer.line_directives = context.debug;
 		if (comment != null) {
 			comment.write (writer);
 		}
-		codegen.source_begin.write (writer);
+		source_begin.write (writer);
 		writer.write_newline ();
-		codegen.source_include_directives.write (writer);
+		source_include_directives.write (writer);
 		writer.write_newline ();
-		codegen.source_type_declaration.write_combined (writer);
+		source_type_declaration.write_combined (writer);
 		writer.write_newline ();
-		codegen.source_type_definition.write_combined (writer);
+		source_type_definition.write_combined (writer);
 		writer.write_newline ();
-		codegen.source_type_member_declaration.write_declaration (writer);
+		source_type_member_declaration.write_declaration (writer);
 		writer.write_newline ();
-		codegen.source_type_member_declaration.write (writer);
+		source_type_member_declaration.write (writer);
 		writer.write_newline ();
-		codegen.source_constant_declaration.write (writer);
+		source_constant_declaration.write (writer);
 		writer.write_newline ();
-		codegen.source_signal_marshaller_declaration.write_declaration (writer);
-		codegen.source_signal_marshaller_declaration.write (writer);
+		source_signal_marshaller_declaration.write_declaration (writer);
+		source_signal_marshaller_declaration.write (writer);
 		writer.write_newline ();
-		codegen.source_type_member_definition.write (writer);
+		source_type_member_definition.write (writer);
 		writer.write_newline ();
-		codegen.source_signal_marshaller_definition.write (writer);
+		source_signal_marshaller_definition.write (writer);
 		writer.write_newline ();
 		writer.close ();
 
-		codegen.header_begin = null;
-		codegen.header_type_declaration = null;
-		codegen.header_type_definition = null;
-		codegen.header_type_member_declaration = null;
-		codegen.header_constant_declaration = null;
-		codegen.source_begin = null;
-		codegen.source_include_directives = null;
-		codegen.source_type_declaration = null;
-		codegen.source_type_definition = null;
-		codegen.source_type_member_declaration = null;
-		codegen.source_constant_declaration = null;
-		codegen.source_type_member_definition = null;
-		codegen.source_signal_marshaller_definition = null;
-		codegen.source_signal_marshaller_declaration = null;
+		header_begin = null;
+		header_type_declaration = null;
+		header_type_definition = null;
+		header_type_member_declaration = null;
+		header_constant_declaration = null;
+		source_begin = null;
+		source_include_directives = null;
+		source_type_declaration = null;
+		source_type_definition = null;
+		source_type_member_declaration = null;
+		source_constant_declaration = null;
+		source_type_member_definition = null;
+		source_signal_marshaller_definition = null;
+		source_signal_marshaller_declaration = null;
 	}
 	
 	private static string get_define_for_filename (string filename) {
@@ -350,4 +523,4014 @@
 		
 		return define.str;
 	}
+
+	public override void emit (CodeContext context) {
+		this.context = context;
+	
+		context.find_header_cycles ();
+
+		root_symbol = context.root;
+
+		bool_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("bool"));
+		char_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("char"));
+		uchar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uchar"));
+		unichar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("unichar"));
+		short_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("short"));
+		ushort_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ushort"));
+		int_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int"));
+		uint_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint"));
+		long_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("long"));
+		ulong_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ulong"));
+		int8_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int8"));
+		uint8_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint8"));
+		int32_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int32"));
+		uint32_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint32"));
+		int64_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int64"));
+		uint64_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint64"));
+		float_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("float"));
+		double_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("double"));
+		string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
+		substring_method = (Method) string_type.data_type.scope.lookup ("substring");
+
+		var glib_ns = root_symbol.scope.lookup ("GLib");
+
+		gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
+		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
+		gerror_type = new ErrorType (null, null);
+		glist_type = (Class) glib_ns.scope.lookup ("List");
+		gslist_type = (Class) glib_ns.scope.lookup ("SList");
+		gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
+		garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
+
+		gquark_type = new ValueType ((TypeSymbol) glib_ns.scope.lookup ("Quark"));
+		mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
+		
+		type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
+
+		if (context.module_init_method != null) {
+			module_init_fragment = new CCodeFragment ();
+			foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) {
+				if (parameter.parameter_type.data_type == type_module_type) {
+					in_plugin = true;
+					module_init_param_name = parameter.name;
+					break;
+				}
+			}
+		}
+
+		var gee_ns = root_symbol.scope.lookup ("Gee");
+		if (gee_ns != null) {
+			iterable_type = (Interface) gee_ns.scope.lookup ("Iterable");
+			iterator_type = (Interface) gee_ns.scope.lookup ("Iterator");
+			collection_type = (Interface) gee_ns.scope.lookup ("Collection");
+			list_type = (Interface) gee_ns.scope.lookup ("List");
+			map_type = (Interface) gee_ns.scope.lookup ("Map");
+		}
+
+		var dbus_ns = root_symbol.scope.lookup ("DBus");
+		if (dbus_ns != null) {
+			dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
+		}
+	
+		/* we're only interested in non-pkg source files */
+		var source_files = context.get_source_files ();
+		foreach (SourceFile file in source_files) {
+			if (!file.external_package) {
+				file.accept (codegen);
+			}
+		}
+	}
+
+	public override void visit_enum (Enum en) {
+		cenum = new CCodeEnum (en.get_cname ());
+
+		CCodeFragment decl_frag;
+		CCodeFragment def_frag;
+		if (en.access != SymbolAccessibility.PRIVATE) {
+			decl_frag = header_type_declaration;
+			def_frag = header_type_definition;
+		} else {
+			decl_frag = source_type_declaration;
+			def_frag = source_type_definition;
+		}
+		
+		if (en.source_reference.comment != null) {
+			def_frag.append (new CCodeComment (en.source_reference.comment));
+		}
+
+		def_frag.append (cenum);
+		def_frag.append (new CCodeNewline ());
+
+		en.accept_children (codegen);
+
+		if (!en.has_type_id) {
+			return;
+		}
+
+		decl_frag.append (new CCodeNewline ());
+
+		var macro = "(%s_get_type ())".printf (en.get_lower_case_cname (null));
+		decl_frag.append (new CCodeMacroReplacement (en.get_type_id (), macro));
+
+		var clist = new CCodeInitializerList (); /* or during visit time? */
+		CCodeInitializerList clist_ev = null;
+		foreach (EnumValue ev in en.get_values ()) {
+			clist_ev = new CCodeInitializerList ();
+			clist_ev.append (new CCodeConstant (ev.get_cname ()));
+			clist_ev.append (new CCodeIdentifier ("\"%s\"".printf (ev.get_cname ())));
+			clist_ev.append (ev.get_canonical_cconstant ());
+			clist.append (clist_ev);
+		}
+
+		clist_ev = new CCodeInitializerList ();
+		clist_ev.append (new CCodeConstant ("0"));
+		clist_ev.append (new CCodeConstant ("NULL"));
+		clist_ev.append (new CCodeConstant ("NULL"));
+		clist.append (clist_ev);
+
+		var enum_decl = new CCodeVariableDeclarator.with_initializer ("values[]", clist);
+
+		CCodeDeclaration cdecl = null;
+		if (en.is_flags) {
+			cdecl = new CCodeDeclaration ("const GFlagsValue");
+		} else {
+			cdecl = new CCodeDeclaration ("const GEnumValue");
+		}
+
+		cdecl.add_declarator (enum_decl);
+		cdecl.modifiers = CCodeModifiers.STATIC;
+
+		var type_init = new CCodeBlock ();
+
+		type_init.add_statement (cdecl);
+
+		var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null));
+		var regfun = new CCodeFunction (fun_name, "GType");
+		var regblock = new CCodeBlock ();
+
+		cdecl = new CCodeDeclaration ("GType");
+		string type_id_name = "%s_type_id".printf (en.get_lower_case_cname (null));
+		cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (type_id_name, new CCodeConstant ("0")));
+		cdecl.modifiers = CCodeModifiers.STATIC;
+		regblock.add_statement (cdecl);
+
+		CCodeFunctionCall reg_call;
+		if (en.is_flags) {
+			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static"));
+		} else {
+			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
+		}
+
+		reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (en.get_cname())));
+		reg_call.add_argument (new CCodeIdentifier ("values"));
+
+		type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
+
+		var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY"));
+		cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0")));
+		var cif = new CCodeIfStatement (cond, type_init);
+		regblock.add_statement (cif);
+
+		regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name)));
+
+		if (en.access != SymbolAccessibility.PRIVATE) {
+			header_type_member_declaration.append (regfun.copy ());
+		} else {
+			source_type_member_declaration.append (regfun.copy ());
+		}
+		regfun.block = regblock;
+
+		source_type_member_definition.append (new CCodeNewline ());
+		source_type_member_definition.append (regfun);
+	}
+
+	public override void visit_enum_value (EnumValue ev) {
+		if (ev.value == null) {
+			cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
+		} else {
+			ev.value.accept (codegen);
+			cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
+		}
+	}
+
+	public override void visit_error_domain (ErrorDomain edomain) {
+		cenum = new CCodeEnum (edomain.get_cname ());
+
+		if (edomain.source_reference.comment != null) {
+			header_type_definition.append (new CCodeComment (edomain.source_reference.comment));
+		}
+		header_type_definition.append (cenum);
+
+		edomain.accept_children (codegen);
+
+		string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
+
+		var error_domain_define = new CCodeMacroReplacement (edomain.get_upper_case_cname (), quark_fun_name + " ()");
+		header_type_definition.append (error_domain_define);
+
+		var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
+		var cquark_block = new CCodeBlock ();
+
+		var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
+		cquark_call.add_argument (new CCodeConstant ("\"" + edomain.get_lower_case_cname () + "-quark\""));
+
+		cquark_block.add_statement (new CCodeReturnStatement (cquark_call));
+
+		header_type_member_declaration.append (cquark_fun.copy ());
+
+		cquark_fun.block = cquark_block;
+		source_type_member_definition.append (cquark_fun);
+	}
+
+	public override void visit_error_code (ErrorCode ecode) {
+		if (ecode.value == null) {
+			cenum.add_value (new CCodeEnumValue (ecode.get_cname ()));
+		} else {
+			ecode.value.accept (codegen);
+			cenum.add_value (new CCodeEnumValue (ecode.get_cname (), (CCodeExpression) ecode.value.ccodenode));
+		}
+	}
+
+	public override void visit_delegate (Delegate d) {
+		d.accept_children (codegen);
+
+		var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
+		foreach (FormalParameter param in d.get_parameters ()) {
+			cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode);
+
+			// handle array parameters
+			if (!param.no_array_length && param.parameter_type is ArrayType) {
+				var array_type = (ArrayType) param.parameter_type;
+				
+				var length_ctype = "int";
+				if (param.direction != ParameterDirection.IN) {
+					length_ctype = "int*";
+				}
+				
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
+					cfundecl.add_parameter (cparam);
+				}
+			}
+		}
+		if (d.has_target) {
+			var cparam = new CCodeFormalParameter ("user_data", "void*");
+			cfundecl.add_parameter (cparam);
+		}
+
+		var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
+
+		if (!d.is_internal_symbol ()) {
+			header_type_declaration.append (ctypedef);
+		} else {
+			source_type_declaration.append (ctypedef);
+		}
+	}
+	
+	public override void visit_member (Member m) {
+		/* stuff meant for all lockable members */
+		if (m is Lockable && ((Lockable)m).get_lock_used ()) {
+			CCodeExpression l = new CCodeIdentifier ("self");
+			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m));	
+
+			instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (m));
+
+			var initf = new CCodeFunctionCall (
+				new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
+
+			initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));		
+
+			instance_init_fragment.append (new CCodeExpressionStatement (initf));
+		
+			requires_free_checked = true;
+
+
+			var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
+
+			fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
+
+			if (instance_finalize_fragment != null) {
+				instance_finalize_fragment.append (new CCodeExpressionStatement (fc));
+			}
+		}
+	}
+
+	public override void visit_constant (Constant c) {
+		c.accept_children (codegen);
+
+		if (!(c.type_reference is ArrayType)) {
+			var cdefine = new CCodeMacroReplacement.with_expression (c.get_cname (), (CCodeExpression) c.initializer.ccodenode);
+			if (!c.is_internal_symbol ()) {
+				header_type_member_declaration.append (cdefine);
+			} else {
+				source_type_member_declaration.append (cdefine);
+			}
+		} else {
+			var cdecl = new CCodeDeclaration (c.type_reference.get_const_cname ());
+			var arr = "";
+			if (c.type_reference is ArrayType) {
+				arr = "[]";
+			}
+			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode));
+			cdecl.modifiers = CCodeModifiers.STATIC;
+		
+			if (!c.is_internal_symbol ()) {
+				header_constant_declaration.append (cdecl);
+			} else {
+				source_constant_declaration.append (cdecl);
+			}
+		}
+	}
+
+	public override void visit_field (Field f) {
+		f.accept_children (codegen);
+
+		var cl = f.parent_symbol as Class;
+		bool is_gtypeinstance = (cl != null && !cl.is_compact);
+
+		CCodeExpression lhs = null;
+		CCodeStruct st = null;
+		
+		string field_ctype = f.field_type.get_cname ();
+		if (f.is_volatile) {
+			field_ctype = "volatile " + field_ctype;
+		}
+
+		if (f.access != SymbolAccessibility.PRIVATE) {
+			if (f.binding == MemberBinding.INSTANCE) {
+				st = instance_struct;
+
+				lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
+			} else if (f.binding == MemberBinding.CLASS) {
+				st = type_struct;
+			} else {
+				var cdecl = new CCodeDeclaration (field_ctype);
+				cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname ()));
+				cdecl.modifiers = CCodeModifiers.EXTERN;
+				header_type_member_declaration.append (cdecl);
+
+				var var_decl = new CCodeVariableDeclarator (f.get_cname ());
+				var_decl.initializer = default_value_for_type (f.field_type, true);
+
+				if (f.initializer != null) {
+					var init = (CCodeExpression) f.initializer.ccodenode;
+					if (is_constant_ccode_expression (init)) {
+						var_decl.initializer = init;
+					}
+				}
+
+				var var_def = new CCodeDeclaration (field_ctype);
+				var_def.add_declarator (var_decl);
+				var_def.modifiers = CCodeModifiers.EXTERN;
+				source_type_member_declaration.append (var_def);
+
+				lhs = new CCodeIdentifier (f.get_cname ());
+			}
+		} else if (f.access == SymbolAccessibility.PRIVATE) {
+			if (f.binding == MemberBinding.INSTANCE) {
+				if (is_gtypeinstance) {
+					st = instance_priv_struct;
+					lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ());
+				} else {
+					st = instance_struct;
+					lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
+				}
+			} else if (f.binding == MemberBinding.CLASS) {
+				st = type_struct;
+			} else {
+				var cdecl = new CCodeDeclaration (field_ctype);
+				var var_decl = new CCodeVariableDeclarator (f.get_cname ());
+				if (f.initializer != null) {
+					var init = (CCodeExpression) f.initializer.ccodenode;
+					if (is_constant_ccode_expression (init)) {
+						var_decl.initializer = init;
+					}
+				}
+				cdecl.add_declarator (var_decl);
+				cdecl.modifiers = CCodeModifiers.STATIC;
+				source_type_member_declaration.append (cdecl);
+
+				lhs = new CCodeIdentifier (f.get_cname ());
+			}
+		}
+
+		if (f.binding == MemberBinding.INSTANCE)  {
+			st.add_field (field_ctype, f.get_cname ());
+			if (f.field_type is ArrayType && !f.no_array_length) {
+				// create fields to store array dimensions
+				var array_type = (ArrayType) f.field_type;
+				
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var len_type = int_type.copy ();
+
+					st.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+				}
+			} else if (f.field_type is DelegateType) {
+				var delegate_type = (DelegateType) f.field_type;
+				if (delegate_type.delegate_symbol.has_target) {
+					// create field to store delegate target
+					st.add_field ("gpointer", get_delegate_target_cname (f.name));
+				}
+			}
+
+			if (f.initializer != null) {
+				var rhs = (CCodeExpression) f.initializer.ccodenode;
+
+				instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+
+				if (f.field_type is ArrayType && !f.no_array_length &&
+				    f.initializer is ArrayCreationExpression) {
+					var array_type = (ArrayType) f.field_type;
+					var this_access = new MemberAccess.simple ("this");
+					this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+					this_access.ccodenode = new CCodeIdentifier ("self");
+					var ma = new MemberAccess (this_access, f.name);
+					ma.symbol_reference = f;
+					
+					Gee.List<Expression> sizes = ((ArrayCreationExpression) f.initializer).get_sizes ();
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						var array_len_lhs = head.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)));
+					}
+				}
+			}
+			
+			if (requires_destroy (f.field_type) && instance_finalize_fragment != null) {
+				var this_access = new MemberAccess.simple ("this");
+				this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+				this_access.ccodenode = new CCodeIdentifier ("self");
+				var ma = new MemberAccess (this_access, f.name);
+				ma.symbol_reference = f;
+				instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.field_type, ma)));
+			}
+		} else if (f.binding == MemberBinding.CLASS)  {
+			st.add_field (field_ctype, f.get_cname ());
+		} else {
+			/* add array length fields where necessary */
+			if (f.field_type is ArrayType && !f.no_array_length) {
+				var array_type = (ArrayType) f.field_type;
+
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var len_type = int_type.copy ();
+
+					var cdecl = new CCodeDeclaration (len_type.get_cname ());
+					cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
+					if (f.access != SymbolAccessibility.PRIVATE) {
+						cdecl.modifiers = CCodeModifiers.EXTERN;
+						header_type_member_declaration.append (cdecl);
+					} else {
+						cdecl.modifiers = CCodeModifiers.STATIC;
+						source_type_member_declaration.append (cdecl);
+					}
+				}
+			} else if (f.field_type is DelegateType) {
+				var delegate_type = (DelegateType) f.field_type;
+				if (delegate_type.delegate_symbol.has_target) {
+					// create field to store delegate target
+					var cdecl = new CCodeDeclaration ("gpointer");
+					cdecl.add_declarator (new CCodeVariableDeclarator (get_delegate_target_cname  (f.get_cname ())));
+					if (f.access != SymbolAccessibility.PRIVATE) {
+						cdecl.modifiers = CCodeModifiers.EXTERN;
+						header_type_member_declaration.append (cdecl);
+					} else {
+						cdecl.modifiers = CCodeModifiers.STATIC;
+						source_type_member_declaration.append (cdecl);
+					}
+				}
+			}
+
+			if (f.initializer != null) {
+				var rhs = (CCodeExpression) f.initializer.ccodenode;
+				if (!is_constant_ccode_expression (rhs)) {
+					if (f.parent_symbol is Class) {
+						class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
+					} else {
+						f.error = true;
+						Report.error (f.source_reference, "Non-constant field initializers not supported in this context");
+						return;
+					}
+				}
+			}
+		}
+	}
+
+	private bool is_constant_ccode_expression (CCodeExpression cexpr) {
+		if (cexpr is CCodeConstant) {
+			return true;
+		} else if (cexpr is CCodeBinaryExpression) {
+			var cbinary = (CCodeBinaryExpression) cexpr;
+			return is_constant_ccode_expression (cbinary.left) && is_constant_ccode_expression (cbinary.right);
+		}
+
+		var cparenthesized = (cexpr as CCodeParenthesizedExpression);
+		return (null != cparenthesized && is_constant_ccode_expression (cparenthesized.inner));
+	}
+
+	/**
+	 * Returns whether the passed cexpr is a pure expression, i.e. an
+	 * expression without side-effects.
+	 */
+	public bool is_pure_ccode_expression (CCodeExpression cexpr) {
+		if (cexpr is CCodeConstant || cexpr is CCodeIdentifier) {
+			return true;
+		} else if (cexpr is CCodeBinaryExpression) {
+			var cbinary = (CCodeBinaryExpression) cexpr;
+			return is_pure_ccode_expression (cbinary.left) && is_constant_ccode_expression (cbinary.right);
+		} else if (cexpr is CCodeMemberAccess) {
+			var cma = (CCodeMemberAccess) cexpr;
+			return is_pure_ccode_expression (cma.inner);
+		}
+
+		var cparenthesized = (cexpr as CCodeParenthesizedExpression);
+		return (null != cparenthesized && is_pure_ccode_expression (cparenthesized.inner));
+	}
+
+	public override void visit_formal_parameter (FormalParameter p) {
+		p.accept_children (codegen);
+
+		if (!p.ellipsis) {
+			string ctypename = p.parameter_type.get_cname ();
+			string cname = p.name;
+
+			// pass non-simple structs always by reference
+			if (p.parameter_type.data_type is Struct) {
+				var st = (Struct) p.parameter_type.data_type;
+				if (!st.is_simple_type () && p.direction == ParameterDirection.IN && !p.parameter_type.nullable) {
+					ctypename += "*";
+				}
+			}
+
+			if (p.direction != ParameterDirection.IN) {
+				ctypename += "*";
+			}
+
+			p.ccodenode = new CCodeFormalParameter (cname, ctypename);
+		} else {
+			p.ccodenode = new CCodeFormalParameter.with_ellipsis ();
+		}
+	}
+
+	public override void visit_property (Property prop) {
+		int old_next_temp_var_id = next_temp_var_id;
+		next_temp_var_id = 0;
+
+		prop.accept_children (codegen);
+
+		next_temp_var_id = old_next_temp_var_id;
+
+		var cl = prop.parent_symbol as Class;
+		if (cl != null && cl.is_subtype_of (gobject_type)
+		    && prop.binding == MemberBinding.INSTANCE) {
+			// GObject property
+			// FIXME: omit real struct types for now since they
+			// cannot be expressed as gobject property yet
+			// don't register private properties
+			if (!prop.property_type.is_real_struct_type ()
+			    && prop.access != SymbolAccessibility.PRIVATE) {
+				prop_enum.add_value (new CCodeEnumValue (prop.get_upper_case_cname ()));
+			}
+		}
+	}
+
+	public override void visit_property_accessor (PropertyAccessor acc) {
+		current_property_accessor = acc;
+		current_method_inner_error = false;
+
+		var prop = (Property) acc.prop;
+
+		bool returns_real_struct = prop.property_type.is_real_struct_type ();
+
+		if (acc.readable && !returns_real_struct) {
+			current_return_type = prop.property_type;
+		} else {
+			current_return_type = new VoidType ();
+		}
+
+		acc.accept_children (codegen);
+
+		var t = (TypeSymbol) prop.parent_symbol;
+
+		ReferenceType this_type;
+		if (t is Class) {
+			this_type = new ObjectType ((Class) t);
+		} else {
+			this_type = new ObjectType ((Interface) t);
+		}
+		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
+		var value_type = prop.property_type.copy ();
+		CCodeFormalParameter cvalueparam;
+		if (returns_real_struct) {
+			cvalueparam = new CCodeFormalParameter ("value", value_type.get_cname () + "*");
+		} else {
+			cvalueparam = new CCodeFormalParameter ("value", value_type.get_cname ());
+		}
+
+		if (prop.is_abstract || prop.is_virtual) {
+			CCodeFunctionDeclarator vdeclarator;
+
+			if (acc.readable) {
+				function = new CCodeFunction (acc.get_cname (), current_return_type.get_cname ());
+
+				var vdecl = new CCodeDeclaration (current_return_type.get_cname ());
+				vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			} else {
+				function = new CCodeFunction (acc.get_cname (), "void");
+
+				var vdecl = new CCodeDeclaration ("void");
+				vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
+				vdecl.add_declarator (vdeclarator);
+				type_struct.add_declaration (vdecl);
+			}
+			function.add_parameter (cselfparam);
+			vdeclarator.add_parameter (cselfparam);
+			if (acc.writable || acc.construction || returns_real_struct) {
+				function.add_parameter (cvalueparam);
+				vdeclarator.add_parameter (cvalueparam);
+			}
+			
+			if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
+				// accessor function should be public if the property is a public symbol and it's not a construct-only setter
+				header_type_member_declaration.append (function.copy ());
+			} else {
+				function.modifiers |= CCodeModifiers.STATIC;
+				source_type_member_declaration.append (function.copy ());
+			}
+			
+			var block = new CCodeBlock ();
+			function.block = block;
+
+			CCodeFunctionCall vcast = null;
+			if (prop.parent_symbol is Interface) {
+				var iface = (Interface) prop.parent_symbol;
+
+				vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (iface.get_upper_case_cname (null))));
+			} else {
+				var cl = (Class) prop.parent_symbol;
+
+				vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
+			}
+			vcast.add_argument (new CCodeIdentifier ("self"));
+
+			if (acc.readable) {
+				var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name)));
+				vcall.add_argument (new CCodeIdentifier ("self"));
+				if (returns_real_struct) {
+					vcall.add_argument (new CCodeIdentifier ("value"));
+					block.add_statement (new CCodeExpressionStatement (vcall));
+				} else {
+					block.add_statement (new CCodeReturnStatement (vcall));
+				}
+			} else {
+				var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name)));
+				vcall.add_argument (new CCodeIdentifier ("self"));
+				vcall.add_argument (new CCodeIdentifier ("value"));
+				block.add_statement (new CCodeExpressionStatement (vcall));
+			}
+
+			source_type_member_definition.append (function);
+		}
+
+		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, prop.property_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 {
+					function.add_parameter (cselfparam);
+				}
+			}
+			if (acc.writable || acc.construction || returns_real_struct) {
+				function.add_parameter (cvalueparam);
+			}
+
+			if (!is_virtual) {
+				if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
+					// accessor function should be public if the property is a public symbol and it's not a construct-only setter
+					header_type_member_declaration.append (function.copy ());
+				} else {
+					function.modifiers |= CCodeModifiers.STATIC;
+					source_type_member_declaration.append (function.copy ());
+				}
+			}
+
+			function.block = (CCodeBlock) acc.body.ccodenode;
+
+			if (is_virtual) {
+				var cdecl = new CCodeDeclaration (this_type.get_cname ());
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", transform_expression (new CCodeIdentifier ("base"), base_type, this_type)));
+				function.block.prepend_statement (cdecl);
+			}
+
+			if (current_method_inner_error) {
+				var cdecl = new CCodeDeclaration ("GError *");
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+				function.block.prepend_statement (cdecl);
+			}
+
+			if (prop.binding == MemberBinding.INSTANCE && !is_virtual) {
+				if (returns_real_struct) {
+					function.block.prepend_statement (create_property_type_check_statement (prop, false, t, true, "self"));
+				} else {
+					function.block.prepend_statement (create_property_type_check_statement (prop, acc.readable, t, true, "self"));
+				}
+			}
+
+			// notify on property changes
+			var typesymbol = (TypeSymbol) prop.parent_symbol;
+			if (typesymbol.is_subtype_of (gobject_type) &&
+			    prop.notify &&
+			    prop.access != SymbolAccessibility.PRIVATE && // FIXME: use better means to detect gobject properties
+			    prop.binding == MemberBinding.INSTANCE &&
+			    !prop.property_type.is_real_struct_type () &&
+			    (acc.writable || acc.construction)) {
+				var notify_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_notify"));
+				notify_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
+				notify_call.add_argument (prop.get_canonical_cconstant ());
+				function.block.add_statement (new CCodeExpressionStatement (notify_call));
+			}
+
+			source_type_member_definition.append (function);
+		}
+
+		current_property_accessor = null;
+		current_return_type = null;
+	}
+
+	public override void visit_constructor (Constructor c) {
+		current_method_inner_error = false;
+		in_constructor = true;
+
+		if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
+			in_static_or_class_ctor = true;
+		}
+		c.accept_children (codegen);
+		in_static_or_class_ctor = false;
+
+		in_constructor = false;
+
+		var cl = (Class) c.parent_symbol;
+
+		if (c.binding == MemberBinding.INSTANCE) {
+			function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
+			function.modifiers = CCodeModifiers.STATIC;
+		
+			function.add_parameter (new CCodeFormalParameter ("type", "GType"));
+			function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint"));
+			function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
+		
+			source_type_member_declaration.append (function.copy ());
+
+
+			var cblock = new CCodeBlock ();
+			var cdecl = new CCodeDeclaration ("GObject *");
+			cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
+			cblock.add_statement (cdecl);
+
+			cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ()));
+			cdecl.add_declarator (new CCodeVariableDeclarator ("klass"));
+			cblock.add_statement (cdecl);
+
+			cdecl = new CCodeDeclaration ("GObjectClass *");
+			cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
+			cblock.add_statement (cdecl);
+
+
+			var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek"));
+			ccall.add_argument (new CCodeIdentifier (cl.get_type_id ()));
+			var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
+			ccast.add_argument (ccall);
+			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast)));
+
+			ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
+			ccall.add_argument (new CCodeIdentifier ("klass"));
+			ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
+			ccast.add_argument (ccall);
+			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
+
+		
+			ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
+			ccall.add_argument (new CCodeIdentifier ("type"));
+			ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
+			ccall.add_argument (new CCodeIdentifier ("construct_properties"));
+			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
+
+
+			ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
+
+			cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
+			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
+		
+			cblock.add_statement (cdecl);
+
+			if (current_method_inner_error) {
+				/* always separate error parameter and inner_error local variable
+				 * as error may be set to NULL but we're always interested in inner errors
+				 */
+				var cdecl = new CCodeDeclaration ("GError *");
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+				cblock.add_statement (cdecl);
+			}
+
+
+			cblock.add_statement (c.body.ccodenode);
+		
+			cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
+		
+			function.block = cblock;
+
+			if (c.source_reference.comment != null) {
+				source_type_member_definition.append (new CCodeComment (c.source_reference.comment));
+			}
+			source_type_member_definition.append (function);
+		} else if (c.binding == MemberBinding.CLASS) {
+			// class constructor
+
+			var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
+			base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
+			base_init.modifiers = CCodeModifiers.STATIC;
+
+			source_type_member_declaration.append (base_init.copy ());
+
+			var block = (CCodeBlock) c.body.ccodenode;
+			if (current_method_inner_error) {
+				/* always separate error parameter and inner_error local variable
+				 * as error may be set to NULL but we're always interested in inner errors
+				 */
+				var cdecl = new CCodeDeclaration ("GError *");
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+				block.prepend_statement (cdecl);
+			}
+
+			base_init.block = block;
+		
+			source_type_member_definition.append (base_init);
+		} else if (c.binding == MemberBinding.STATIC) {
+			// static class constructor
+			// add to class_init
+
+			if (current_method_inner_error) {
+				/* always separate error parameter and inner_error local variable
+				 * as error may be set to NULL but we're always interested in inner errors
+				 */
+				var cdecl = new CCodeDeclaration ("GError *");
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+				class_init_fragment.append (cdecl);
+			}
+
+			class_init_fragment.append (c.body.ccodenode);
+		} else {
+			Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
+		}
+	}
+
+	public override void visit_destructor (Destructor d) {
+		current_method_inner_error = false;
+
+		d.accept_children (codegen);
+
+		CCodeFragment cfrag = new CCodeFragment ();
+
+		if (current_method_inner_error) {
+			var cdecl = new CCodeDeclaration ("GError *");
+			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
+			cfrag.append (cdecl);
+		}
+
+		cfrag.append (d.body.ccodenode);
+
+		d.ccodenode = cfrag;
+	}
+
+	public override void visit_block (Block b) {
+		current_symbol = b;
+
+		b.accept_children (codegen);
+
+		var local_vars = b.get_local_variables ();
+		foreach (LocalVariable local in local_vars) {
+			local.active = false;
+		}
+		
+		var cblock = new CCodeBlock ();
+		
+		foreach (CodeNode stmt in b.get_statements ()) {
+			if (stmt.error) {
+				continue;
+			}
+
+			var src = stmt.source_reference;
+			if (src != null && src.comment != null) {
+				cblock.add_statement (new CCodeComment (src.comment));
+			}
+			
+			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 (LocalVariable local in local_vars) {
+			if (requires_destroy (local.variable_type)) {
+				var ma = new MemberAccess.simple (local.name);
+				ma.symbol_reference = local;
+				cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
+			}
+		}
+
+		if (b.parent_symbol is Method) {
+			var m = (Method) b.parent_symbol;
+			foreach (FormalParameter param in m.get_parameters ()) {
+				if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
+					var ma = new MemberAccess.simple (param.name);
+					ma.symbol_reference = param;
+					cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
+				}
+			}
+		}
+
+		b.ccodenode = cblock;
+
+		current_symbol = current_symbol.parent_symbol;
+	}
+
+	public override void visit_empty_statement (EmptyStatement stmt) {
+		stmt.ccodenode = new CCodeEmptyStatement ();
+	}
+
+	public override void visit_declaration_statement (DeclarationStatement stmt) {
+		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 string get_variable_cname (string name) {
+		if (c_keywords.contains (name)) {
+			return name + "_";
+		} else {
+			return name;
+		}
+	}
+
+	public override void visit_local_variable (LocalVariable local) {
+		local.accept_children (codegen);
+
+		if (local.variable_type is ArrayType) {
+			// create variables to store array dimensions
+			var array_type = (ArrayType) local.variable_type;
+			
+			for (int dim = 1; dim <= array_type.rank; dim++) {
+				var len_var = new LocalVariable (int_type.copy (), head.get_array_length_cname (local.name, dim));
+				temp_vars.insert (0, len_var);
+			}
+		} else if (local.variable_type is DelegateType) {
+			var deleg_type = (DelegateType) local.variable_type;
+			var d = deleg_type.delegate_symbol;
+			if (d.has_target) {
+				// create variable to store delegate target
+				var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (local.name));
+				temp_vars.insert (0, target_var);
+			}
+		}
+	
+		CCodeExpression rhs = null;
+		if (local.initializer != null && local.initializer.ccodenode != null) {
+			rhs = (CCodeExpression) local.initializer.ccodenode;
+
+			if (local.variable_type is ArrayType) {
+				var array_type = (ArrayType) local.variable_type;
+
+				var ccomma = new CCodeCommaExpression ();
+
+				var temp_var = get_temp_variable (local.variable_type, true, local);
+				temp_vars.insert (0, temp_var);
+				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), rhs));
+
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var lhs_array_len = new CCodeIdentifier (head.get_array_length_cname (local.name, dim));
+					var rhs_array_len = head.get_array_length_cexpression (local.initializer, dim);
+					ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
+				}
+				
+				ccomma.append_expression (new CCodeIdentifier (temp_var.name));
+				
+				rhs = ccomma;
+			} else if (local.variable_type is DelegateType) {
+				var deleg_type = (DelegateType) local.variable_type;
+				var d = deleg_type.delegate_symbol;
+				if (d.has_target) {
+					var ccomma = new CCodeCommaExpression ();
+
+					var temp_var = get_temp_variable (local.variable_type, true, local);
+					temp_vars.insert (0, temp_var);
+					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), rhs));
+
+					var lhs_delegate_target = new CCodeIdentifier (get_delegate_target_cname (local.name));
+					var rhs_delegate_target = get_delegate_target_cexpression (local.initializer);
+					ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
+				
+					ccomma.append_expression (new CCodeIdentifier (temp_var.name));
+				
+					rhs = ccomma;
+				}
+			}
+		} else if (local.variable_type.is_reference_type_or_type_parameter ()) {
+			rhs = new CCodeConstant ("NULL");
+
+			if (local.variable_type is ArrayType) {
+				// initialize array length variables
+				var array_type = (ArrayType) local.variable_type;
+
+				var ccomma = new CCodeCommaExpression ();
+
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (head.get_array_length_cname (local.name, dim)), new CCodeConstant ("0")));
+				}
+
+				ccomma.append_expression (rhs);
+
+				rhs = ccomma;
+			}
+		}
+			
+		var cvar = new CCodeVariableDeclarator.with_initializer (get_variable_cname (local.name), rhs);
+
+		var cfrag = new CCodeFragment ();
+		var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
+		cdecl.add_declarator (cvar);
+		cfrag.append (cdecl);
+
+		if (local.initializer != null && local.initializer.tree_can_fail) {
+			head.add_simple_check (local.initializer, cfrag);
+		}
+
+		/* try to initialize uninitialized variables */
+		if (cvar.initializer == null) {
+			cvar.initializer = default_value_for_type (local.variable_type, true);
+		}
+
+		local.ccodenode = cfrag;
+
+		local.active = true;
+	}
+
+	public override void visit_initializer_list (InitializerList list) {
+		list.accept_children (codegen);
+
+		if (list.target_type.data_type is Struct) {
+			/* initializer is used as struct initializer */
+			var st = (Struct) list.target_type.data_type;
+
+			var clist = new CCodeInitializerList ();
+
+			var field_it = st.get_fields ().iterator ();
+			foreach (Expression expr in list.get_initializers ()) {
+				Field field = null;
+				while (field == null) {
+					field_it.next ();
+					field = field_it.get ();
+					if (field.binding != MemberBinding.INSTANCE) {
+						// we only initialize instance fields
+						field = null;
+					}
+				}
+
+				var cexpr = (CCodeExpression) expr.ccodenode;
+
+				string ctype = field.get_ctype ();
+				if (ctype != null) {
+					cexpr = new CCodeCastExpression (cexpr, ctype);
+				}
+
+				clist.append (cexpr);
+			}
+
+			list.ccodenode = clist;
+		} else {
+			var clist = new CCodeInitializerList ();
+			foreach (Expression expr in list.get_initializers ()) {
+				clist.append ((CCodeExpression) expr.ccodenode);
+			}
+			list.ccodenode = clist;
+		}
+	}
+
+	public LocalVariable get_temp_variable (DataType type, bool value_owned = true, CodeNode? node_reference = null) {
+		var var_type = type.copy ();
+		var_type.value_owned = value_owned;
+		var local = new LocalVariable (var_type, "_tmp%d".printf (next_temp_var_id));
+
+		if (node_reference != null) {
+			local.source_reference = node_reference.source_reference;
+		}
+
+		next_temp_var_id++;
+		
+		return local;
+	}
+
+	private CCodeExpression get_type_id_expression (DataType type) {
+		if (type.data_type != null) {
+			return new CCodeIdentifier (type.data_type.get_type_id ());
+		} else if (type.type_parameter != null) {
+			string var_name = "%s_type".printf (type.type_parameter.name.down ());
+			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), var_name);
+		} else {
+			return new CCodeIdentifier ("G_TYPE_NONE");
+		}
+	}
+
+	public CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
+		var cl = type.data_type as Class;
+		if (type is ErrorType) {
+			return new CCodeIdentifier ("g_error_copy");
+		} else if (type.data_type != null) {
+			string dup_function;
+			if (type.data_type.is_reference_counting ()) {
+				dup_function = type.data_type.get_ref_function ();
+				if (type.data_type is Interface && dup_function == null) {
+					Report.error (source_reference, "missing class prerequisite for interface `%s'".printf (type.data_type.get_full_name ()));
+					return null;
+				}
+			} else if (cl != null && cl.is_immutable) {
+				// allow duplicates of immutable instances as for example strings
+				dup_function = type.data_type.get_dup_function ();
+			} else if (type is ValueType) {
+				if (type.nullable) {
+					dup_function = generate_struct_dup_wrapper ((ValueType) type);
+				} else {
+					dup_function = "";
+				}
+			} else {
+				// duplicating non-reference counted objects may cause side-effects (and performance issues)
+				Report.error (source_reference, "duplicating %s instance, use weak variable or explicitly invoke copy method".printf (type.data_type.name));
+				return null;
+			}
+
+			return new CCodeIdentifier (dup_function);
+		} else if (type.type_parameter != null && current_type_symbol is Class) {
+			string func_name = "%s_dup_func".printf (type.type_parameter.name.down ());
+			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+		} else if (type is ArrayType) {
+			return new CCodeIdentifier (generate_array_dup_wrapper ((ArrayType) type));
+		} else if (type is PointerType) {
+			var pointer_type = (PointerType) type;
+			return get_dup_func_expression (pointer_type.base_type, source_reference);
+		} else {
+			return new CCodeConstant ("NULL");
+		}
+	}
+
+	string generate_array_dup_wrapper (ArrayType array_type) {
+		string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
+
+		if (!add_wrapper (dup_func)) {
+			// wrapper already defined
+			return dup_func;
+		}
+
+		// declaration
+
+		var function = new CCodeFunction (dup_func, array_type.get_cname ());
+		function.modifiers = CCodeModifiers.STATIC;
+
+		function.add_parameter (new CCodeFormalParameter ("self", array_type.get_cname ()));
+		// total length over all dimensions
+		function.add_parameter (new CCodeFormalParameter ("length", "int"));
+
+		// definition
+
+		var block = new CCodeBlock ();
+
+		if (requires_copy (array_type.element_type)) {
+			var old_temp_vars = temp_vars;
+
+			var cdecl = new CCodeDeclaration (array_type.get_cname ());
+			var cvardecl = new CCodeVariableDeclarator ("result");
+			cdecl.add_declarator (cvardecl);
+			var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
+			gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+			gnew.add_argument (new CCodeIdentifier ("length"));
+			cvardecl.initializer = gnew;
+			block.add_statement (cdecl);
+
+			var idx_decl = new CCodeDeclaration ("int");
+			idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
+			block.add_statement (idx_decl);
+
+			var loop_body = new CCodeBlock ();
+			loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
+
+			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);
+
+			block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
+
+			var cfrag = new CCodeFragment ();
+			append_temp_decl (cfrag, temp_vars);
+			block.add_statement (cfrag);
+			temp_vars = old_temp_vars;
+		} else {
+			var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+			dup_call.add_argument (new CCodeIdentifier ("self"));
+
+			var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+			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));
+		}
+
+		// append to file
+
+		source_type_member_declaration.append (function.copy ());
+
+		function.block = block;
+		source_type_member_definition.append (function);
+
+		return dup_func;
+	}
+
+	private string generate_struct_dup_wrapper (ValueType value_type) {
+		string dup_func = "_%sdup".printf (value_type.type_symbol.get_lower_case_cprefix ());
+
+		if (!add_wrapper (dup_func)) {
+			// wrapper already defined
+			return dup_func;
+		}
+
+		// declaration
+
+		var function = new CCodeFunction (dup_func, value_type.get_cname ());
+		function.modifiers = CCodeModifiers.STATIC;
+
+		function.add_parameter (new CCodeFormalParameter ("self", value_type.get_cname ()));
+
+		// definition
+
+		var block = new CCodeBlock ();
+
+		var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
+		dup_call.add_argument (new CCodeIdentifier ("self"));
+
+		var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+		sizeof_call.add_argument (new CCodeIdentifier (value_type.type_symbol.get_cname ()));
+		dup_call.add_argument (sizeof_call);
+
+		block.add_statement (new CCodeReturnStatement (dup_call));
+
+		// append to file
+
+		source_type_member_declaration.append (function.copy ());
+
+		function.block = block;
+		source_type_member_definition.append (function);
+
+		return dup_func;
+	}
+
+	public CCodeExpression? get_destroy_func_expression (DataType type) {
+		if (type.data_type == glist_type || type.data_type == gslist_type) {
+			// create wrapper function to free list elements if necessary
+
+			bool elements_require_free = false;
+			CCodeExpression element_destroy_func_expression = null;
+
+			foreach (DataType type_arg in type.get_type_arguments ()) {
+				elements_require_free = requires_destroy (type_arg);
+				if (elements_require_free) {
+					element_destroy_func_expression = get_destroy_func_expression (type_arg);
+				}
+			}
+			
+			if (elements_require_free && element_destroy_func_expression is CCodeIdentifier) {
+				return new CCodeIdentifier (generate_glist_free_wrapper (type, (CCodeIdentifier) element_destroy_func_expression));
+			} else {
+				return new CCodeIdentifier (type.data_type.get_free_function ());
+			}
+		} else if (type is ErrorType) {
+			return new CCodeIdentifier ("g_error_free");
+		} else if (type.data_type != null) {
+			string unref_function;
+			if (type is ReferenceType) {
+				if (type.data_type.is_reference_counting ()) {
+					unref_function = type.data_type.get_unref_function ();
+					if (type.data_type is Interface && unref_function == null) {
+						Report.error (type.source_reference, "missing class prerequisite for interface `%s'".printf (type.data_type.get_full_name ()));
+						return null;
+					}
+				} else {
+					unref_function = type.data_type.get_free_function ();
+				}
+			} else {
+				if (type.nullable) {
+					unref_function = type.data_type.get_free_function ();
+					if (unref_function == null) {
+						unref_function = "g_free";
+					}
+				} else {
+					var st = (Struct) type.data_type;
+					unref_function = st.get_destroy_function ();
+				}
+			}
+			if (unref_function == null) {
+				return new CCodeConstant ("NULL");
+			}
+			return new CCodeIdentifier (unref_function);
+		} else if (type.type_parameter != null && current_type_symbol is Class) {
+			string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ());
+			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+		} else if (type is ArrayType) {
+			return new CCodeIdentifier ("g_free");
+		} else if (type is PointerType) {
+			return new CCodeIdentifier ("g_free");
+		} else {
+			return new CCodeConstant ("NULL");
+		}
+	}
+
+	private string generate_glist_free_wrapper (DataType list_type, CCodeIdentifier element_destroy_func_expression) {
+		string destroy_func = "_%s_%s".printf (list_type.data_type.get_free_function (), element_destroy_func_expression.name);
+
+		if (!add_wrapper (destroy_func)) {
+			// wrapper already defined
+			return destroy_func;
+		}
+
+		// declaration
+
+		var function = new CCodeFunction (destroy_func, "void");
+		function.modifiers = CCodeModifiers.STATIC;
+
+		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+		function.add_parameter (new CCodeFormalParameter ("self", list_type.get_cname ()));
+
+		// definition
+
+		var block = new CCodeBlock ();
+
+		CCodeFunctionCall element_free_call;
+		if (list_type.data_type == glist_type) {
+			element_free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
+		} else {
+			element_free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_slist_foreach"));
+		}
+		element_free_call.add_argument (new CCodeIdentifier ("self"));
+		element_free_call.add_argument (new CCodeCastExpression (element_destroy_func_expression, "GFunc"));
+		element_free_call.add_argument (new CCodeConstant ("NULL"));
+		block.add_statement (new CCodeExpressionStatement (element_free_call));
+
+		var cfreecall = new CCodeFunctionCall (new CCodeIdentifier (list_type.data_type.get_free_function ()));
+		cfreecall.add_argument (new CCodeIdentifier ("self"));
+		block.add_statement (new CCodeExpressionStatement (cfreecall));
+
+		// append to file
+
+		source_type_member_declaration.append (function.copy ());
+
+		function.block = block;
+		source_type_member_definition.append (function);
+
+		return destroy_func;
+	}
+
+	public CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
+		var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
+
+		if (type is ValueType && !type.nullable) {
+			// normal value type, no null check
+			ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
+			return ccall;
+		}
+
+		/* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */
+		
+		/* can be simplified to
+		 * foo = (unref (foo), NULL)
+		 * if foo is of static type non-null
+		 */
+
+		var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
+		if (type.type_parameter != null) {
+			if (!(current_type_symbol is Class) || current_class.is_compact) {
+				return new CCodeConstant ("NULL");
+			}
+
+			// unref functions are optional for type parameters
+			var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
+			cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
+		}
+
+		ccall.add_argument (cvar);
+
+		/* set freed references to NULL to prevent further use */
+		var ccomma = new CCodeCommaExpression ();
+
+		if (type.data_type == gstringbuilder_type) {
+			ccall.add_argument (new CCodeConstant ("TRUE"));
+		} else if (type is ArrayType) {
+			var array_type = (ArrayType) type;
+			if (array_type.element_type.data_type == null || array_type.element_type.data_type.is_reference_type ()) {
+				requires_array_free = true;
+
+				bool first = true;
+				CCodeExpression csizeexpr = null;
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					if (first) {
+						csizeexpr = head.get_array_length_cexpression (expr, dim);
+						first = false;
+					} else {
+						csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, head.get_array_length_cexpression (expr, dim));
+					}
+				}
+
+				ccall.call = new CCodeIdentifier ("_vala_array_free");
+				ccall.add_argument (csizeexpr);
+				ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
+			}
+		}
+		
+		ccomma.append_expression (ccall);
+		ccomma.append_expression (new CCodeConstant ("NULL"));
+		
+		var cassign = new CCodeAssignment (cvar, ccomma);
+
+		// g_free (NULL) is allowed
+		bool uses_gfree = (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free");
+		uses_gfree = uses_gfree || type is ArrayType;
+		if (uses_gfree) {
+			return new CCodeParenthesizedExpression (cassign);
+		}
+
+		return new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), new CCodeParenthesizedExpression (cassign));
+	}
+	
+	public override void visit_end_full_expression (Expression expr) {
+		/* expr is a full expression, i.e. an initializer, the
+		 * expression in an expression statement, the controlling
+		 * expression in if, while, for, or foreach statements
+		 *
+		 * 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 (((Gee.List<LocalVariable>) temp_ref_vars).size == 0) {
+			/* nothing to do without temporary variables */
+			return;
+		}
+
+		var expr_type = expr.value_type;
+		if (expr.target_type != null) {
+			expr_type = expr.target_type;
+		}
+
+		var full_expr_var = get_temp_variable (expr_type, true, expr);
+		expr.temp_vars.add (full_expr_var);
+		
+		var expr_list = new CCodeCommaExpression ();
+		expr_list.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_var.name), (CCodeExpression) expr.ccodenode));
+		
+		foreach (LocalVariable local in temp_ref_vars) {
+			var ma = new MemberAccess.simple (local.name);
+			ma.symbol_reference = local;
+			expr_list.append_expression (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma));
+		}
+		
+		expr_list.append_expression (new CCodeIdentifier (full_expr_var.name));
+		
+		expr.ccodenode = expr_list;
+		
+		temp_ref_vars.clear ();
+	}
+	
+	private void append_temp_decl (CCodeFragment cfrag, Gee.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);
+			// sets #line
+			local.ccodenode = vardecl;
+			cdecl.add_declarator (vardecl);
+
+			var st = local.variable_type.data_type as Struct;
+
+			if (local.variable_type.is_reference_type_or_type_parameter ()) {
+				vardecl.initializer = new CCodeConstant ("NULL");
+			} else if (st != null && !st.is_simple_type ()) {
+				// 0-initialize struct with struct initializer { 0 }
+				// necessary as they will be passed by reference
+				var clist = new CCodeInitializerList ();
+				clist.append (new CCodeConstant ("0"));
+
+				vardecl.initializer = clist;
+			}
+			
+			cfrag.append (cdecl);
+		}
+	}
+
+	public override void visit_expression_statement (ExpressionStatement stmt) {
+		if (stmt.expression.error) {
+			stmt.error = true;
+			return;
+		}
+
+		stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
+
+		var invoc = stmt.expression as InvocationExpression;
+		if (invoc != null) {
+			var m = invoc.call.symbol_reference as Method;
+			var ma = invoc.call as MemberAccess;
+			if (m != null && m.coroutine && (ma == null || ma.member_name != "begin"
+				                         || ma.inner.symbol_reference != ma.symbol_reference)) {
+				var cfrag = new CCodeFragment ();
+
+				int state = next_coroutine_state++;
+
+				cfrag.append (stmt.ccodenode);
+				cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "state"), new CCodeConstant (state.to_string ()))));
+				cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+				cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+
+				stmt.ccodenode = cfrag;
+			}
+		}
+
+		if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
+			// simple case, no node breakdown necessary
+
+			var cfrag = new CCodeFragment ();
+
+			cfrag.append (stmt.ccodenode);
+
+			head.add_simple_check (stmt.expression, cfrag);
+
+			stmt.ccodenode = cfrag;
+		}
+
+		/* free temporary objects */
+
+		if (((Gee.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)));
+		}
+		
+		stmt.ccodenode = cfrag;
+		
+		temp_vars.clear ();
+		temp_ref_vars.clear ();
+	}
+	
+	public void create_temp_decl (Statement stmt, Gee.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);
+		
+		// FIXME cast to CodeNode shouldn't be necessary as Statement requires CodeNode
+		cfrag.append (((CodeNode) stmt).ccodenode);
+		
+		((CodeNode) stmt).ccodenode = cfrag;
+	}
+
+	public override void visit_if_statement (IfStatement stmt) {
+		stmt.accept_children (codegen);
+
+		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);
+	}
+
+	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, true, stmt);
+		stmt.expression.temp_vars.insert (0, temp_var);
+
+		var ctemp = new CCodeIdentifier (temp_var.name);
+		var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
+		var czero = new CCodeConstant ("0");
+
+		var cswitchblock = new CCodeFragment ();
+		stmt.ccodenode = cswitchblock;
+
+		var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
+		var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+		cquark.add_argument (ctemp);
+
+		var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
+
+		temp_var = get_temp_variable (gquark_type);
+		stmt.expression.temp_vars.insert (0, temp_var);
+
+		int label_count = 0;
+
+		foreach (SwitchSection section in stmt.get_sections ()) {
+			if (section.has_default_label ()) {
+				continue;
+			}
+
+			foreach (SwitchLabel label in section.get_labels ()) {
+				var cexpr = (CCodeExpression) label.expression.ccodenode;
+
+				if (is_constant_ccode_expression (cexpr)) {
+					var cname = "%s_label%d".printf (temp_var.name, label_count++);
+					var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
+
+					cdecl.modifiers = CCodeModifiers.STATIC;
+					cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
+
+					cswitchblock.append (cdecl);
+				}
+			}
+		}
+
+		cswitchblock.append (new CCodeExpressionStatement (cinit));
+
+		ctemp = new CCodeIdentifier (temp_var.name);
+		cinit = new CCodeAssignment (ctemp, ccond);
+
+		cswitchblock.append (new CCodeExpressionStatement (cinit));
+		create_temp_decl (stmt, stmt.expression.temp_vars);
+
+		Gee.List<Statement> default_statements = null;
+		label_count = 0;
+
+		// generate nested if statements		
+		CCodeStatement ctopstmt = null;
+		CCodeIfStatement coldif = null;
+
+		foreach (SwitchSection section in stmt.get_sections ()) {
+			if (section.has_default_label ()) {
+				default_statements = section.get_statements ();
+				continue;
+			}
+
+			CCodeBinaryExpression cor = null;
+			foreach (SwitchLabel label in section.get_labels ()) {
+				var cexpr = (CCodeExpression) label.expression.ccodenode;
+
+				if (is_constant_ccode_expression (cexpr)) {
+					var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
+					var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
+					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
+					var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
+
+					ccall.add_argument (cexpr);
+
+					cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
+				} else {
+					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
+					ccall.add_argument (cexpr);
+					cexpr = ccall;
+				}
+
+				var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
+
+				if (cor == null) {
+					cor = ccmp;
+				} else {
+					cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
+				}
+			}
+
+			var cblock = new CCodeBlock ();
+			foreach (CodeNode body_stmt in section.get_statements ()) {
+				if (body_stmt.ccodenode is CCodeFragment) {
+					foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
+						cblock.add_statement (cstmt);
+					}
+				} else {
+					cblock.add_statement (body_stmt.ccodenode);
+				}
+			}
+
+			var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+			var cif = new CCodeIfStatement (cor, cdo);
+
+			if (coldif != null) {
+				coldif.false_statement = cif;
+			} else {
+				ctopstmt = cif;
+			}
+
+			coldif = cif;
+		}
+	
+		if (default_statements != null) {
+			var cblock = new CCodeBlock ();
+			foreach (CodeNode body_stmt in default_statements) {
+				cblock.add_statement (body_stmt.ccodenode);
+			}
+		
+			var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
+
+			if (coldif == null) {
+				// there is only one section and that section
+				// contains a default label
+				ctopstmt = cdo;
+			} else {
+				coldif.false_statement = cdo;
+			}
+		}
+	
+		cswitchblock.append (ctopstmt);
+	}
+
+	public override void visit_switch_statement (SwitchStatement stmt) {
+		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;
+
+		foreach (SwitchSection section in stmt.get_sections ()) {
+			if (section.has_default_label ()) {
+				cswitch.add_statement (new CCodeLabel ("default"));
+				var cdefaultblock = new CCodeBlock ();
+				cswitch.add_statement (cdefaultblock);
+				foreach (CodeNode default_stmt in section.get_statements ()) {
+					cdefaultblock.add_statement (default_stmt.ccodenode);
+				}
+				continue;
+			}
+
+			foreach (SwitchLabel label in section.get_labels ()) {
+				cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
+			}
+
+			var cblock = new CCodeBlock ();
+			cswitch.add_statement (cblock);
+			foreach (CodeNode body_stmt in section.get_statements ()) {
+				cblock.add_statement (body_stmt.ccodenode);
+			}
+		}
+	}
+
+	public override void visit_switch_section (SwitchSection section) {
+		visit_block (section);
+	}
+
+	public override void visit_while_statement (WhileStatement stmt) {
+		stmt.accept_children (codegen);
+
+		stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
+		
+		create_temp_decl (stmt, stmt.condition.temp_vars);
+	}
+
+	public override void visit_do_statement (DoStatement stmt) {
+		stmt.accept_children (codegen);
+
+		stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
+		
+		create_temp_decl (stmt, stmt.condition.temp_vars);
+	}
+
+	public override void visit_for_statement (ForStatement stmt) {
+		stmt.accept_children (codegen);
+
+		CCodeExpression ccondition = null;
+		if (stmt.condition != null) {
+			ccondition = (CCodeExpression) stmt.condition.ccodenode;
+		}
+
+		var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
+		stmt.ccodenode = cfor;
+		
+		foreach (Expression init_expr in stmt.get_initializer ()) {
+			cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
+			create_temp_decl (stmt, init_expr.temp_vars);
+		}
+		
+		foreach (Expression it_expr in stmt.get_iterator ()) {
+			cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
+			create_temp_decl (stmt, it_expr.temp_vars);
+		}
+
+		if (stmt.condition != null) {
+			create_temp_decl (stmt, stmt.condition.temp_vars);
+		}
+	}
+
+	public override void visit_foreach_statement (ForeachStatement stmt) {
+		stmt.element_variable.active = true;
+		stmt.collection_variable.active = true;
+		if (stmt.iterator_variable != null) {
+			stmt.iterator_variable.active = true;
+		}
+
+		visit_block (stmt);
+
+		var cblock = new CCodeBlock ();
+		// sets #line
+		stmt.ccodenode = cblock;
+
+		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 ();
+		var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
+		var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
+		ccolvardecl.line = cblock.line;
+		ccoldecl.add_declarator (ccolvardecl);
+		cblock.add_statement (ccoldecl);
+		
+		if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
+			// exception handling
+			var cfrag = new CCodeFragment ();
+			head.add_simple_check (stmt.collection, cfrag);
+			cblock.add_statement (cfrag);
+		}
+
+		if (stmt.collection.value_type is ArrayType) {
+			var array_type = (ArrayType) stmt.collection.value_type;
+			
+			var array_len = head.get_array_length_cexpression (stmt.collection);
+
+			// store array length for use by _vala_array_free
+			var clendecl = new CCodeDeclaration ("int");
+			clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
+			cblock.add_statement (clendecl);
+
+			if (array_len is CCodeConstant) {
+				// the array has no length parameter i.e. it is NULL-terminated array
+
+				var it_name = "%s_it".printf (stmt.variable_name);
+			
+				var citdecl = new CCodeDeclaration (collection_type.get_cname ());
+				citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+				cblock.add_statement (citdecl);
+				
+				var cbody = new CCodeBlock ();
+
+				CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
+
+				var element_type = array_type.element_type.copy ();
+				element_type.value_owned = false;
+				element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+				var cfrag = new CCodeFragment ();
+				append_temp_decl (cfrag, temp_vars);
+				cbody.add_statement (cfrag);
+				temp_vars.clear ();
+
+				var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+				cbody.add_statement (cdecl);
+
+				// add array length variable for stacked arrays
+				if (stmt.type_reference is ArrayType) {
+					var inner_array_type = (ArrayType) stmt.type_reference;
+					for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+						cdecl = new CCodeDeclaration ("int");
+						cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+						cbody.add_statement (cdecl);
+					}
+				}
+
+				cbody.add_statement (stmt.body.ccodenode);
+				
+				var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
+				
+				var cfor = new CCodeForStatement (ccond, cbody);
+
+				cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+		
+				cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+				cblock.add_statement (cfor);
+			} else {
+				// the array has a length parameter
+
+				var it_name = (stmt.variable_name + "_it");
+			
+				var citdecl = new CCodeDeclaration ("int");
+				citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+				cblock.add_statement (citdecl);
+				
+				var cbody = new CCodeBlock ();
+
+				CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
+
+				var element_type = array_type.element_type.copy ();
+				element_type.value_owned = false;
+				element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+				var cfrag = new CCodeFragment ();
+				append_temp_decl (cfrag, temp_vars);
+				cbody.add_statement (cfrag);
+				temp_vars.clear ();
+
+				var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+				cbody.add_statement (cdecl);
+
+				// add array length variable for stacked arrays
+				if (stmt.type_reference is ArrayType) {
+					var inner_array_type = (ArrayType) stmt.type_reference;
+					for (int dim = 1; dim <= inner_array_type.rank; dim++) {
+						cdecl = new CCodeDeclaration ("int");
+						cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
+						cbody.add_statement (cdecl);
+					}
+				}
+
+				cbody.add_statement (stmt.body.ccodenode);
+				
+				var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
+				var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
+				var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
+				
+				/* only check for null if the containers elements are of reference-type */
+				CCodeBinaryExpression ccond;
+				if (array_type.element_type.is_reference_type_or_type_parameter ()) {
+					var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
+					var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
+					var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
+
+					ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
+				} else {
+					/* assert when trying to iterate over value-type arrays of unknown length */
+					var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
+					cassert.add_argument (ccond_ind1);
+					cblock.add_statement (new CCodeExpressionStatement (cassert));
+
+					ccond = ccond_ind2;
+				}
+				
+				var cfor = new CCodeForStatement (ccond, cbody);
+				cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+				cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+				cblock.add_statement (cfor);
+			}
+		} 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
+
+			var it_name = "%s_it".printf (stmt.variable_name);
+		
+			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);
+			
+			var cbody = new CCodeBlock ();
+
+			CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
+
+			if (collection_type.get_type_arguments ().size != 1) {
+				Report.error (stmt.source_reference, "internal error: missing generic type argument");
+				stmt.error = true;
+				return;
+			}
+
+			var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
+			element_data_type.value_owned = false;
+			element_data_type.is_type_argument = true;
+			element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
+
+			var cfrag = new CCodeFragment ();
+			append_temp_decl (cfrag, temp_vars);
+			cbody.add_statement (cfrag);
+			temp_vars.clear ();
+
+			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+			cvardecl.line = cblock.line;
+			cdecl.add_declarator (cvardecl);
+			cbody.add_statement (cdecl);
+			
+			cbody.add_statement (stmt.body.ccodenode);
+			
+			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
+			
+			var cfor = new CCodeForStatement (ccond, cbody);
+			
+			cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
+
+			cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
+			cblock.add_statement (cfor);
+		} else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
+			// iterating over a Gee.List, use integer to avoid the cost of an iterator object
+
+			var it_name = "%s_it".printf (stmt.variable_name);
+
+			var citdecl = new CCodeDeclaration ("int");
+			citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
+			cblock.add_statement (citdecl);
+			
+			var cbody = new CCodeBlock ();
+
+			var get_method = (Method) list_type.scope.lookup ("get");
+			var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+			get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
+			get_ccall.add_argument (new CCodeIdentifier (it_name));
+			CCodeExpression element_expr = get_ccall;
+
+			var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
+
+			element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
+
+			var cfrag = new CCodeFragment ();
+			append_temp_decl (cfrag, temp_vars);
+			cbody.add_statement (cfrag);
+			temp_vars.clear ();
+
+			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+			cvardecl.line = cblock.line;
+			cdecl.add_declarator (cvardecl);
+			cbody.add_statement (cdecl);
+
+			cbody.add_statement (stmt.body.ccodenode);
+
+			var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
+			list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
+
+			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
+
+			var cfor = new CCodeForStatement (ccond, cbody);
+			cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
+			cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
+			cfor.line = cblock.line;
+			cblock.add_statement (cfor);
+		} else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
+			// iterating over a Gee.Iterable, use iterator
+
+			var it_name = "%s_it".printf (stmt.variable_name);
+
+			var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
+			var it_method = (Method) iterable_type.scope.lookup ("iterator");
+			var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
+			it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
+			var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
+			citvardecl.line = cblock.line;
+			citdecl.add_declarator (citvardecl);
+			cblock.add_statement (citdecl);
+			
+			var cbody = new CCodeBlock ();
+
+			var get_method = (Method) iterator_type.scope.lookup ("get");
+			var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+			get_ccall.add_argument (new CCodeIdentifier (it_name));
+			CCodeExpression element_expr = get_ccall;
+
+			Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
+			type_arg_it.next ();
+			var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
+
+			element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
+
+			var cfrag = new CCodeFragment ();
+			append_temp_decl (cfrag, temp_vars);
+			cbody.add_statement (cfrag);
+			temp_vars.clear ();
+
+			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
+			cvardecl.line = cblock.line;
+			cdecl.add_declarator (cvardecl);
+			cbody.add_statement (cdecl);
+			
+			cbody.add_statement (stmt.body.ccodenode);
+
+			var next_method = (Method) iterator_type.scope.lookup ("next");
+			var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
+			next_ccall.add_argument (new CCodeIdentifier (it_name));
+
+			var cwhile = new CCodeWhileStatement (next_ccall, cbody);
+			cwhile.line = cblock.line;
+			cblock.add_statement (cwhile);
+		}
+
+		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 (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
+				cunref.line = cblock.line;
+				cblock.add_statement (cunref);
+			}
+		}
+	}
+
+	public override void visit_break_statement (BreakStatement stmt) {
+		stmt.ccodenode = new CCodeBreakStatement ();
+
+		create_local_free (stmt, true);
+	}
+
+	public override void visit_continue_statement (ContinueStatement stmt) {
+		stmt.ccodenode = new CCodeContinueStatement ();
+
+		create_local_free (stmt, true);
+	}
+
+	public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) {
+		var b = (Block) sym;
+
+		var local_vars = b.get_local_variables ();
+		foreach (LocalVariable local in local_vars) {
+			if (local.active && requires_destroy (local.variable_type)) {
+				var ma = new MemberAccess.simple (local.name);
+				ma.symbol_reference = local;
+				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
+			}
+		}
+		
+		if (stop_at_loop) {
+			if (b.parent_node is DoStatement || b.parent_node is WhileStatement ||
+			    b.parent_node is ForStatement || b.parent_node is ForeachStatement ||
+			    b.parent_node is SwitchStatement) {
+				return;
+			}
+		}
+
+		if (sym.parent_symbol is Block) {
+			append_local_free (sym.parent_symbol, cfrag, stop_at_loop);
+		} else if (sym.parent_symbol is Method) {
+			append_param_free ((Method) sym.parent_symbol, cfrag);
+		}
+	}
+
+	private void append_param_free (Method m, CCodeFragment cfrag) {
+		foreach (FormalParameter param in m.get_parameters ()) {
+			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
+				var ma = new MemberAccess.simple (param.name);
+				ma.symbol_reference = param;
+				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
+			}
+		}
+	}
+
+	private 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;
+	}
+
+	private bool append_local_free_expr (Symbol sym, CCodeCommaExpression ccomma, bool stop_at_loop) {
+		bool found = false;
+	
+		var b = (Block) sym;
+
+		var local_vars = b.get_local_variables ();
+		foreach (LocalVariable local in local_vars) {
+			if (local.active && requires_destroy (local.variable_type)) {
+				found = true;
+				var ma = new MemberAccess.simple (local.name);
+				ma.symbol_reference = local;
+				ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
+			}
+		}
+		
+		if (sym.parent_symbol is Block) {
+			found = append_local_free_expr (sym.parent_symbol, ccomma, stop_at_loop) || found;
+		} else if (sym.parent_symbol is Method) {
+			found = append_param_free_expr ((Method) sym.parent_symbol, ccomma) || found;
+		}
+		
+		return found;
+	}
+
+	private bool append_param_free_expr (Method m, CCodeCommaExpression ccomma) {
+		bool found = false;
+
+		foreach (FormalParameter param in m.get_parameters ()) {
+			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
+				found = true;
+				var ma = new MemberAccess.simple (param.name);
+				ma.symbol_reference = param;
+				ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma));
+			}
+		}
+
+		return found;
+	}
+
+	private void create_local_free_expr (Expression expr) {
+		var expr_type = expr.value_type;
+		if (expr.target_type != null) {
+			expr_type = expr.target_type;
+		}
+
+		var return_expr_decl = get_temp_variable (expr_type, true, expr);
+		
+		var ccomma = new CCodeCommaExpression ();
+		ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (return_expr_decl.name), (CCodeExpression) expr.ccodenode));
+
+		if (!append_local_free_expr (current_symbol, ccomma, false)) {
+			/* no local variables need to be freed */
+			return;
+		}
+
+		ccomma.append_expression (new CCodeIdentifier (return_expr_decl.name));
+		
+		expr.ccodenode = ccomma;
+		expr.temp_vars.add (return_expr_decl);
+	}
+
+	public override void visit_return_statement (ReturnStatement stmt) {
+		// avoid unnecessary ref/unref pair
+		if (stmt.return_expression != null) {
+			var local = stmt.return_expression.symbol_reference as LocalVariable;
+			if (current_return_type.value_owned
+			    && local != null && local.variable_type.value_owned) {
+				/* return expression is local variable taking ownership and
+				 * current method is transferring ownership */
+
+				// don't ref expression
+				stmt.return_expression.value_type.value_owned = true;
+			}
+		}
+
+		stmt.accept_children (codegen);
+
+		if (stmt.return_expression == null) {
+			stmt.ccodenode = new CCodeReturnStatement ();
+			
+			create_local_free (stmt);
+		} else {
+			Symbol return_expression_symbol = null;
+
+			// avoid unnecessary ref/unref pair
+			var local = stmt.return_expression.symbol_reference as LocalVariable;
+			if (current_return_type.value_owned
+			    && local != null && local.variable_type.value_owned) {
+				/* return expression is local variable taking ownership and
+				 * current method is transferring ownership */
+
+				// don't unref variable
+				return_expression_symbol = local;
+				return_expression_symbol.active = false;
+			}
+
+			// return array length if appropriate
+			if (current_method != null && !current_method.no_array_length && current_return_type is ArrayType) {
+				var return_expr_decl = get_temp_variable (stmt.return_expression.value_type, true, stmt);
+
+				var ccomma = new CCodeCommaExpression ();
+				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (return_expr_decl.name), (CCodeExpression) stmt.return_expression.ccodenode));
+
+				var array_type = (ArrayType) current_return_type;
+
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var len_l = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (head.get_array_length_cname ("result", dim)));
+					var len_r = head.get_array_length_cexpression (stmt.return_expression, dim);
+					ccomma.append_expression (new CCodeAssignment (len_l, len_r));
+				}
+
+				ccomma.append_expression (new CCodeIdentifier (return_expr_decl.name));
+				
+				stmt.return_expression.ccodenode = ccomma;
+				stmt.return_expression.temp_vars.add (return_expr_decl);
+			}
+
+			create_local_free_expr (stmt.return_expression);
+
+			// Property getters of non simple structs shall return the struct value as out parameter,
+			// therefore replace any return statement with an assignment statement to the out formal
+			// paramenter and insert an empty return statement afterwards.
+			if (current_property_accessor != null &&
+			    current_property_accessor.readable &&
+			    current_property_accessor.prop.property_type.is_real_struct_type()) {
+			    	var cfragment = new CCodeFragment ();
+				cfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("*value"), (CCodeExpression) stmt.return_expression.ccodenode)));
+				cfragment.append (new CCodeReturnStatement ());
+				stmt.ccodenode = cfragment;
+			} else {
+				stmt.ccodenode = new CCodeReturnStatement ((CCodeExpression) stmt.return_expression.ccodenode);
+			}
+
+			create_temp_decl (stmt, stmt.return_expression.temp_vars);
+
+			if (return_expression_symbol != null) {
+				return_expression_symbol.active = true;
+			}
+		}
+	}
+
+	public override void visit_yield_statement (YieldStatement stmt) {
+		if (stmt.yield_expression == null) {
+			var cfrag = new CCodeFragment ();
+			stmt.ccodenode = cfrag;
+
+			var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_idle_add"));
+			idle_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (current_method.get_real_cname ()), "GSourceFunc"));
+			idle_call.add_argument (new CCodeIdentifier ("data"));
+
+			int state = next_coroutine_state++;
+
+			cfrag.append (new CCodeExpressionStatement (idle_call));
+			cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "state"), new CCodeConstant (state.to_string ()))));
+			cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
+			cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
+
+			return;
+		}
+
+		stmt.accept_children (codegen);
+
+		if (stmt.yield_expression.error) {
+			stmt.error = true;
+			return;
+		}
+
+		stmt.ccodenode = new CCodeExpressionStatement ((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);
+
+			head.add_simple_check (stmt.yield_expression, cfrag);
+
+			stmt.ccodenode = cfrag;
+		}
+
+		/* free temporary objects */
+
+		if (((Gee.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)));
+		}
+		
+		stmt.ccodenode = cfrag;
+		
+		temp_vars.clear ();
+		temp_ref_vars.clear ();
+	}
+
+	public override void visit_try_statement (TryStatement stmt) {
+		int this_try_id = next_try_id++;
+
+		var old_try = current_try;
+		var old_try_id = current_try_id;
+		current_try = stmt;
+		current_try_id = this_try_id;
+
+		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
+			clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ());
+		}
+
+		if (stmt.finally_body != null) {
+			stmt.finally_body.accept (codegen);
+		}
+
+		stmt.body.accept (codegen);
+
+		current_try = old_try;
+		current_try_id = old_try_id;
+
+		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
+			clause.accept (codegen);
+		}
+
+		if (stmt.finally_body != null) {
+			stmt.finally_body.accept (codegen);
+		}
+
+		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)));
+		if (stmt.finally_body != null) {
+			cfrag.append (stmt.finally_body.ccodenode);
+		} else {
+			// avoid gcc error: label at end of compound statement
+			cfrag.append (new CCodeEmptyStatement ());
+		}
+
+		stmt.ccodenode = cfrag;
+	}
+
+	public override void visit_catch_clause (CatchClause clause) {
+		if (clause.error_variable != null) {
+			clause.error_variable.active = true;
+		}
+
+		current_method_inner_error = true;
+
+		clause.accept_children (codegen);
+
+		var cfrag = new CCodeFragment ();
+		cfrag.append (new CCodeLabel (clause.clabel_name));
+
+		var cblock = new CCodeBlock ();
+
+		string variable_name = clause.variable_name;
+		if (variable_name == null) {
+			variable_name = "__err";
+		}
+
+		var cdecl = new CCodeDeclaration ("GError *");
+		cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (variable_name, new CCodeIdentifier ("inner_error")));
+		cblock.add_statement (cdecl);
+		cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("inner_error"), new CCodeConstant ("NULL"))));
+
+		cblock.add_statement (clause.body.ccodenode);
+
+		cfrag.append (cblock);
+
+		clause.ccodenode = cfrag;
+	}
+
+	private string get_symbol_lock_name (Symbol sym) {
+		return "__lock_%s".printf (sym.name);
+	}
+
+	public override void visit_lock_statement (LockStatement stmt) {
+		var cn = new CCodeFragment ();
+		CCodeExpression l = null;
+		CCodeFunctionCall fc;
+		var inner_node = ((MemberAccess)stmt.resource).inner;
+		
+		if (inner_node  == null) {
+			l = new CCodeIdentifier ("self");
+		} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
+			 l = new InstanceCast ((CCodeExpression) inner_node.ccodenode, (TypeSymbol) stmt.resource.symbol_reference.parent_symbol);
+		} else {
+			l = (CCodeExpression) inner_node.ccodenode;
+		}
+		l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference));
+		
+		fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
+		fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
+
+		cn.append (new CCodeExpressionStatement (fc));
+		
+		cn.append (stmt.body.ccodenode);
+		
+		fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
+		fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
+		cn.append (new CCodeExpressionStatement (fc));
+		
+		stmt.ccodenode = cn;
+	}
+
+	public override void visit_delete_statement (DeleteStatement stmt) {
+		stmt.accept_children (codegen);
+
+		var pointer_type = (PointerType) stmt.expression.value_type;
+		DataType type = pointer_type;
+		if (pointer_type.base_type.data_type != null && pointer_type.base_type.data_type.is_reference_type ()) {
+			type = pointer_type.base_type;
+		}
+
+		var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
+		ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode);
+		stmt.ccodenode = new CCodeExpressionStatement (ccall);
+	}
+
+	public override void visit_expression (Expression expr) {
+		if (expr.ccodenode != null && !expr.lvalue) {
+			// memory management, implicit casts, and boxing/unboxing
+			expr.ccodenode = transform_expression ((CCodeExpression) expr.ccodenode, expr.value_type, expr.target_type, expr);
+		}
+	}
+
+	public override void visit_boolean_literal (BooleanLiteral expr) {
+		expr.ccodenode = new CCodeConstant (expr.value ? "TRUE" : "FALSE");
+	}
+
+	public override void visit_character_literal (CharacterLiteral expr) {
+		if (expr.get_char () >= 0x20 && expr.get_char () < 0x80) {
+			expr.ccodenode = new CCodeConstant (expr.value);
+		} else {
+			expr.ccodenode = new CCodeConstant ("%uU".printf (expr.get_char ()));
+		}
+	}
+
+	public override void visit_integer_literal (IntegerLiteral expr) {
+		expr.ccodenode = new CCodeConstant (expr.value);
+	}
+
+	public override void visit_real_literal (RealLiteral expr) {
+		expr.ccodenode = new CCodeConstant (expr.value);
+	}
+
+	public override void visit_string_literal (StringLiteral expr) {
+		expr.ccodenode = new CCodeConstant (expr.value);
+	}
+
+	public override void visit_null_literal (NullLiteral expr) {
+		expr.ccodenode = new CCodeConstant ("NULL");
+	}
+
+	public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
+		expr.accept_children (codegen);
+
+		expr.ccodenode = new CCodeParenthesizedExpression ((CCodeExpression) expr.inner.ccodenode);
+	}
+
+	public string get_delegate_target_cname (string delegate_cname) {
+		return "%s_target".printf (delegate_cname);
+	}
+
+	public CCodeExpression get_delegate_target_cexpression (Expression delegate_expr) {
+		bool is_out = false;
+	
+		if (delegate_expr is UnaryExpression) {
+			var unary_expr = (UnaryExpression) delegate_expr;
+			if (unary_expr.operator == UnaryOperator.OUT || unary_expr.operator == UnaryOperator.REF) {
+				delegate_expr = unary_expr.inner;
+				is_out = true;
+			}
+		}
+		
+		if (delegate_expr is InvocationExpression) {
+			var invocation_expr = (InvocationExpression) delegate_expr;
+			return invocation_expr.delegate_target;
+		} else if (delegate_expr is LambdaExpression) {
+			if ((current_method != null && current_method.binding == MemberBinding.INSTANCE) || in_constructor) {
+				return new CCodeIdentifier ("self");
+			} else {
+				return new CCodeConstant ("NULL");
+			}
+		} else if (delegate_expr.symbol_reference != null) {
+			if (delegate_expr.symbol_reference is FormalParameter) {
+				var param = (FormalParameter) delegate_expr.symbol_reference;
+				CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (param.name));
+				if (param.direction != ParameterDirection.IN) {
+					// accessing argument of out/ref param
+					target_expr = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr));
+				}
+				if (is_out) {
+					// passing array as out/ref
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is LocalVariable) {
+				var local = (LocalVariable) delegate_expr.symbol_reference;
+				var target_expr = new CCodeIdentifier (get_delegate_target_cname (local.name));
+				if (is_out) {
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is Field) {
+				var field = (Field) delegate_expr.symbol_reference;
+				var target_cname = get_delegate_target_cname (field.name);
+
+				var ma = (MemberAccess) delegate_expr;
+
+				var base_type = ma.inner.value_type;
+				CCodeExpression target_expr = null;
+
+				var pub_inst = (CCodeExpression) get_ccodenode (ma.inner);
+
+				if (field.binding == MemberBinding.INSTANCE) {
+					var instance_expression_type = base_type;
+					var instance_target_type = get_data_type_for_symbol ((TypeSymbol) field.parent_symbol);
+					CCodeExpression typed_inst = transform_expression (pub_inst, instance_expression_type, instance_target_type);
+
+					CCodeExpression inst;
+					if (field.access == SymbolAccessibility.PRIVATE) {
+						inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
+					} else {
+						inst = typed_inst;
+					}
+					if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
+						target_expr = new CCodeMemberAccess.pointer (inst, target_cname);
+					} else {
+						target_expr = new CCodeMemberAccess (inst, target_cname);
+					}
+				} else {
+					target_expr = new CCodeIdentifier (target_cname);
+				}
+
+				if (is_out) {
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+				} else {
+					return target_expr;
+				}
+			} else if (delegate_expr.symbol_reference is Method) {
+				var m = (Method) delegate_expr.symbol_reference;
+				var ma = (MemberAccess) delegate_expr;
+				if (m.binding == MemberBinding.STATIC) {
+					return new CCodeConstant ("NULL");
+				} else {
+					return (CCodeExpression) get_ccodenode (ma.inner);
+				}
+			}
+		}
+
+		return new CCodeConstant ("NULL");
+	}
+
+	public string get_delegate_target_destroy_notify_cname (string delegate_cname) {
+		return "%s_target_destroy_notify".printf (delegate_cname);
+	}
+
+	public override void visit_base_access (BaseAccess expr) {
+		expr.ccodenode = new InstanceCast (new CCodeIdentifier ("self"), expr.value_type.data_type);
+	}
+
+	public override void visit_postfix_expression (PostfixExpression expr) {
+		MemberAccess ma = find_property_access (expr.inner);
+		if (ma != null) {
+			// property postfix expression
+			var prop = (Property) ma.symbol_reference;
+			
+			var ccomma = new CCodeCommaExpression ();
+			
+			// assign current value to temp variable
+			var temp_decl = get_temp_variable (prop.property_type, true, expr);
+			temp_vars.insert (0, temp_decl);
+			ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), (CCodeExpression) expr.inner.ccodenode));
+			
+			// increment/decrement property
+			var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS;
+			var cexpr = new CCodeBinaryExpression (op, new CCodeIdentifier (temp_decl.name), new CCodeConstant ("1"));
+			var ccall = get_property_set_call (prop, ma, cexpr);
+			ccomma.append_expression (ccall);
+			
+			// return previous value
+			ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
+			
+			expr.ccodenode = ccomma;
+			return;
+		}
+	
+		var op = expr.increment ? CCodeUnaryOperator.POSTFIX_INCREMENT : CCodeUnaryOperator.POSTFIX_DECREMENT;
+	
+		expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
+	}
+	
+	private MemberAccess? find_property_access (Expression expr) {
+		if (expr is ParenthesizedExpression) {
+			var pe = (ParenthesizedExpression) expr;
+			return find_property_access (pe.inner);
+		}
+	
+		if (!(expr is MemberAccess)) {
+			return null;
+		}
+		
+		var ma = (MemberAccess) expr;
+		if (ma.symbol_reference is Property) {
+			return ma;
+		}
+		
+		return null;
+	}
+
+	public bool requires_copy (DataType type) {
+		if (!type.is_disposable ()) {
+			return false;
+		}
+
+		if (type.type_parameter != null) {
+			if (!(current_type_symbol is Class) || current_class.is_compact) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	public bool requires_destroy (DataType type) {
+		if (!type.is_disposable ()) {
+			return false;
+		}
+
+		if (type.type_parameter != null) {
+			if (!(current_type_symbol is Class) || current_class.is_compact) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	private CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
+		if (expression_type is ValueType && !expression_type.nullable) {
+			// normal value type, no null check
+			// (copy (&expr, &temp), temp)
+
+			var decl = get_temp_variable (expression_type, false, node);
+			temp_vars.insert (0, decl);
+
+			var ctemp = new CCodeIdentifier (decl.name);
+			
+			var vt = (ValueType) expression_type;
+			var st = (Struct) vt.type_symbol;
+			var copy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_copy_function ()));
+			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr));
+			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
+
+			var ccomma = new CCodeCommaExpression ();
+			ccomma.append_expression (copy_call);
+			ccomma.append_expression (ctemp);
+
+			return ccomma;
+		}
+
+		/* (temp = expr, temp == NULL ? NULL : ref (temp))
+		 *
+		 * can be simplified to
+		 * ref (expr)
+		 * if static type of expr is non-null
+		 */
+		 
+		var dupexpr = get_dup_func_expression (expression_type, node.source_reference);
+
+		if (dupexpr == null) {
+			node.error = true;
+			return null;
+		}
+
+		var ccall = new CCodeFunctionCall (dupexpr);
+
+		if (expr != null && expr.is_non_null ()) {
+			// expression is non-null
+			ccall.add_argument ((CCodeExpression) expr.ccodenode);
+			
+			return ccall;
+		} else {
+			var decl = get_temp_variable (expression_type, false, node);
+			temp_vars.insert (0, decl);
+
+			var ctemp = new CCodeIdentifier (decl.name);
+			
+			var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, new CCodeConstant ("NULL"));
+			if (expression_type.type_parameter != null) {
+				if (!(current_type_symbol is Class)) {
+					return cexpr;
+				}
+
+				// dup functions are optional for type parameters
+				var cdupisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_dup_func_expression (expression_type, node.source_reference), new CCodeConstant ("NULL"));
+				cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cdupisnull);
+			}
+
+			if (expression_type.type_parameter != null) {
+				// cast from gconstpointer to gpointer as GBoxedCopyFunc expects gpointer
+				ccall.add_argument (new CCodeCastExpression (ctemp, "gpointer"));
+			} else {
+				ccall.add_argument (ctemp);
+			}
+
+			if (expression_type is ArrayType) {
+				var array_type = (ArrayType) expression_type;
+				bool first = true;
+				CCodeExpression csizeexpr = null;
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					if (first) {
+						csizeexpr = head.get_array_length_cexpression (expr, dim);
+						first = false;
+					} else {
+						csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, head.get_array_length_cexpression (expr, dim));
+					}
+				}
+
+				ccall.add_argument (csizeexpr);
+			}
+
+			var ccomma = new CCodeCommaExpression ();
+			ccomma.append_expression (new CCodeAssignment (ctemp, cexpr));
+
+			CCodeExpression cifnull;
+			if (expression_type.data_type != null) {
+				cifnull = new CCodeConstant ("NULL");
+			} else {
+				// the value might be non-null even when the dup function is null,
+				// so we may not just use NULL for type parameters
+
+				// cast from gconstpointer to gpointer as methods in
+				// generic classes may not return gconstpointer
+				cifnull = new CCodeCastExpression (ctemp, "gpointer");
+			}
+			ccomma.append_expression (new CCodeConditionalExpression (cisnull, cifnull, ccall));
+
+			return ccomma;
+		}
+	}
+
+	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+		expr.accept_children (codegen);
+
+		CCodeExpression instance = null;
+		CCodeExpression creation_expr = null;
+
+		var st = expr.type_reference.data_type as Struct;
+		if ((st != null && !st.is_simple_type ()) || expr.get_object_initializer ().size > 0) {
+			// value-type initialization or object creation expression with object initializer
+			var temp_decl = get_temp_variable (expr.type_reference, false, expr);
+			temp_vars.add (temp_decl);
+
+			instance = new CCodeIdentifier (get_variable_cname (temp_decl.name));
+		}
+
+		if (expr.symbol_reference == null) {
+			CCodeFunctionCall creation_call;
+
+			// no creation method
+			if (expr.type_reference.data_type == glist_type ||
+			    expr.type_reference.data_type == gslist_type) {
+				// NULL is an empty list
+				expr.ccodenode = new CCodeConstant ("NULL");
+			} else if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) {
+				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
+				creation_call.add_argument (new CCodeConstant (expr.type_reference.data_type.get_type_id ()));
+				creation_call.add_argument (new CCodeConstant ("NULL"));
+			} else if (expr.type_reference.data_type is Class) {
+				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
+				creation_call.add_argument (new CCodeConstant (expr.type_reference.data_type.get_cname ()));
+				creation_call.add_argument (new CCodeConstant ("1"));
+			} else if (expr.type_reference.data_type is Struct) {
+				// memset needs string.h
+				string_h_needed = true;
+				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
+				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
+				creation_call.add_argument (new CCodeConstant ("0"));
+				creation_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (expr.type_reference.get_cname ())));
+			}
+
+			creation_expr = creation_call;
+		} else if (expr.symbol_reference is Method) {
+			// use creation method
+			var m = (Method) expr.symbol_reference;
+			var params = m.get_parameters ();
+			CCodeFunctionCall creation_call;
+
+			creation_call = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
+
+			if ((st != null && !st.is_simple_type ()) && !(m.cinstance_parameter_position < 0)) {
+				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
+			}
+
+			var cl = expr.type_reference.data_type as Class;
+			if (cl != null && !cl.is_compact) {
+				foreach (DataType type_arg in expr.type_reference.get_type_arguments ()) {
+					creation_call.add_argument (get_type_id_expression (type_arg));
+					if (requires_copy (type_arg)) {
+						var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference);
+						if (dup_func == null) {
+							// type doesn't contain a copy function
+							expr.error = true;
+							return;
+						}
+						creation_call.add_argument (new CCodeCastExpression (dup_func, "GBoxedCopyFunc"));
+						creation_call.add_argument (get_destroy_func_expression (type_arg));
+					} else {
+						creation_call.add_argument (new CCodeConstant ("NULL"));
+						creation_call.add_argument (new CCodeConstant ("NULL"));
+					}
+				}
+			}
+
+			var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+
+			bool ellipsis = false;
+
+			int i = 1;
+			int arg_pos;
+			Iterator<FormalParameter> params_it = params.iterator ();
+			foreach (Expression arg in expr.get_argument_list ()) {
+				CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
+				FormalParameter param = null;
+				if (params_it.next ()) {
+					param = params_it.get ();
+					ellipsis = param.ellipsis;
+					if (!ellipsis) {
+						if (!param.no_array_length && param.parameter_type is ArrayType) {
+							var array_type = (ArrayType) param.parameter_type;
+							for (int dim = 1; dim <= array_type.rank; dim++) {
+								carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), head.get_array_length_cexpression (arg, dim));
+							}
+						} else if (param.parameter_type is DelegateType) {
+							var deleg_type = (DelegateType) param.parameter_type;
+							var d = deleg_type.delegate_symbol;
+							if (d.has_target) {
+								var delegate_target = get_delegate_target_cexpression (arg);
+								carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
+							}
+						}
+
+						cexpr = handle_struct_argument (param, arg, cexpr);
+					}
+
+					arg_pos = get_param_pos (param.cparameter_position, ellipsis);
+				} else {
+					// default argument position
+					arg_pos = get_param_pos (i, ellipsis);
+				}
+			
+				carg_map.set (arg_pos, cexpr);
+
+				i++;
+			}
+			while (params_it.next ()) {
+				var param = params_it.get ();
+				
+				if (param.ellipsis) {
+					ellipsis = true;
+					break;
+				}
+				
+				if (param.default_expression == null) {
+					Report.error (expr.source_reference, "no default expression for argument %d".printf (i));
+					return;
+				}
+				
+				/* evaluate default expression here as the code
+				 * generator might not have visited the formal
+				 * parameter yet */
+				param.default_expression.accept (codegen);
+			
+				carg_map.set (get_param_pos (param.cparameter_position), (CCodeExpression) param.default_expression.ccodenode);
+				i++;
+			}
+
+			// append C arguments in the right order
+			int last_pos = -1;
+			int min_pos;
+			while (true) {
+				min_pos = -1;
+				foreach (int pos in carg_map.get_keys ()) {
+					if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+						min_pos = pos;
+					}
+				}
+				if (min_pos == -1) {
+					break;
+				}
+				creation_call.add_argument (carg_map.get (min_pos));
+				last_pos = min_pos;
+			}
+
+			if ((st != null && !st.is_simple_type ()) && m.cinstance_parameter_position < 0) {
+				// instance parameter is at the end in a struct creation method
+				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
+			}
+
+			if (expr.tree_can_fail) {
+				// method can fail
+				current_method_inner_error = true;
+				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
+			}
+
+			if (ellipsis) {
+				/* ensure variable argument list ends with NULL
+				 * except when using printf-style arguments */
+				if (!m.printf_format && m.sentinel != "") {
+					creation_call.add_argument (new CCodeConstant (m.sentinel));
+				}
+			}
+
+			creation_expr = creation_call;
+
+			// cast the return value of the creation method back to the intended type if
+			// it requested a special C return type
+			if (head.get_custom_creturn_type (m) != null) {
+				creation_expr = new CCodeCastExpression (creation_expr, expr.type_reference.get_cname ());
+			}
+		} else if (expr.symbol_reference is ErrorCode) {
+			var ecode = (ErrorCode) expr.symbol_reference;
+			var edomain = (ErrorDomain) ecode.parent_symbol;
+			CCodeFunctionCall creation_call;
+
+			creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_new"));
+			creation_call.add_argument (new CCodeIdentifier (edomain.get_upper_case_cname ()));
+			creation_call.add_argument (new CCodeIdentifier (ecode.get_cname ()));
+
+			foreach (Expression arg in expr.get_argument_list ()) {
+				creation_call.add_argument ((CCodeExpression) arg.ccodenode);
+			}
+
+			creation_expr = creation_call;
+		} else {
+			assert (false);
+		}
+			
+		if (instance != null) {
+			var ccomma = new CCodeCommaExpression ();
+
+			if (expr.type_reference.data_type is Struct) {
+				ccomma.append_expression (creation_expr);
+			} else {
+				ccomma.append_expression (new CCodeAssignment (instance, creation_expr));
+			}
+
+			foreach (MemberInitializer init in expr.get_object_initializer ()) {
+				if (init.symbol_reference is Field) {
+					var f = (Field) init.symbol_reference;
+					var instance_target_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+					var typed_inst = transform_expression (instance, expr.type_reference, instance_target_type);
+					CCodeExpression lhs;
+					if (expr.type_reference.data_type is Struct) {
+						lhs = new CCodeMemberAccess (typed_inst, f.get_cname ());
+					} else {
+						lhs = new CCodeMemberAccess.pointer (typed_inst, f.get_cname ());
+					}
+					ccomma.append_expression (new CCodeAssignment (lhs, (CCodeExpression) init.initializer.ccodenode));
+				} else if (init.symbol_reference is Property) {
+					var inst_ma = new MemberAccess.simple ("new");
+					inst_ma.value_type = expr.type_reference;
+					inst_ma.ccodenode = instance;
+					var ma = new MemberAccess (inst_ma, init.name);
+					ccomma.append_expression (get_property_set_call ((Property) init.symbol_reference, ma, (CCodeExpression) init.initializer.ccodenode));
+				}
+			}
+
+			ccomma.append_expression (instance);
+
+			expr.ccodenode = ccomma;
+		} else if (creation_expr != null) {
+			expr.ccodenode = creation_expr;
+		}
+	}
+
+	public CCodeExpression? handle_struct_argument (FormalParameter param, Expression arg, CCodeExpression? cexpr) {
+		// pass non-simple struct instances always by reference
+		if (!(arg.value_type is NullType) && param.parameter_type.data_type is Struct && !((Struct) param.parameter_type.data_type).is_simple_type ()) {
+			// we already use a reference for arguments of ref, out, and nullable parameters
+			if (param.direction == ParameterDirection.IN && !param.parameter_type.nullable) {
+				var unary = cexpr as CCodeUnaryExpression;
+				if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
+					// *expr => expr
+					return unary.inner;
+				} else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
+					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
+				} else {
+					// if cexpr is e.g. a function call, we can't take the address of the expression
+					// (tmp = expr, &tmp)
+					var ccomma = new CCodeCommaExpression ();
+
+					var temp_var = get_temp_variable (arg.value_type);
+					temp_vars.insert (0, temp_var);
+					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), cexpr));
+					ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
+
+					return ccomma;
+				}
+			}
+		}
+
+		return cexpr;
+	}
+
+	public override void visit_sizeof_expression (SizeofExpression expr) {
+		var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+		csizeof.add_argument (new CCodeIdentifier (expr.type_reference.get_cname ()));
+		expr.ccodenode = csizeof;
+	}
+
+	public override void visit_typeof_expression (TypeofExpression expr) {
+		expr.ccodenode = get_type_id_expression (expr.type_reference);
+	}
+
+	public override void visit_unary_expression (UnaryExpression expr) {
+		expr.accept_children (codegen);
+
+		CCodeUnaryOperator op;
+		if (expr.operator == UnaryOperator.PLUS) {
+			op = CCodeUnaryOperator.PLUS;
+		} else if (expr.operator == UnaryOperator.MINUS) {
+			op = CCodeUnaryOperator.MINUS;
+		} else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) {
+			op = CCodeUnaryOperator.LOGICAL_NEGATION;
+		} else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
+			op = CCodeUnaryOperator.BITWISE_COMPLEMENT;
+		} else if (expr.operator == UnaryOperator.INCREMENT) {
+			op = CCodeUnaryOperator.PREFIX_INCREMENT;
+		} else if (expr.operator == UnaryOperator.DECREMENT) {
+			op = CCodeUnaryOperator.PREFIX_DECREMENT;
+		} else if (expr.operator == UnaryOperator.REF) {
+			op = CCodeUnaryOperator.ADDRESS_OF;
+		} else if (expr.operator == UnaryOperator.OUT) {
+			op = CCodeUnaryOperator.ADDRESS_OF;
+		}
+		expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
+	}
+
+	public override void visit_cast_expression (CastExpression expr) {
+		var cl = expr.type_reference.data_type as Class;
+		var iface = expr.type_reference.data_type as Interface;
+		if (iface != null || (cl != null && !cl.is_compact)) {
+			// checked cast for strict subtypes of GTypeInstance
+			if (expr.is_silent_cast) {
+				var ccomma = new CCodeCommaExpression ();
+				var temp_decl = get_temp_variable (expr.inner.value_type, true, expr);
+
+				temp_vars.add (temp_decl);
+
+				var ctemp = new CCodeIdentifier (temp_decl.name);
+				var cinit = new CCodeAssignment (ctemp, (CCodeExpression) expr.inner.ccodenode);
+				var ccheck = create_type_check (ctemp, expr.type_reference);
+				var ccast = new CCodeCastExpression (ctemp, expr.type_reference.get_cname ());
+				var cnull = new CCodeConstant ("NULL");
+
+				ccomma.append_expression (cinit);
+				ccomma.append_expression (new CCodeConditionalExpression (ccheck, ccast, cnull));
+	
+				expr.ccodenode = ccomma;
+			} else {
+				expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type);
+			}
+		} else {
+			if (expr.is_silent_cast) {
+				expr.error = true;
+				Report.error (expr.source_reference, "Operation not supported for this type");
+				return;
+			}
+			expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
+		}
+	}
+	
+	public override void visit_pointer_indirection (PointerIndirection expr) {
+		expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, (CCodeExpression) expr.inner.ccodenode);
+	}
+
+	public override void visit_addressof_expression (AddressofExpression expr) {
+		expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
+	}
+
+	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		expr.accept_children (codegen);
+
+		/* (tmp = var, var = null, tmp) */
+		var ccomma = new CCodeCommaExpression ();
+		var temp_decl = get_temp_variable (expr.value_type, true, expr);
+		temp_vars.insert (0, temp_decl);
+		var cvar = new CCodeIdentifier (temp_decl.name);
+
+		ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode));
+		ccomma.append_expression (new CCodeAssignment ((CCodeExpression) expr.inner.ccodenode, new CCodeConstant ("NULL")));
+		ccomma.append_expression (cvar);
+		expr.ccodenode = ccomma;
+	}
+
+	public override void visit_binary_expression (BinaryExpression expr) {
+		var cleft = (CCodeExpression) expr.left.ccodenode;
+		var cright = (CCodeExpression) expr.right.ccodenode;
+		
+		CCodeBinaryOperator op;
+		if (expr.operator == BinaryOperator.PLUS) {
+			op = CCodeBinaryOperator.PLUS;
+		} else if (expr.operator == BinaryOperator.MINUS) {
+			op = CCodeBinaryOperator.MINUS;
+		} else if (expr.operator == BinaryOperator.MUL) {
+			op = CCodeBinaryOperator.MUL;
+		} else if (expr.operator == BinaryOperator.DIV) {
+			op = CCodeBinaryOperator.DIV;
+		} else if (expr.operator == BinaryOperator.MOD) {
+			op = CCodeBinaryOperator.MOD;
+		} else if (expr.operator == BinaryOperator.SHIFT_LEFT) {
+			op = CCodeBinaryOperator.SHIFT_LEFT;
+		} else if (expr.operator == BinaryOperator.SHIFT_RIGHT) {
+			op = CCodeBinaryOperator.SHIFT_RIGHT;
+		} else if (expr.operator == BinaryOperator.LESS_THAN) {
+			op = CCodeBinaryOperator.LESS_THAN;
+		} else if (expr.operator == BinaryOperator.GREATER_THAN) {
+			op = CCodeBinaryOperator.GREATER_THAN;
+		} else if (expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL) {
+			op = CCodeBinaryOperator.LESS_THAN_OR_EQUAL;
+		} else if (expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
+			op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL;
+		} else if (expr.operator == BinaryOperator.EQUALITY) {
+			op = CCodeBinaryOperator.EQUALITY;
+		} else if (expr.operator == BinaryOperator.INEQUALITY) {
+			op = CCodeBinaryOperator.INEQUALITY;
+		} else if (expr.operator == BinaryOperator.BITWISE_AND) {
+			op = CCodeBinaryOperator.BITWISE_AND;
+		} else if (expr.operator == BinaryOperator.BITWISE_OR) {
+			op = CCodeBinaryOperator.BITWISE_OR;
+		} else if (expr.operator == BinaryOperator.BITWISE_XOR) {
+			op = CCodeBinaryOperator.BITWISE_XOR;
+		} else if (expr.operator == BinaryOperator.AND) {
+			op = CCodeBinaryOperator.AND;
+		} else if (expr.operator == BinaryOperator.OR) {
+			op = CCodeBinaryOperator.OR;
+		} else if (expr.operator == BinaryOperator.IN) {
+			var container_type = expr.right.value_type.data_type;
+			if (container_type != null && collection_type != null && map_type != null &&
+		           (container_type.is_subtype_of (collection_type) || container_type.is_subtype_of (map_type))) {
+				Method contains_method;
+				if (container_type.is_subtype_of (collection_type)) {
+					contains_method = (Method) collection_type.scope.lookup ("contains");
+					assert (contains_method != null);
+					var contains_ccall = new CCodeFunctionCall (new CCodeIdentifier (contains_method.get_cname ()));
+					contains_ccall.add_argument (new InstanceCast (cright, collection_type));
+					contains_ccall.add_argument (cleft);
+					expr.ccodenode = contains_ccall;
+				} else {
+					contains_method = (Method) map_type.scope.lookup ("contains");
+					assert (contains_method != null);
+					var contains_ccall = new CCodeFunctionCall (new CCodeIdentifier (contains_method.get_cname ()));
+					contains_ccall.add_argument (new InstanceCast (cright, map_type));
+					contains_ccall.add_argument (cleft);
+					expr.ccodenode = contains_ccall;
+				}
+				return;
+			}
+		
+			expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeParenthesizedExpression (new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeParenthesizedExpression (cright), new CCodeParenthesizedExpression (cleft))), new CCodeParenthesizedExpression (cleft));
+			return;
+		}
+		
+		if (expr.operator == BinaryOperator.EQUALITY ||
+		    expr.operator == BinaryOperator.INEQUALITY) {
+			var left_type_as_struct = expr.left.value_type.data_type as Struct;
+			var right_type_as_struct = expr.right.value_type.data_type as Struct;
+
+			if (expr.left.value_type.data_type is Class && !((Class) expr.left.value_type.data_type).is_compact &&
+			    expr.right.value_type.data_type is Class && !((Class) expr.right.value_type.data_type).is_compact) {
+				var left_cl = (Class) expr.left.value_type.data_type;
+				var right_cl = (Class) expr.right.value_type.data_type;
+				
+				if (left_cl != right_cl) {
+					if (left_cl.is_subtype_of (right_cl)) {
+						cleft = new InstanceCast (cleft, right_cl);
+					} else if (right_cl.is_subtype_of (left_cl)) {
+						cright = new InstanceCast (cright, left_cl);
+					}
+				}
+			} else if (left_type_as_struct != null && expr.right.value_type is NullType) {
+				cleft = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft);
+			} else if (right_type_as_struct != null && expr.left.value_type is NullType) {
+				cright = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cright);
+			}
+		}
+
+		if (!(expr.left.value_type is NullType)
+		    && expr.left.value_type.compatible (string_type)
+		    && !(expr.right.value_type is NullType)
+		    && expr.right.value_type.compatible (string_type)) {
+			if (expr.operator == BinaryOperator.PLUS) {
+				// string concatenation
+				if (expr.left.is_constant () && expr.right.is_constant ()) {
+					string left, right;
+
+					if (cleft is CCodeIdentifier) {
+						left = ((CCodeIdentifier) cleft).name;
+					} else if (cleft is CCodeConstant) {
+						left = ((CCodeConstant) cleft).name;
+					}
+					if (cright is CCodeIdentifier) {
+						right = ((CCodeIdentifier) cright).name;
+					} else if (cright is CCodeConstant) {
+						right = ((CCodeConstant) cright).name;
+					}
+
+					expr.ccodenode = new CCodeConstant ("%s %s".printf (left, right));
+					return;
+				} else {
+					// convert to g_strconcat (a, b, NULL)
+					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
+					ccall.add_argument (cleft);
+					ccall.add_argument (cright);
+					ccall.add_argument (new CCodeConstant("NULL"));
+					expr.ccodenode = ccall;
+					return;
+				}
+			} else if (expr.operator == BinaryOperator.EQUALITY
+			           || expr.operator == BinaryOperator.INEQUALITY
+			           || expr.operator == BinaryOperator.LESS_THAN
+			           || expr.operator == BinaryOperator.GREATER_THAN
+			           || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
+			           || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
+				requires_strcmp0 = true;
+				var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
+				ccall.add_argument (cleft);
+				ccall.add_argument (cright);
+				cleft = ccall;
+				cright = new CCodeConstant ("0");
+			}
+		}
+
+		expr.ccodenode = new CCodeBinaryExpression (op, cleft, cright);
+	}
+
+	public string get_type_check_function (TypeSymbol type) {
+		var cl = type as Class;
+		if (cl != null && cl.type_check_function != null) {
+			return cl.type_check_function;
+		} else {
+			return type.get_upper_case_cname ("IS_");
+		}
+	}
+
+	CCodeExpression create_type_check (CCodeNode ccodenode, DataType type) {
+		var et = type as ErrorType;
+		if (et != null && et.error_code != null) {
+			var matches_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches"));
+			matches_call.add_argument ((CCodeExpression) ccodenode);
+			matches_call.add_argument (new CCodeIdentifier (et.error_domain.get_upper_case_cname ()));
+			matches_call.add_argument (new CCodeIdentifier (et.error_code.get_cname ()));
+			return matches_call;
+		} else if (et != null && et.error_domain != null) {
+			var instance_domain = new CCodeMemberAccess.pointer ((CCodeExpression) ccodenode, "domain");
+			var type_domain = new CCodeIdentifier (et.error_domain.get_upper_case_cname ());
+			return new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, instance_domain, type_domain);
+		} else {
+			var ccheck = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (type.data_type)));
+			ccheck.add_argument ((CCodeExpression) ccodenode);
+			return ccheck;
+		}
+	}
+
+	public override void visit_type_check (TypeCheck expr) {
+		expr.ccodenode = create_type_check (expr.expression.ccodenode, expr.type_reference);
+	}
+
+	public override void visit_conditional_expression (ConditionalExpression expr) {
+		expr.ccodenode = new CCodeConditionalExpression ((CCodeExpression) expr.condition.ccodenode, (CCodeExpression) expr.true_expression.ccodenode, (CCodeExpression) expr.false_expression.ccodenode);
+	}
+
+	public override void visit_lambda_expression (LambdaExpression l) {
+		// use instance position from delegate
+		var dt = (DelegateType) l.target_type;
+		l.method.cinstance_parameter_position = dt.delegate_symbol.cinstance_parameter_position;
+
+		var old_temp_vars = temp_vars;
+		var old_temp_ref_vars = temp_ref_vars;
+		temp_vars = new ArrayList<LocalVariable> ();
+		temp_ref_vars = new ArrayList<LocalVariable> ();
+
+		l.accept_children (codegen);
+
+		temp_vars = old_temp_vars;
+		temp_ref_vars = old_temp_ref_vars;
+
+		l.ccodenode = new CCodeIdentifier (l.method.get_cname ());
+	}
+
+	public CCodeExpression convert_from_generic_pointer (CCodeExpression cexpr, DataType actual_type) {
+		var result = cexpr;
+		if (actual_type.data_type is Struct) {
+			var st = (Struct) actual_type.data_type;
+			if (st == uint_type.data_type) {
+				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_UINT"));
+				cconv.add_argument (cexpr);
+				result = cconv;
+			} else if (st == bool_type.data_type || st.is_integer_type ()) {
+				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_INT"));
+				cconv.add_argument (cexpr);
+				result = cconv;
+			}
+		} else if (actual_type.data_type != null && actual_type.data_type.is_reference_type ()) {
+			result = new CCodeCastExpression (cexpr, actual_type.get_cname ());
+		}
+		return result;
+	}
+
+	public CCodeExpression convert_to_generic_pointer (CCodeExpression cexpr, DataType actual_type) {
+		var result = cexpr;
+		if (actual_type.data_type is Struct) {
+			var st = (Struct) actual_type.data_type;
+			if (st == uint_type.data_type) {
+				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GUINT_TO_POINTER"));
+				cconv.add_argument (cexpr);
+				result = cconv;
+			} else if (st == bool_type.data_type || st.is_integer_type ()) {
+				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GINT_TO_POINTER"));
+				cconv.add_argument (cexpr);
+				result = cconv;
+			}
+		}
+		return result;
+	}
+
+	// manage memory and implicit casts
+	public CCodeExpression transform_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
+		var cexpr = source_cexpr;
+		if (expression_type == null) {
+			return cexpr;
+		}
+
+
+		if (expression_type.value_owned
+		    && expression_type.floating_reference) {
+			/* constructor of GInitiallyUnowned subtype
+			 * returns floating reference, sink it
+			 */
+			var csink = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref_sink"));
+			csink.add_argument (cexpr);
+			
+			cexpr = csink;
+		}
+
+		bool boxing = (expression_type is ValueType && !expression_type.nullable
+		               && target_type is ValueType && target_type.nullable);
+		bool unboxing = (expression_type is ValueType && expression_type.nullable
+		                 && target_type is ValueType && !target_type.nullable);
+
+		if (expression_type.value_owned
+		    && (target_type == null || !target_type.value_owned || boxing || unboxing)) {
+			// value leaked, destroy it
+			var pointer_type = target_type as PointerType;
+			if (pointer_type != null && !(pointer_type.base_type is VoidType)) {
+				// manual memory management for non-void pointers
+				// 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.insert (0, decl);
+				temp_ref_vars.insert (0, decl);
+				cexpr = new CCodeParenthesizedExpression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), cexpr));
+
+				if (expression_type is ArrayType && expr != null) {
+					var array_type = (ArrayType) expression_type;
+					var ccomma = new CCodeCommaExpression ();
+					ccomma.append_expression (cexpr);
+					for (int dim = 1; dim <= array_type.rank; dim++) {
+						var len_decl = new LocalVariable (int_type.copy (), head.get_array_length_cname (decl.name, dim));
+						temp_vars.insert (0, len_decl);
+						ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (len_decl.name)), head.get_array_length_cexpression (expr, dim)));
+					}
+					ccomma.append_expression (new CCodeIdentifier (get_variable_cname (decl.name)));
+					cexpr = ccomma;
+				}
+			}
+		}
+
+		if (target_type == null) {
+			// value will be destroyed, no need for implicit casts
+			return cexpr;
+		}
+
+		if (boxing) {
+			// value needs to be boxed
+
+			var unary = cexpr as CCodeUnaryExpression;
+			if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
+				// *expr => expr
+				cexpr = unary.inner;
+			} else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
+				cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
+			} else {
+				var decl = get_temp_variable (expression_type, expression_type.value_owned, expression_type);
+				temp_vars.insert (0, decl);
+
+				var ccomma = new CCodeCommaExpression ();
+				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), cexpr));
+				ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (get_variable_cname (decl.name))));
+				cexpr = ccomma;
+			}
+		} else if (unboxing) {
+			// unbox value
+
+			cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cexpr);
+		} else {
+			cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr);
+		}
+
+		if (expression_type.is_type_argument) {
+			cexpr = convert_from_generic_pointer (cexpr, target_type);
+		} else if (target_type.is_type_argument) {
+			cexpr = convert_to_generic_pointer (cexpr, expression_type);
+		}
+
+		if (target_type.value_owned && (!expression_type.value_owned || boxing || unboxing)) {
+			// need to copy value
+			if (requires_copy (target_type) && !(expression_type is NullType)) {
+				CodeNode node = expr;
+				if (node == null) {
+					node = expression_type;
+				}
+				cexpr = get_ref_cexpression (target_type, cexpr, expr, node);
+			}
+		}
+
+		return cexpr;
+	}
+
+	private CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
+		var cexpr = source_cexpr;
+
+		if (expression_type.data_type != null && expression_type.data_type == target_type.data_type) {
+			// same type, no cast required
+			return cexpr;
+		}
+
+		if (expression_type is NullType) {
+			// null literal, no cast required when not converting to generic type pointer
+			return cexpr;
+		}
+
+		var cl = target_type.data_type as Class;
+		var iface = target_type.data_type as Interface;
+		if (context.checking && (iface != null || (cl != null && !cl.is_compact))) {
+			// checked cast for strict subtypes of GTypeInstance
+			return new InstanceCast (cexpr, target_type.data_type);
+		} else if (target_type.data_type != null && expression_type.get_cname () != target_type.get_cname ()) {
+			var st = target_type.data_type as Struct;
+			if (target_type.data_type.is_reference_type () || (st != null && st.is_simple_type ())) {
+				// don't cast non-simple structs
+				return new CCodeCastExpression (cexpr, target_type.get_cname ());
+			} else {
+				return cexpr;
+			}
+		} else if (target_type is DelegateType && expression_type is MethodType) {
+			var dt = (DelegateType) target_type;
+			var mt = (MethodType) expression_type;
+
+			var method = mt.method_symbol;
+			if (method.base_method != null) {
+				method = method.base_method;
+			} else if (method.base_interface_method != null) {
+				method = method.base_interface_method;
+			}
+
+			return new CCodeIdentifier (generate_delegate_wrapper (method, dt.delegate_symbol));
+		} else {
+			return cexpr;
+		}
+	}
+
+	private string generate_delegate_wrapper (Method m, Delegate d) {
+		string delegate_name;
+		var sig = d.parent_symbol as Signal;
+		var dynamic_sig = sig as DynamicSignal;
+		if (dynamic_sig != null) {
+			delegate_name = head.get_dynamic_signal_cname (dynamic_sig);
+		} else if (sig != null) {
+			delegate_name = sig.parent_symbol.get_lower_case_cprefix () + sig.get_cname ();
+		} else {
+			delegate_name = Symbol.camel_case_to_lower_case (d.get_cname ());
+		}
+
+		string wrapper_name = "_%s_%s".printf (m.get_cname (), delegate_name);
+
+		if (!add_wrapper (wrapper_name)) {
+			// wrapper already defined
+			return wrapper_name;
+		}
+
+		// declaration
+
+		var function = new CCodeFunction (wrapper_name, m.return_type.get_cname ());
+		function.modifiers = CCodeModifiers.STATIC;
+		m.ccodenode = function;
+
+		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
+
+		if (d.has_target) {
+			var cparam = new CCodeFormalParameter ("self", "gpointer");
+			cparam_map.set (get_param_pos (d.cinstance_parameter_position), cparam);
+		}
+
+		var d_params = d.get_parameters ();
+		foreach (FormalParameter param in d_params) {
+			// ensure that C code node has been generated
+			param.accept (codegen);
+
+			cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
+
+			// handle array parameters
+			if (!param.no_array_length && param.parameter_type is ArrayType) {
+				var array_type = (ArrayType) param.parameter_type;
+				
+				var length_ctype = "int";
+				if (param.direction != ParameterDirection.IN) {
+					length_ctype = "int*";
+				}
+				
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
+					cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
+				}
+			}
+
+		}
+
+		if (m.get_error_types ().size > 0) {
+			var cparam = new CCodeFormalParameter ("error", "GError**");
+			cparam_map.set (get_param_pos (-1), cparam);
+		}
+
+		// append C parameters in the right order
+		int last_pos = -1;
+		int min_pos;
+		while (true) {
+			min_pos = -1;
+			foreach (int pos in cparam_map.get_keys ()) {
+				if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+					min_pos = pos;
+				}
+			}
+			if (min_pos == -1) {
+				break;
+			}
+			function.add_parameter (cparam_map.get (min_pos));
+			last_pos = min_pos;
+		}
+
+
+		// definition
+
+		var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
+
+		int i = 0;
+		if (m.binding == MemberBinding.INSTANCE) {
+			CCodeExpression arg;
+			if (d.has_target) {
+				arg = new CCodeIdentifier ("self");
+			} else {
+				// use first delegate parameter as instance
+				arg = new CCodeIdentifier ((d_params.get (0).ccodenode as CCodeFormalParameter).name);
+				i = 1;
+			}
+			carg_map.set (get_param_pos (m.cinstance_parameter_position), arg);
+		}
+
+		foreach (FormalParameter param in m.get_parameters ()) {
+			CCodeExpression arg;
+			arg = new CCodeIdentifier ((d_params.get (i).ccodenode as CCodeFormalParameter).name);
+			carg_map.set (get_param_pos (param.cparameter_position), arg);
+
+			// handle array arguments
+			if (!param.no_array_length && param.parameter_type is ArrayType) {
+				var array_type = (ArrayType) param.parameter_type;
+				for (int dim = 1; dim <= array_type.rank; dim++) {
+					CCodeExpression clength;
+					if (d_params.get (i).no_array_length) {
+						clength = new CCodeConstant ("-1");
+					} else {
+						clength = new CCodeIdentifier (head.get_array_length_cname (d_params.get (i).name, dim));
+					}
+					carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), clength);
+				}
+			}
+
+			i++;
+		}
+
+		if (m.get_error_types ().size > 0) {
+			carg_map.set (get_param_pos (-1), new CCodeIdentifier ("error"));
+		}
+
+		var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
+
+		// append C arguments in the right order
+		last_pos = -1;
+		while (true) {
+			min_pos = -1;
+			foreach (int pos in carg_map.get_keys ()) {
+				if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
+					min_pos = pos;
+				}
+			}
+			if (min_pos == -1) {
+				break;
+			}
+			ccall.add_argument (carg_map.get (min_pos));
+			last_pos = min_pos;
+		}
+
+		var block = new CCodeBlock ();
+		if (m.return_type is VoidType) {
+			block.add_statement (new CCodeExpressionStatement (ccall));
+		} else {
+			block.add_statement (new CCodeReturnStatement (ccall));
+		}
+
+		// append to file
+
+		source_type_member_declaration.append (function.copy ());
+
+		function.block = block;
+		source_type_member_definition.append (function);
+
+		return wrapper_name;
+	}
+
+	public CCodeFunctionCall get_property_set_call (Property prop, MemberAccess ma, CCodeExpression cexpr) {
+		if (ma.inner is BaseAccess) {
+			if (prop.base_property != null) {
+				var base_class = (Class) prop.base_property.parent_symbol;
+				var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
+				vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
+				
+				var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name)));
+				ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
+				ccall.add_argument (cexpr);
+				return ccall;
+			} else if (prop.base_interface_property != null) {
+				var base_iface = (Interface) prop.base_interface_property.parent_symbol;
+				string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
+
+				var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), "set_%s".printf (prop.name)));
+				ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
+				ccall.add_argument (cexpr);
+				return ccall;
+			}
+		}
+
+		var set_func = "g_object_set";
+		
+		var base_property = prop;
+		if (!prop.no_accessor_method) {
+			if (prop.base_property != null) {
+				base_property = prop.base_property;
+			} else if (prop.base_interface_property != null) {
+				base_property = prop.base_interface_property;
+			}
+			var base_property_type = (TypeSymbol) base_property.parent_symbol;
+			set_func = "%s_set_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name);
+			if (prop is DynamicProperty) {
+				set_func = head.get_dynamic_property_setter_cname ((DynamicProperty) prop);
+			}
+		}
+		
+		var ccall = new CCodeFunctionCall (new CCodeIdentifier (set_func));
+
+		if (prop.binding == MemberBinding.INSTANCE) {
+			/* target instance is first argument */
+			ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
+		}
+
+		if (prop.no_accessor_method) {
+			/* property name is second argument of g_object_set */
+			ccall.add_argument (prop.get_canonical_cconstant ());
+		}
+			
+		ccall.add_argument (cexpr);
+		
+		if (prop.no_accessor_method) {
+			ccall.add_argument (new CCodeConstant ("NULL"));
+		}
+
+		return ccall;
+	}
+
+	/* indicates whether a given Expression eligable for an ADDRESS_OF operator
+	 * from a vala to C point of view all expressions denoting locals, fields and
+	 * parameters are eligable to an ADDRESS_OF operator */
+	public bool is_address_of_possible (Expression e) {
+		var ma = e as MemberAccess;
+
+		if (ma == null) {
+			return false;
+		}
+		if (ma.symbol_reference == null) {
+			return false;
+		}
+		if (ma.symbol_reference is FormalParameter) {
+			return true;
+		}
+		if (ma.symbol_reference is LocalVariable) {
+			return true;
+		}
+		if (ma.symbol_reference is Field) {
+			return true;
+		}
+		return false;
+	}
+
+	/* retrieve the correct address_of expression for a give expression, creates temporary variables
+	 * where necessary, ce is the corresponding ccode expression for e */
+	public CCodeExpression get_address_of_expression (Expression e, CCodeExpression ce) {
+		// is address of trivially possible?
+		if (is_address_of_possible (e)) {
+			return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ce);
+		}
+
+		var ccomma = new CCodeCommaExpression ();
+		var temp_decl = get_temp_variable (e.value_type);
+		var ctemp = new CCodeIdentifier (temp_decl.name);
+		temp_vars.add (temp_decl);
+		ccomma.append_expression (new CCodeAssignment (ctemp, ce));
+		ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
+		return ccomma;
+	}
+
+	public bool add_wrapper (string wrapper_name) {
+		return wrappers.add (wrapper_name);
+	}
+
+	public static DataType get_data_type_for_symbol (TypeSymbol sym) {
+		DataType type = null;
+
+		if (sym is Class) {
+			type = new ObjectType ((Class) sym);
+		} else if (sym is Interface) {
+			type = new ObjectType ((Interface) sym);
+		} else if (sym is Struct) {
+			type = new ValueType ((Struct) sym);
+		} else if (sym is Enum) {
+			type = new ValueType ((Enum) sym);
+		} else if (sym is ErrorDomain) {
+			type = new ErrorType ((ErrorDomain) sym, null);
+		} else if (sym is ErrorCode) {
+			type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym);
+		} else {
+			Report.error (null, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
+			return new InvalidType ();
+		}
+
+		return type;
+	}
+
+	public CCodeExpression? default_value_for_type (DataType type, bool initializer_expression) {
+		if ((type.data_type != null && type.data_type.is_reference_type ()) || type is PointerType || type is ArrayType) {
+			return new CCodeConstant ("NULL");
+		} else if (type.data_type != null && type.data_type.get_default_value () != null) {
+			return new CCodeConstant (type.data_type.get_default_value ());
+		} else if (type.data_type is Struct && initializer_expression) {
+			// 0-initialize struct with struct initializer { 0 }
+			// only allowed as initializer expression in C
+			var clist = new CCodeInitializerList ();
+			clist.append (new CCodeConstant ("0"));
+			return clist;
+		} else if (type.type_parameter != null) {
+			return new CCodeConstant ("NULL");
+		} else if (type is ErrorType) {
+			return new CCodeConstant ("NULL");
+		}
+		return null;
+	}
+	
+	private CCodeStatement create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) {
+		if (check_return_type) {
+			return create_type_check_statement (prop, prop.property_type, t, non_null, var_name);
+		} else {
+			return create_type_check_statement (prop, new VoidType (), t, non_null, var_name);
+		}
+	}
+
+	public CCodeStatement? create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
+		var ccheck = new CCodeFunctionCall ();
+		
+		if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
+			var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (t)));
+			ctype_check.add_argument (new CCodeIdentifier (var_name));
+			
+			CCodeExpression cexpr = ctype_check;
+			if (!non_null) {
+				var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
+			
+				cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
+			}
+			ccheck.add_argument (cexpr);
+		} else if (!non_null) {
+			return null;
+		} else {
+			var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
+			ccheck.add_argument (cnonnull);
+		}
+		
+		if (ret_type is VoidType) {
+			/* void function */
+			ccheck.call = new CCodeIdentifier ("g_return_if_fail");
+		} else {
+			ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
+
+			var cdefault = default_value_for_type (ret_type, false);
+			if (cdefault != null) {
+				ccheck.add_argument (cdefault);
+			} else {
+				return new CCodeExpressionStatement (new CCodeConstant ("0"));
+			}
+		}
+		
+		return new CCodeExpressionStatement (ccheck);
+	}
+
+	public int get_param_pos (double param_pos, bool ellipsis = false) {
+		if (!ellipsis) {
+			if (param_pos >= 0) {
+				return (int) (param_pos * 1000);
+			} else {
+				return (int) ((100 + param_pos) * 1000);
+			}
+		} else {
+			if (param_pos >= 0) {
+				return (int) ((100 + param_pos) * 1000);
+			} else {
+				return (int) ((200 + param_pos) * 1000);
+			}
+		}
+	}
+
+	public bool dbus_use_ptr_array (ArrayType array_type) {
+		if (array_type.element_type.data_type == string_type.data_type) {
+			// use char**
+			return false;
+		} else if (array_type.element_type.data_type == bool_type.data_type
+		           || array_type.element_type.data_type == char_type.data_type
+		           || array_type.element_type.data_type == uchar_type.data_type
+		           || array_type.element_type.data_type == int_type.data_type
+		           || array_type.element_type.data_type == uint_type.data_type
+		           || array_type.element_type.data_type == long_type.data_type
+		           || array_type.element_type.data_type == ulong_type.data_type
+		           || array_type.element_type.data_type == int8_type.data_type
+		           || array_type.element_type.data_type == uint8_type.data_type
+		           || array_type.element_type.data_type == int32_type.data_type
+		           || array_type.element_type.data_type == uint32_type.data_type
+		           || array_type.element_type.data_type == int64_type.data_type
+		           || array_type.element_type.data_type == uint64_type.data_type
+		           || array_type.element_type.data_type == double_type.data_type) {
+			// use GArray
+			return false;
+		} else {
+			// use GPtrArray
+			return true;
+		}
+	}
+
+	public CCodeNode? get_ccodenode (CodeNode node) {
+		if (node.ccodenode == null) {
+			node.accept (codegen);
+		}
+		return node.ccodenode;
+	}
 }

Modified: trunk/gobject/valaccodedynamicpropertymodule.vala
==============================================================================
--- trunk/gobject/valaccodedynamicpropertymodule.vala	(original)
+++ trunk/gobject/valaccodedynamicpropertymodule.vala	Mon Nov  3 20:50:43 2008
@@ -44,20 +44,20 @@
 		func.add_parameter (new CCodeFormalParameter ("obj", dynamic_property.dynamic_type.get_cname ()));
 
 		var block = new CCodeBlock ();
-		if (dynamic_property.dynamic_type.data_type == codegen.dbus_object_type) {
+		if (dynamic_property.dynamic_type.data_type == dbus_object_type) {
 			generate_dbus_property_getter_wrapper (node, block);
 		} else if (dynamic_property.dynamic_type.data_type != null
-		           && dynamic_property.dynamic_type.data_type.is_subtype_of (codegen.gobject_type)) {
+		           && dynamic_property.dynamic_type.data_type.is_subtype_of (gobject_type)) {
 			generate_gobject_property_getter_wrapper (node, block);
 		} else {
 			Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.dynamic_type.to_string ()));
 		}
 
 		// append to C source file
-		codegen.source_type_member_declaration.append (func.copy ());
+		source_type_member_declaration.append (func.copy ());
 
 		func.block = block;
-		codegen.source_type_member_definition.append (func);
+		source_type_member_definition.append (func);
 
 		return getter_cname;
 	}
@@ -74,20 +74,20 @@
 		func.add_parameter (new CCodeFormalParameter ("value", node.property_type.get_cname ()));
 
 		var block = new CCodeBlock ();
-		if (dynamic_property.dynamic_type.data_type == codegen.dbus_object_type) {
+		if (dynamic_property.dynamic_type.data_type == dbus_object_type) {
 			generate_dbus_property_setter_wrapper (node, block);
 		} else if (dynamic_property.dynamic_type.data_type != null
-		           && dynamic_property.dynamic_type.data_type.is_subtype_of (codegen.gobject_type)) {
+		           && dynamic_property.dynamic_type.data_type.is_subtype_of (gobject_type)) {
 			generate_gobject_property_setter_wrapper (node, block);
 		} else {
 			Report.error (node.source_reference, "dynamic properties are not supported for `%s'".printf (dynamic_property.dynamic_type.to_string ()));
 		}
 
 		// append to C source file
-		codegen.source_type_member_declaration.append (func.copy ());
+		source_type_member_declaration.append (func.copy ());
 
 		func.block = block;
-		codegen.source_type_member_definition.append (func);
+		source_type_member_definition.append (func);
 
 		return setter_cname;
 	}

Modified: trunk/gobject/valaccodedynamicsignalmodule.vala
==============================================================================
--- trunk/gobject/valaccodedynamicsignalmodule.vala	(original)
+++ trunk/gobject/valaccodedynamicsignalmodule.vala	Mon Nov  3 20:50:43 2008
@@ -47,20 +47,20 @@
 		func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
 		func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
 		var block = new CCodeBlock ();
-		if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) {
+		if (dynamic_signal.dynamic_type.data_type == dbus_object_type) {
 			generate_dbus_connect_wrapper (node, block);
 		} else if (dynamic_signal.dynamic_type.data_type != null
-		           && dynamic_signal.dynamic_type.data_type.is_subtype_of (codegen.gobject_type)) {
+		           && dynamic_signal.dynamic_type.data_type.is_subtype_of (gobject_type)) {
 			generate_gobject_connect_wrapper (node, block);
 		} else {
 			Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
 		}
 
 		// append to C source file
-		codegen.source_type_member_declaration.append (func.copy ());
+		source_type_member_declaration.append (func.copy ());
 
 		func.block = block;
-		codegen.source_type_member_definition.append (func);
+		source_type_member_definition.append (func);
 
 		return connect_wrapper_name;
 	}
@@ -75,17 +75,17 @@
 		func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
 		func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
 		var block = new CCodeBlock ();
-		if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) {
+		if (dynamic_signal.dynamic_type.data_type == dbus_object_type) {
 			generate_dbus_disconnect_wrapper (node, block);
 		} else {
 			Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
 		}
 
 		// append to C source file
-		codegen.source_type_member_declaration.append (func.copy ());
+		source_type_member_declaration.append (func.copy ());
 
 		func.block = block;
-		codegen.source_type_member_definition.append (func);
+		source_type_member_definition.append (func);
 
 		return disconnect_wrapper_name;
 	}
@@ -142,7 +142,7 @@
 
 			var array_type = param.parameter_type as ArrayType;
 			if (array_type != null) {
-				if (array_type.element_type.data_type == codegen.string_type.data_type) {
+				if (array_type.element_type.data_type == string_type.data_type) {
 					register_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
 					add_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
 				} else {

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Mon Nov  3 20:50:43 2008
@@ -30,118 +30,6 @@
 public class Vala.CCodeGenerator : CodeGenerator {
 	public CCodeModule head;
 
-	public CodeContext context;
-	
-	public Symbol root_symbol;
-	public Symbol current_symbol;
-	public TypeSymbol current_type_symbol;
-	public Class current_class;
-	public Method current_method;
-	public DataType current_return_type;
-	public TryStatement current_try;
-	public PropertyAccessor current_property_accessor;
-
-	public CCodeFragment header_begin;
-	public CCodeFragment header_type_declaration;
-	public CCodeFragment header_type_definition;
-	public CCodeFragment header_type_member_declaration;
-	public CCodeFragment header_constant_declaration;
-	public CCodeFragment source_begin;
-	public CCodeFragment source_include_directives;
-	public CCodeFragment source_type_declaration;
-	public CCodeFragment source_type_definition;
-	public CCodeFragment source_type_member_declaration;
-	public CCodeFragment source_constant_declaration;
-	public CCodeFragment source_signal_marshaller_declaration;
-	public CCodeFragment source_type_member_definition;
-	public CCodeFragment class_init_fragment;
-	public CCodeFragment instance_init_fragment;
-	public CCodeFragment instance_finalize_fragment;
-	public CCodeFragment source_signal_marshaller_definition;
-	public CCodeFragment module_init_fragment;
-	
-	public CCodeStruct param_spec_struct;
-	public CCodeStruct instance_struct;
-	public CCodeStruct type_struct;
-	public CCodeStruct instance_priv_struct;
-	public CCodeEnum prop_enum;
-	public CCodeEnum cenum;
-	public CCodeFunction function;
-	public CCodeBlock block;
-	
-	/* all temporary variables */
-	public ArrayList<LocalVariable> temp_vars = new ArrayList<LocalVariable> ();
-	/* temporary variables that own their content */
-	public ArrayList<LocalVariable> temp_ref_vars = new ArrayList<LocalVariable> ();
-	/* cache to check whether a certain marshaller has been created yet */
-	public Gee.Set<string> user_marshal_set;
-	/* (constant) hash table with all predefined marshallers */
-	public Gee.Set<string> predefined_marshal_set;
-	/* (constant) hash table with all C keywords */
-	public Gee.Set<string> c_keywords;
-	
-	public int next_temp_var_id = 0;
-	private int current_try_id = 0;
-	private int next_try_id = 0;
-	private int next_array_dup_id = 0;
-	public bool in_creation_method = false;
-	private bool in_constructor = false;
-	public bool in_static_or_class_ctor = false;
-	public bool current_method_inner_error = false;
-	int next_coroutine_state = 1;
-
-	public DataType bool_type;
-	public DataType char_type;
-	public DataType uchar_type;
-	public DataType unichar_type;
-	public DataType short_type;
-	public DataType ushort_type;
-	public DataType int_type;
-	public DataType uint_type;
-	public DataType long_type;
-	public DataType ulong_type;
-	public DataType int8_type;
-	public DataType uint8_type;
-	public DataType int32_type;
-	public DataType uint32_type;
-	public DataType int64_type;
-	public DataType uint64_type;
-	public DataType string_type;
-	public DataType float_type;
-	public DataType double_type;
-	public TypeSymbol gtype_type;
-	public TypeSymbol gobject_type;
-	public ErrorType gerror_type;
-	public Class glist_type;
-	public Class gslist_type;
-	public TypeSymbol gstringbuilder_type;
-	public TypeSymbol garray_type;
-	public DataType gquark_type;
-	public Struct mutex_type;
-	public TypeSymbol type_module_type;
-	public Interface iterable_type;
-	public Interface iterator_type;
-	public Interface collection_type;
-	public Interface list_type;
-	public Interface map_type;
-	public TypeSymbol dbus_object_type;
-
-	public Method substring_method;
-
-	public bool in_plugin = false;
-	public string module_init_param_name;
-	
-	public bool string_h_needed;
-	public bool gvaluecollector_h_needed;
-	public bool gio_h_needed;
-	public bool requires_free_checked;
-	public bool requires_array_free;
-	public bool requires_array_move;
-	public bool requires_strcmp0;
-	public bool dbus_glib_h_needed;
-
-	public Set<string> wrappers;
-
 	public CCodeGenerator () {
 		/* included by inheritance
 		head = new CCodeBaseModule (this, head);
@@ -161,149 +49,10 @@
 		head = new DBusClientModule (this, head);
 		*/
 		head = new DBusServerModule (this, head);
-
-		predefined_marshal_set = new HashSet<string> (str_hash, str_equal);
-		predefined_marshal_set.add ("VOID:VOID");
-		predefined_marshal_set.add ("VOID:BOOLEAN");
-		predefined_marshal_set.add ("VOID:CHAR");
-		predefined_marshal_set.add ("VOID:UCHAR");
-		predefined_marshal_set.add ("VOID:INT");
-		predefined_marshal_set.add ("VOID:UINT");
-		predefined_marshal_set.add ("VOID:LONG");
-		predefined_marshal_set.add ("VOID:ULONG");
-		predefined_marshal_set.add ("VOID:ENUM");
-		predefined_marshal_set.add ("VOID:FLAGS");
-		predefined_marshal_set.add ("VOID:FLOAT");
-		predefined_marshal_set.add ("VOID:DOUBLE");
-		predefined_marshal_set.add ("VOID:STRING");
-		predefined_marshal_set.add ("VOID:POINTER");
-		predefined_marshal_set.add ("VOID:OBJECT");
-		predefined_marshal_set.add ("STRING:OBJECT,POINTER");
-		predefined_marshal_set.add ("VOID:UINT,POINTER");
-		predefined_marshal_set.add ("BOOLEAN:FLAGS");
-
-		c_keywords = new HashSet<string> (str_hash, str_equal);
-
-		// C99 keywords
-		c_keywords.add ("_Bool");
-		c_keywords.add ("_Complex");
-		c_keywords.add ("_Imaginary");
-		c_keywords.add ("auto");
-		c_keywords.add ("break");
-		c_keywords.add ("case");
-		c_keywords.add ("char");
-		c_keywords.add ("const");
-		c_keywords.add ("continue");
-		c_keywords.add ("default");
-		c_keywords.add ("do");
-		c_keywords.add ("double");
-		c_keywords.add ("else");
-		c_keywords.add ("enum");
-		c_keywords.add ("extern");
-		c_keywords.add ("float");
-		c_keywords.add ("for");
-		c_keywords.add ("goto");
-		c_keywords.add ("if");
-		c_keywords.add ("inline");
-		c_keywords.add ("int");
-		c_keywords.add ("long");
-		c_keywords.add ("register");
-		c_keywords.add ("restrict");
-		c_keywords.add ("return");
-		c_keywords.add ("short");
-		c_keywords.add ("signed");
-		c_keywords.add ("sizeof");
-		c_keywords.add ("static");
-		c_keywords.add ("struct");
-		c_keywords.add ("switch");
-		c_keywords.add ("typedef");
-		c_keywords.add ("union");
-		c_keywords.add ("unsigned");
-		c_keywords.add ("void");
-		c_keywords.add ("volatile");
-		c_keywords.add ("while");
-
-		// MSVC keywords
-		c_keywords.add ("cdecl");
 	}
 
 	public override void emit (CodeContext context) {
-		this.head.emit (context);
-
-		this.context = context;
-	
-		context.find_header_cycles ();
-
-		root_symbol = context.root;
-
-		bool_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("bool"));
-		char_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("char"));
-		uchar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uchar"));
-		unichar_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("unichar"));
-		short_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("short"));
-		ushort_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ushort"));
-		int_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int"));
-		uint_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint"));
-		long_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("long"));
-		ulong_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("ulong"));
-		int8_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int8"));
-		uint8_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint8"));
-		int32_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int32"));
-		uint32_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint32"));
-		int64_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("int64"));
-		uint64_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("uint64"));
-		float_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("float"));
-		double_type = new ValueType ((TypeSymbol) root_symbol.scope.lookup ("double"));
-		string_type = new ObjectType ((Class) root_symbol.scope.lookup ("string"));
-		substring_method = (Method) string_type.data_type.scope.lookup ("substring");
-
-		var glib_ns = root_symbol.scope.lookup ("GLib");
-
-		gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
-		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
-		gerror_type = new ErrorType (null, null);
-		glist_type = (Class) glib_ns.scope.lookup ("List");
-		gslist_type = (Class) glib_ns.scope.lookup ("SList");
-		gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
-		garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
-
-		gquark_type = new ValueType ((TypeSymbol) glib_ns.scope.lookup ("Quark"));
-		mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
-		
-		type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
-
-		if (context.module_init_method != null) {
-			module_init_fragment = new CCodeFragment ();
-			foreach (FormalParameter parameter in context.module_init_method.get_parameters ()) {
-				if (parameter.parameter_type.data_type == type_module_type) {
-					in_plugin = true;
-					module_init_param_name = parameter.name;
-					break;
-				}
-			}
-		}
-
-		var gee_ns = root_symbol.scope.lookup ("Gee");
-		if (gee_ns != null) {
-			iterable_type = (Interface) gee_ns.scope.lookup ("Iterable");
-			iterator_type = (Interface) gee_ns.scope.lookup ("Iterator");
-			collection_type = (Interface) gee_ns.scope.lookup ("Collection");
-			list_type = (Interface) gee_ns.scope.lookup ("List");
-			map_type = (Interface) gee_ns.scope.lookup ("Map");
-		}
-
-		var dbus_ns = root_symbol.scope.lookup ("DBus");
-		if (dbus_ns != null) {
-			dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
-		}
-	
-		/* we're only interested in non-pkg source files */
-		var source_files = context.get_source_files ();
-		foreach (SourceFile file in source_files) {
-			if (!file.external_package) {
-				file.accept (this);
-			}
-		}
+		head.emit (context);
 	}
 
 	public override void visit_source_file (SourceFile source_file) {
@@ -323,448 +72,35 @@
 	}
 
 	public override void visit_enum (Enum en) {
-		cenum = new CCodeEnum (en.get_cname ());
-
-		CCodeFragment decl_frag;
-		CCodeFragment def_frag;
-		if (en.access != SymbolAccessibility.PRIVATE) {
-			decl_frag = header_type_declaration;
-			def_frag = header_type_definition;
-		} else {
-			decl_frag = source_type_declaration;
-			def_frag = source_type_definition;
-		}
-		
-		if (en.source_reference.comment != null) {
-			def_frag.append (new CCodeComment (en.source_reference.comment));
-		}
-
-		def_frag.append (cenum);
-		def_frag.append (new CCodeNewline ());
-
-		en.accept_children (this);
-
-		if (!en.has_type_id) {
-			return;
-		}
-
-		decl_frag.append (new CCodeNewline ());
-
-		var macro = "(%s_get_type ())".printf (en.get_lower_case_cname (null));
-		decl_frag.append (new CCodeMacroReplacement (en.get_type_id (), macro));
-
-		var clist = new CCodeInitializerList (); /* or during visit time? */
-		CCodeInitializerList clist_ev = null;
-		foreach (EnumValue ev in en.get_values ()) {
-			clist_ev = new CCodeInitializerList ();
-			clist_ev.append (new CCodeConstant (ev.get_cname ()));
-			clist_ev.append (new CCodeIdentifier ("\"%s\"".printf (ev.get_cname ())));
-			clist_ev.append (ev.get_canonical_cconstant ());
-			clist.append (clist_ev);
-		}
-
-		clist_ev = new CCodeInitializerList ();
-		clist_ev.append (new CCodeConstant ("0"));
-		clist_ev.append (new CCodeConstant ("NULL"));
-		clist_ev.append (new CCodeConstant ("NULL"));
-		clist.append (clist_ev);
-
-		var enum_decl = new CCodeVariableDeclarator.with_initializer ("values[]", clist);
-
-		CCodeDeclaration cdecl = null;
-		if (en.is_flags) {
-			cdecl = new CCodeDeclaration ("const GFlagsValue");
-		} else {
-			cdecl = new CCodeDeclaration ("const GEnumValue");
-		}
-
-		cdecl.add_declarator (enum_decl);
-		cdecl.modifiers = CCodeModifiers.STATIC;
-
-		var type_init = new CCodeBlock ();
-
-		type_init.add_statement (cdecl);
-
-		var fun_name = "%s_get_type".printf (en.get_lower_case_cname (null));
-		var regfun = new CCodeFunction (fun_name, "GType");
-		var regblock = new CCodeBlock ();
-
-		cdecl = new CCodeDeclaration ("GType");
-		string type_id_name = "%s_type_id".printf (en.get_lower_case_cname (null));
-		cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (type_id_name, new CCodeConstant ("0")));
-		cdecl.modifiers = CCodeModifiers.STATIC;
-		regblock.add_statement (cdecl);
-
-		CCodeFunctionCall reg_call;
-		if (en.is_flags) {
-			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_flags_register_static"));
-		} else {
-			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_enum_register_static"));
-		}
-
-		reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (en.get_cname())));
-		reg_call.add_argument (new CCodeIdentifier ("values"));
-
-		type_init.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier (type_id_name), reg_call)));
-
-		var cond = new CCodeFunctionCall (new CCodeIdentifier ("G_UNLIKELY"));
-		cond.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (type_id_name), new CCodeConstant ("0")));
-		var cif = new CCodeIfStatement (cond, type_init);
-		regblock.add_statement (cif);
-
-		regblock.add_statement (new CCodeReturnStatement (new CCodeConstant (type_id_name)));
-
-		if (en.access != SymbolAccessibility.PRIVATE) {
-			header_type_member_declaration.append (regfun.copy ());
-		} else {
-			source_type_member_declaration.append (regfun.copy ());
-		}
-		regfun.block = regblock;
-
-		source_type_member_definition.append (new CCodeNewline ());
-		source_type_member_definition.append (regfun);
+		head.visit_enum (en);
 	}
 
 	public override void visit_enum_value (EnumValue ev) {
-		if (ev.value == null) {
-			cenum.add_value (new CCodeEnumValue (ev.get_cname ()));
-		} else {
-			ev.value.accept (this);
-			cenum.add_value (new CCodeEnumValue (ev.get_cname (), (CCodeExpression) ev.value.ccodenode));
-		}
+		head.visit_enum_value (ev);
 	}
 
 	public override void visit_error_domain (ErrorDomain edomain) {
-		cenum = new CCodeEnum (edomain.get_cname ());
-
-		if (edomain.source_reference.comment != null) {
-			header_type_definition.append (new CCodeComment (edomain.source_reference.comment));
-		}
-		header_type_definition.append (cenum);
-
-		edomain.accept_children (this);
-
-		string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
-
-		var error_domain_define = new CCodeMacroReplacement (edomain.get_upper_case_cname (), quark_fun_name + " ()");
-		header_type_definition.append (error_domain_define);
-
-		var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
-		var cquark_block = new CCodeBlock ();
-
-		var cquark_call = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
-		cquark_call.add_argument (new CCodeConstant ("\"" + edomain.get_lower_case_cname () + "-quark\""));
-
-		cquark_block.add_statement (new CCodeReturnStatement (cquark_call));
-
-		header_type_member_declaration.append (cquark_fun.copy ());
-
-		cquark_fun.block = cquark_block;
-		source_type_member_definition.append (cquark_fun);
+		head.visit_error_domain (edomain);
 	}
 
 	public override void visit_error_code (ErrorCode ecode) {
-		if (ecode.value == null) {
-			cenum.add_value (new CCodeEnumValue (ecode.get_cname ()));
-		} else {
-			ecode.value.accept (this);
-			cenum.add_value (new CCodeEnumValue (ecode.get_cname (), (CCodeExpression) ecode.value.ccodenode));
-		}
+		head.visit_error_code (ecode);
 	}
 
 	public override void visit_delegate (Delegate d) {
-		d.accept_children (this);
-
-		var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
-		foreach (FormalParameter param in d.get_parameters ()) {
-			cfundecl.add_parameter ((CCodeFormalParameter) param.ccodenode);
-
-			// handle array parameters
-			if (!param.no_array_length && param.parameter_type is ArrayType) {
-				var array_type = (ArrayType) param.parameter_type;
-				
-				var length_ctype = "int";
-				if (param.direction != ParameterDirection.IN) {
-					length_ctype = "int*";
-				}
-				
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
-					cfundecl.add_parameter (cparam);
-				}
-			}
-		}
-		if (d.has_target) {
-			var cparam = new CCodeFormalParameter ("user_data", "void*");
-			cfundecl.add_parameter (cparam);
-		}
-
-		var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
-
-		if (!d.is_internal_symbol ()) {
-			header_type_declaration.append (ctypedef);
-		} else {
-			source_type_declaration.append (ctypedef);
-		}
+		head.visit_delegate (d);
 	}
 	
 	public override void visit_member (Member m) {
-		/* stuff meant for all lockable members */
-		if (m is Lockable && ((Lockable)m).get_lock_used ()) {
-			CCodeExpression l = new CCodeIdentifier ("self");
-			l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (m));	
-
-			instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (m));
-
-			var initf = new CCodeFunctionCall (
-				new CCodeIdentifier (mutex_type.default_construction_method.get_cname ()));
-
-			initf.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));		
-
-			instance_init_fragment.append (new CCodeExpressionStatement (initf));
-		
-			requires_free_checked = true;
-
-
-			var fc = new CCodeFunctionCall (new CCodeIdentifier ("g_static_rec_mutex_free"));
-
-			fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-
-			if (instance_finalize_fragment != null) {
-				instance_finalize_fragment.append (new CCodeExpressionStatement (fc));
-			}
-		}
+		head.visit_member (m);
 	}
 
 	public override void visit_constant (Constant c) {
-		c.accept_children (this);
-
-		if (!(c.type_reference is ArrayType)) {
-			var cdefine = new CCodeMacroReplacement.with_expression (c.get_cname (), (CCodeExpression) c.initializer.ccodenode);
-			if (!c.is_internal_symbol ()) {
-				header_type_member_declaration.append (cdefine);
-			} else {
-				source_type_member_declaration.append (cdefine);
-			}
-		} else {
-			var cdecl = new CCodeDeclaration (c.type_reference.get_const_cname ());
-			var arr = "";
-			if (c.type_reference is ArrayType) {
-				arr = "[]";
-			}
-			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("%s%s".printf (c.get_cname (), arr), (CCodeExpression) c.initializer.ccodenode));
-			cdecl.modifiers = CCodeModifiers.STATIC;
-		
-			if (!c.is_internal_symbol ()) {
-				header_constant_declaration.append (cdecl);
-			} else {
-				source_constant_declaration.append (cdecl);
-			}
-		}
+		head.visit_constant (c);
 	}
 
 	public override void visit_field (Field f) {
-		f.accept_children (this);
-
-		var cl = f.parent_symbol as Class;
-		bool is_gtypeinstance = (cl != null && !cl.is_compact);
-
-		CCodeExpression lhs = null;
-		CCodeStruct st = null;
-		
-		string field_ctype = f.field_type.get_cname ();
-		if (f.is_volatile) {
-			field_ctype = "volatile " + field_ctype;
-		}
-
-		if (f.access != SymbolAccessibility.PRIVATE) {
-			if (f.binding == MemberBinding.INSTANCE) {
-				st = instance_struct;
-
-				lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
-			} else if (f.binding == MemberBinding.CLASS) {
-				st = type_struct;
-			} else {
-				var cdecl = new CCodeDeclaration (field_ctype);
-				cdecl.add_declarator (new CCodeVariableDeclarator (f.get_cname ()));
-				cdecl.modifiers = CCodeModifiers.EXTERN;
-				header_type_member_declaration.append (cdecl);
-
-				var var_decl = new CCodeVariableDeclarator (f.get_cname ());
-				var_decl.initializer = default_value_for_type (f.field_type, true);
-
-				if (f.initializer != null) {
-					var init = (CCodeExpression) f.initializer.ccodenode;
-					if (is_constant_ccode_expression (init)) {
-						var_decl.initializer = init;
-					}
-				}
-
-				var var_def = new CCodeDeclaration (field_ctype);
-				var_def.add_declarator (var_decl);
-				var_def.modifiers = CCodeModifiers.EXTERN;
-				source_type_member_declaration.append (var_def);
-
-				lhs = new CCodeIdentifier (f.get_cname ());
-			}
-		} else if (f.access == SymbolAccessibility.PRIVATE) {
-			if (f.binding == MemberBinding.INSTANCE) {
-				if (is_gtypeinstance) {
-					st = instance_priv_struct;
-					lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), f.get_cname ());
-				} else {
-					st = instance_struct;
-					lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ());
-				}
-			} else if (f.binding == MemberBinding.CLASS) {
-				st = type_struct;
-			} else {
-				var cdecl = new CCodeDeclaration (field_ctype);
-				var var_decl = new CCodeVariableDeclarator (f.get_cname ());
-				if (f.initializer != null) {
-					var init = (CCodeExpression) f.initializer.ccodenode;
-					if (is_constant_ccode_expression (init)) {
-						var_decl.initializer = init;
-					}
-				}
-				cdecl.add_declarator (var_decl);
-				cdecl.modifiers = CCodeModifiers.STATIC;
-				source_type_member_declaration.append (cdecl);
-
-				lhs = new CCodeIdentifier (f.get_cname ());
-			}
-		}
-
-		if (f.binding == MemberBinding.INSTANCE)  {
-			st.add_field (field_ctype, f.get_cname ());
-			if (f.field_type is ArrayType && !f.no_array_length) {
-				// create fields to store array dimensions
-				var array_type = (ArrayType) f.field_type;
-				
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var len_type = int_type.copy ();
-
-					st.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
-				}
-			} else if (f.field_type is DelegateType) {
-				var delegate_type = (DelegateType) f.field_type;
-				if (delegate_type.delegate_symbol.has_target) {
-					// create field to store delegate target
-					st.add_field ("gpointer", get_delegate_target_cname (f.name));
-				}
-			}
-
-			if (f.initializer != null) {
-				var rhs = (CCodeExpression) f.initializer.ccodenode;
-
-				instance_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
-
-				if (f.field_type is ArrayType && !f.no_array_length &&
-				    f.initializer is ArrayCreationExpression) {
-					var array_type = (ArrayType) f.field_type;
-					var this_access = new MemberAccess.simple ("this");
-					this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
-					this_access.ccodenode = new CCodeIdentifier ("self");
-					var ma = new MemberAccess (this_access, f.name);
-					ma.symbol_reference = f;
-					
-					Gee.List<Expression> sizes = ((ArrayCreationExpression) f.initializer).get_sizes ();
-					for (int dim = 1; dim <= array_type.rank; dim++) {
-						var array_len_lhs = head.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)));
-					}
-				}
-			}
-			
-			if (requires_destroy (f.field_type) && instance_finalize_fragment != null) {
-				var this_access = new MemberAccess.simple ("this");
-				this_access.value_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
-				this_access.ccodenode = new CCodeIdentifier ("self");
-				var ma = new MemberAccess (this_access, f.name);
-				ma.symbol_reference = f;
-				instance_finalize_fragment.append (new CCodeExpressionStatement (get_unref_expression (lhs, f.field_type, ma)));
-			}
-		} else if (f.binding == MemberBinding.CLASS)  {
-			st.add_field (field_ctype, f.get_cname ());
-		} else {
-			/* add array length fields where necessary */
-			if (f.field_type is ArrayType && !f.no_array_length) {
-				var array_type = (ArrayType) f.field_type;
-
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var len_type = int_type.copy ();
-
-					var cdecl = new CCodeDeclaration (len_type.get_cname ());
-					cdecl.add_declarator (new CCodeVariableDeclarator (head.get_array_length_cname (f.get_cname (), dim)));
-					if (f.access != SymbolAccessibility.PRIVATE) {
-						cdecl.modifiers = CCodeModifiers.EXTERN;
-						header_type_member_declaration.append (cdecl);
-					} else {
-						cdecl.modifiers = CCodeModifiers.STATIC;
-						source_type_member_declaration.append (cdecl);
-					}
-				}
-			} else if (f.field_type is DelegateType) {
-				var delegate_type = (DelegateType) f.field_type;
-				if (delegate_type.delegate_symbol.has_target) {
-					// create field to store delegate target
-					var cdecl = new CCodeDeclaration ("gpointer");
-					cdecl.add_declarator (new CCodeVariableDeclarator (get_delegate_target_cname  (f.get_cname ())));
-					if (f.access != SymbolAccessibility.PRIVATE) {
-						cdecl.modifiers = CCodeModifiers.EXTERN;
-						header_type_member_declaration.append (cdecl);
-					} else {
-						cdecl.modifiers = CCodeModifiers.STATIC;
-						source_type_member_declaration.append (cdecl);
-					}
-				}
-			}
-
-			if (f.initializer != null) {
-				var rhs = (CCodeExpression) f.initializer.ccodenode;
-				if (!is_constant_ccode_expression (rhs)) {
-					if (f.parent_symbol is Class) {
-						class_init_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (lhs, rhs)));
-					} else {
-						f.error = true;
-						Report.error (f.source_reference, "Non-constant field initializers not supported in this context");
-						return;
-					}
-				}
-			}
-		}
-	}
-
-	private bool is_constant_ccode_expression (CCodeExpression cexpr) {
-		if (cexpr is CCodeConstant) {
-			return true;
-		} else if (cexpr is CCodeBinaryExpression) {
-			var cbinary = (CCodeBinaryExpression) cexpr;
-			return is_constant_ccode_expression (cbinary.left) && is_constant_ccode_expression (cbinary.right);
-		}
-
-		var cparenthesized = (cexpr as CCodeParenthesizedExpression);
-		return (null != cparenthesized && is_constant_ccode_expression (cparenthesized.inner));
-	}
-
-	/**
-	 * Returns whether the passed cexpr is a pure expression, i.e. an
-	 * expression without side-effects.
-	 */
-	public bool is_pure_ccode_expression (CCodeExpression cexpr) {
-		if (cexpr is CCodeConstant || cexpr is CCodeIdentifier) {
-			return true;
-		} else if (cexpr is CCodeBinaryExpression) {
-			var cbinary = (CCodeBinaryExpression) cexpr;
-			return is_pure_ccode_expression (cbinary.left) && is_constant_ccode_expression (cbinary.right);
-		} else if (cexpr is CCodeMemberAccess) {
-			var cma = (CCodeMemberAccess) cexpr;
-			return is_pure_ccode_expression (cma.inner);
-		}
-
-		var cparenthesized = (cexpr as CCodeParenthesizedExpression);
-		return (null != cparenthesized && is_pure_ccode_expression (cparenthesized.inner));
+		head.visit_field (f);
 	}
 
 	public override void visit_method (Method m) {
@@ -776,241 +112,15 @@
 	}
 
 	public override void visit_formal_parameter (FormalParameter p) {
-		p.accept_children (this);
-
-		if (!p.ellipsis) {
-			string ctypename = p.parameter_type.get_cname ();
-			string cname = p.name;
-
-			// pass non-simple structs always by reference
-			if (p.parameter_type.data_type is Struct) {
-				var st = (Struct) p.parameter_type.data_type;
-				if (!st.is_simple_type () && p.direction == ParameterDirection.IN && !p.parameter_type.nullable) {
-					ctypename += "*";
-				}
-			}
-
-			if (p.direction != ParameterDirection.IN) {
-				ctypename += "*";
-			}
-
-			p.ccodenode = new CCodeFormalParameter (cname, ctypename);
-		} else {
-			p.ccodenode = new CCodeFormalParameter.with_ellipsis ();
-		}
+		head.visit_formal_parameter (p);
 	}
 
 	public override void visit_property (Property prop) {
-		int old_next_temp_var_id = next_temp_var_id;
-		next_temp_var_id = 0;
-
-		prop.accept_children (this);
-
-		next_temp_var_id = old_next_temp_var_id;
-
-		var cl = prop.parent_symbol as Class;
-		if (cl != null && cl.is_subtype_of (gobject_type)
-		    && prop.binding == MemberBinding.INSTANCE) {
-			// GObject property
-			// FIXME: omit real struct types for now since they
-			// cannot be expressed as gobject property yet
-			// don't register private properties
-			if (!prop.property_type.is_real_struct_type ()
-			    && prop.access != SymbolAccessibility.PRIVATE) {
-				prop_enum.add_value (new CCodeEnumValue (prop.get_upper_case_cname ()));
-			}
-		}
+		head.visit_property (prop);
 	}
 
 	public override void visit_property_accessor (PropertyAccessor acc) {
-		current_property_accessor = acc;
-		current_method_inner_error = false;
-
-		var prop = (Property) acc.prop;
-
-		bool returns_real_struct = prop.property_type.is_real_struct_type ();
-
-		if (acc.readable && !returns_real_struct) {
-			current_return_type = prop.property_type;
-		} else {
-			current_return_type = new VoidType ();
-		}
-
-		acc.accept_children (this);
-
-		var t = (TypeSymbol) prop.parent_symbol;
-
-		ReferenceType this_type;
-		if (t is Class) {
-			this_type = new ObjectType ((Class) t);
-		} else {
-			this_type = new ObjectType ((Interface) t);
-		}
-		var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ());
-		var value_type = prop.property_type.copy ();
-		CCodeFormalParameter cvalueparam;
-		if (returns_real_struct) {
-			cvalueparam = new CCodeFormalParameter ("value", value_type.get_cname () + "*");
-		} else {
-			cvalueparam = new CCodeFormalParameter ("value", value_type.get_cname ());
-		}
-
-		if (prop.is_abstract || prop.is_virtual) {
-			CCodeFunctionDeclarator vdeclarator;
-
-			if (acc.readable) {
-				function = new CCodeFunction (acc.get_cname (), current_return_type.get_cname ());
-
-				var vdecl = new CCodeDeclaration (current_return_type.get_cname ());
-				vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name));
-				vdecl.add_declarator (vdeclarator);
-				type_struct.add_declaration (vdecl);
-			} else {
-				function = new CCodeFunction (acc.get_cname (), "void");
-
-				var vdecl = new CCodeDeclaration ("void");
-				vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name));
-				vdecl.add_declarator (vdeclarator);
-				type_struct.add_declaration (vdecl);
-			}
-			function.add_parameter (cselfparam);
-			vdeclarator.add_parameter (cselfparam);
-			if (acc.writable || acc.construction || returns_real_struct) {
-				function.add_parameter (cvalueparam);
-				vdeclarator.add_parameter (cvalueparam);
-			}
-			
-			if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
-				// accessor function should be public if the property is a public symbol and it's not a construct-only setter
-				header_type_member_declaration.append (function.copy ());
-			} else {
-				function.modifiers |= CCodeModifiers.STATIC;
-				source_type_member_declaration.append (function.copy ());
-			}
-			
-			var block = new CCodeBlock ();
-			function.block = block;
-
-			CCodeFunctionCall vcast = null;
-			if (prop.parent_symbol is Interface) {
-				var iface = (Interface) prop.parent_symbol;
-
-				vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_INTERFACE".printf (iface.get_upper_case_cname (null))));
-			} else {
-				var cl = (Class) prop.parent_symbol;
-
-				vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null))));
-			}
-			vcast.add_argument (new CCodeIdentifier ("self"));
-
-			if (acc.readable) {
-				var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name)));
-				vcall.add_argument (new CCodeIdentifier ("self"));
-				if (returns_real_struct) {
-					vcall.add_argument (new CCodeIdentifier ("value"));
-					block.add_statement (new CCodeExpressionStatement (vcall));
-				} else {
-					block.add_statement (new CCodeReturnStatement (vcall));
-				}
-			} else {
-				var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name)));
-				vcall.add_argument (new CCodeIdentifier ("self"));
-				vcall.add_argument (new CCodeIdentifier ("value"));
-				block.add_statement (new CCodeExpressionStatement (vcall));
-			}
-
-			source_type_member_definition.append (function);
-		}
-
-		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, prop.property_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 {
-					function.add_parameter (cselfparam);
-				}
-			}
-			if (acc.writable || acc.construction || returns_real_struct) {
-				function.add_parameter (cvalueparam);
-			}
-
-			if (!is_virtual) {
-				if (!prop.is_internal_symbol () && (acc.readable || acc.writable) && acc.access != SymbolAccessibility.PRIVATE) {
-					// accessor function should be public if the property is a public symbol and it's not a construct-only setter
-					header_type_member_declaration.append (function.copy ());
-				} else {
-					function.modifiers |= CCodeModifiers.STATIC;
-					source_type_member_declaration.append (function.copy ());
-				}
-			}
-
-			function.block = (CCodeBlock) acc.body.ccodenode;
-
-			if (is_virtual) {
-				var cdecl = new CCodeDeclaration (this_type.get_cname ());
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", transform_expression (new CCodeIdentifier ("base"), base_type, this_type)));
-				function.block.prepend_statement (cdecl);
-			}
-
-			if (current_method_inner_error) {
-				var cdecl = new CCodeDeclaration ("GError *");
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
-				function.block.prepend_statement (cdecl);
-			}
-
-			if (prop.binding == MemberBinding.INSTANCE && !is_virtual) {
-				if (returns_real_struct) {
-					function.block.prepend_statement (create_property_type_check_statement (prop, false, t, true, "self"));
-				} else {
-					function.block.prepend_statement (create_property_type_check_statement (prop, acc.readable, t, true, "self"));
-				}
-			}
-
-			// notify on property changes
-			var typesymbol = (TypeSymbol) prop.parent_symbol;
-			if (typesymbol.is_subtype_of (gobject_type) &&
-			    prop.notify &&
-			    prop.access != SymbolAccessibility.PRIVATE && // FIXME: use better means to detect gobject properties
-			    prop.binding == MemberBinding.INSTANCE &&
-			    !prop.property_type.is_real_struct_type () &&
-			    (acc.writable || acc.construction)) {
-				var notify_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_notify"));
-				notify_call.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GObject *"));
-				notify_call.add_argument (prop.get_canonical_cconstant ());
-				function.block.add_statement (new CCodeExpressionStatement (notify_call));
-			}
-
-			source_type_member_definition.append (function);
-		}
-
-		current_property_accessor = null;
-		current_return_type = null;
+		head.visit_property_accessor (acc);
 	}
 
 	public override void visit_signal (Signal sig) {
@@ -1018,1670 +128,83 @@
 	}
 
 	public override void visit_constructor (Constructor c) {
-		current_method_inner_error = false;
-		in_constructor = true;
-
-		if (c.binding == MemberBinding.CLASS || c.binding == MemberBinding.STATIC) {
-			in_static_or_class_ctor = true;
-		}
-		c.accept_children (this);
-		in_static_or_class_ctor = false;
-
-		in_constructor = false;
-
-		var cl = (Class) c.parent_symbol;
-
-		if (c.binding == MemberBinding.INSTANCE) {
-			function = new CCodeFunction ("%s_constructor".printf (cl.get_lower_case_cname (null)), "GObject *");
-			function.modifiers = CCodeModifiers.STATIC;
-		
-			function.add_parameter (new CCodeFormalParameter ("type", "GType"));
-			function.add_parameter (new CCodeFormalParameter ("n_construct_properties", "guint"));
-			function.add_parameter (new CCodeFormalParameter ("construct_properties", "GObjectConstructParam *"));
-		
-			source_type_member_declaration.append (function.copy ());
-
-
-			var cblock = new CCodeBlock ();
-			var cdecl = new CCodeDeclaration ("GObject *");
-			cdecl.add_declarator (new CCodeVariableDeclarator ("obj"));
-			cblock.add_statement (cdecl);
-
-			cdecl = new CCodeDeclaration ("%sClass *".printf (cl.get_cname ()));
-			cdecl.add_declarator (new CCodeVariableDeclarator ("klass"));
-			cblock.add_statement (cdecl);
-
-			cdecl = new CCodeDeclaration ("GObjectClass *");
-			cdecl.add_declarator (new CCodeVariableDeclarator ("parent_class"));
-			cblock.add_statement (cdecl);
-
-
-			var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek"));
-			ccall.add_argument (new CCodeIdentifier (cl.get_type_id ()));
-			var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
-			ccast.add_argument (ccall);
-			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("klass"), ccast)));
-
-			ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent"));
-			ccall.add_argument (new CCodeIdentifier ("klass"));
-			ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
-			ccast.add_argument (ccall);
-			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_class"), ccast)));
-
-		
-			ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier ("parent_class"), "constructor"));
-			ccall.add_argument (new CCodeIdentifier ("type"));
-			ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
-			ccall.add_argument (new CCodeIdentifier ("construct_properties"));
-			cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("obj"), ccall)));
-
-
-			ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl);
-
-			cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ()));
-			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall));
-		
-			cblock.add_statement (cdecl);
-
-			if (current_method_inner_error) {
-				/* always separate error parameter and inner_error local variable
-				 * as error may be set to NULL but we're always interested in inner errors
-				 */
-				var cdecl = new CCodeDeclaration ("GError *");
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
-				cblock.add_statement (cdecl);
-			}
-
-
-			cblock.add_statement (c.body.ccodenode);
-		
-			cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("obj")));
-		
-			function.block = cblock;
-
-			if (c.source_reference.comment != null) {
-				source_type_member_definition.append (new CCodeComment (c.source_reference.comment));
-			}
-			source_type_member_definition.append (function);
-		} else if (c.binding == MemberBinding.CLASS) {
-			// class constructor
-
-			var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void");
-			base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ())));
-			base_init.modifiers = CCodeModifiers.STATIC;
-
-			source_type_member_declaration.append (base_init.copy ());
-
-			var block = (CCodeBlock) c.body.ccodenode;
-			if (current_method_inner_error) {
-				/* always separate error parameter and inner_error local variable
-				 * as error may be set to NULL but we're always interested in inner errors
-				 */
-				var cdecl = new CCodeDeclaration ("GError *");
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
-				block.prepend_statement (cdecl);
-			}
-
-			base_init.block = block;
-		
-			source_type_member_definition.append (base_init);
-		} else if (c.binding == MemberBinding.STATIC) {
-			// static class constructor
-			// add to class_init
-
-			if (current_method_inner_error) {
-				/* always separate error parameter and inner_error local variable
-				 * as error may be set to NULL but we're always interested in inner errors
-				 */
-				var cdecl = new CCodeDeclaration ("GError *");
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
-				class_init_fragment.append (cdecl);
-			}
-
-			class_init_fragment.append (c.body.ccodenode);
-		} else {
-			Report.error (c.source_reference, "internal error: constructors must have instance, class, or static binding");
-		}
+		head.visit_constructor (c);
 	}
 
 	public override void visit_destructor (Destructor d) {
-		current_method_inner_error = false;
-
-		d.accept_children (this);
-
-		CCodeFragment cfrag = new CCodeFragment ();
-
-		if (current_method_inner_error) {
-			var cdecl = new CCodeDeclaration ("GError *");
-			cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL")));
-			cfrag.append (cdecl);
-		}
-
-		cfrag.append (d.body.ccodenode);
-
-		d.ccodenode = cfrag;
+		head.visit_destructor (d);
 	}
 
 	public override void visit_block (Block b) {
-		current_symbol = b;
-
-		b.accept_children (this);
-
-		var local_vars = b.get_local_variables ();
-		foreach (LocalVariable local in local_vars) {
-			local.active = false;
-		}
-		
-		var cblock = new CCodeBlock ();
-		
-		foreach (CodeNode stmt in b.get_statements ()) {
-			if (stmt.error) {
-				continue;
-			}
-
-			var src = stmt.source_reference;
-			if (src != null && src.comment != null) {
-				cblock.add_statement (new CCodeComment (src.comment));
-			}
-			
-			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 (LocalVariable local in local_vars) {
-			if (requires_destroy (local.variable_type)) {
-				var ma = new MemberAccess.simple (local.name);
-				ma.symbol_reference = local;
-				cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
-			}
-		}
-
-		if (b.parent_symbol is Method) {
-			var m = (Method) b.parent_symbol;
-			foreach (FormalParameter param in m.get_parameters ()) {
-				if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
-					var ma = new MemberAccess.simple (param.name);
-					ma.symbol_reference = param;
-					cblock.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
-				}
-			}
-		}
-
-		b.ccodenode = cblock;
-
-		current_symbol = current_symbol.parent_symbol;
+		head.visit_block (b);
 	}
 
 	public override void visit_empty_statement (EmptyStatement stmt) {
-		stmt.ccodenode = new CCodeEmptyStatement ();
+		head.visit_empty_statement (stmt);
 	}
 
 	public override void visit_declaration_statement (DeclarationStatement stmt) {
-		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 string get_variable_cname (string name) {
-		if (c_keywords.contains (name)) {
-			return name + "_";
-		} else {
-			return name;
-		}
+		head.visit_declaration_statement (stmt);
 	}
 
 	public override void visit_local_variable (LocalVariable local) {
-		local.accept_children (this);
-
-		if (local.variable_type is ArrayType) {
-			// create variables to store array dimensions
-			var array_type = (ArrayType) local.variable_type;
-			
-			for (int dim = 1; dim <= array_type.rank; dim++) {
-				var len_var = new LocalVariable (int_type.copy (), head.get_array_length_cname (local.name, dim));
-				temp_vars.insert (0, len_var);
-			}
-		} else if (local.variable_type is DelegateType) {
-			var deleg_type = (DelegateType) local.variable_type;
-			var d = deleg_type.delegate_symbol;
-			if (d.has_target) {
-				// create variable to store delegate target
-				var target_var = new LocalVariable (new PointerType (new VoidType ()), get_delegate_target_cname (local.name));
-				temp_vars.insert (0, target_var);
-			}
-		}
-	
-		CCodeExpression rhs = null;
-		if (local.initializer != null && local.initializer.ccodenode != null) {
-			rhs = (CCodeExpression) local.initializer.ccodenode;
-
-			if (local.variable_type is ArrayType) {
-				var array_type = (ArrayType) local.variable_type;
-
-				var ccomma = new CCodeCommaExpression ();
-
-				var temp_var = get_temp_variable (local.variable_type, true, local);
-				temp_vars.insert (0, temp_var);
-				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), rhs));
-
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var lhs_array_len = new CCodeIdentifier (head.get_array_length_cname (local.name, dim));
-					var rhs_array_len = head.get_array_length_cexpression (local.initializer, dim);
-					ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
-				}
-				
-				ccomma.append_expression (new CCodeIdentifier (temp_var.name));
-				
-				rhs = ccomma;
-			} else if (local.variable_type is DelegateType) {
-				var deleg_type = (DelegateType) local.variable_type;
-				var d = deleg_type.delegate_symbol;
-				if (d.has_target) {
-					var ccomma = new CCodeCommaExpression ();
-
-					var temp_var = get_temp_variable (local.variable_type, true, local);
-					temp_vars.insert (0, temp_var);
-					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), rhs));
-
-					var lhs_delegate_target = new CCodeIdentifier (get_delegate_target_cname (local.name));
-					var rhs_delegate_target = get_delegate_target_cexpression (local.initializer);
-					ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
-				
-					ccomma.append_expression (new CCodeIdentifier (temp_var.name));
-				
-					rhs = ccomma;
-				}
-			}
-		} else if (local.variable_type.is_reference_type_or_type_parameter ()) {
-			rhs = new CCodeConstant ("NULL");
-
-			if (local.variable_type is ArrayType) {
-				// initialize array length variables
-				var array_type = (ArrayType) local.variable_type;
-
-				var ccomma = new CCodeCommaExpression ();
-
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (head.get_array_length_cname (local.name, dim)), new CCodeConstant ("0")));
-				}
-
-				ccomma.append_expression (rhs);
-
-				rhs = ccomma;
-			}
-		}
-			
-		var cvar = new CCodeVariableDeclarator.with_initializer (get_variable_cname (local.name), rhs);
-
-		var cfrag = new CCodeFragment ();
-		var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
-		cdecl.add_declarator (cvar);
-		cfrag.append (cdecl);
-
-		if (local.initializer != null && local.initializer.tree_can_fail) {
-			head.add_simple_check (local.initializer, cfrag);
-		}
-
-		/* try to initialize uninitialized variables */
-		if (cvar.initializer == null) {
-			cvar.initializer = default_value_for_type (local.variable_type, true);
-		}
-
-		local.ccodenode = cfrag;
-
-		local.active = true;
+		head.visit_local_variable (local);
 	}
 
 	public override void visit_initializer_list (InitializerList list) {
-		list.accept_children (this);
-
-		if (list.target_type.data_type is Struct) {
-			/* initializer is used as struct initializer */
-			var st = (Struct) list.target_type.data_type;
-
-			var clist = new CCodeInitializerList ();
-
-			var field_it = st.get_fields ().iterator ();
-			foreach (Expression expr in list.get_initializers ()) {
-				Field field = null;
-				while (field == null) {
-					field_it.next ();
-					field = field_it.get ();
-					if (field.binding != MemberBinding.INSTANCE) {
-						// we only initialize instance fields
-						field = null;
-					}
-				}
-
-				var cexpr = (CCodeExpression) expr.ccodenode;
-
-				string ctype = field.get_ctype ();
-				if (ctype != null) {
-					cexpr = new CCodeCastExpression (cexpr, ctype);
-				}
-
-				clist.append (cexpr);
-			}
-
-			list.ccodenode = clist;
-		} else {
-			var clist = new CCodeInitializerList ();
-			foreach (Expression expr in list.get_initializers ()) {
-				clist.append ((CCodeExpression) expr.ccodenode);
-			}
-			list.ccodenode = clist;
-		}
-	}
-
-	public LocalVariable get_temp_variable (DataType type, bool value_owned = true, CodeNode? node_reference = null) {
-		var var_type = type.copy ();
-		var_type.value_owned = value_owned;
-		var local = new LocalVariable (var_type, "_tmp%d".printf (next_temp_var_id));
-
-		if (node_reference != null) {
-			local.source_reference = node_reference.source_reference;
-		}
-
-		next_temp_var_id++;
-		
-		return local;
-	}
-
-	private CCodeExpression get_type_id_expression (DataType type) {
-		if (type.data_type != null) {
-			return new CCodeIdentifier (type.data_type.get_type_id ());
-		} else if (type.type_parameter != null) {
-			string var_name = "%s_type".printf (type.type_parameter.name.down ());
-			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), var_name);
-		} else {
-			return new CCodeIdentifier ("G_TYPE_NONE");
-		}
-	}
-
-	public CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
-		var cl = type.data_type as Class;
-		if (type is ErrorType) {
-			return new CCodeIdentifier ("g_error_copy");
-		} else if (type.data_type != null) {
-			string dup_function;
-			if (type.data_type.is_reference_counting ()) {
-				dup_function = type.data_type.get_ref_function ();
-				if (type.data_type is Interface && dup_function == null) {
-					Report.error (source_reference, "missing class prerequisite for interface `%s'".printf (type.data_type.get_full_name ()));
-					return null;
-				}
-			} else if (cl != null && cl.is_immutable) {
-				// allow duplicates of immutable instances as for example strings
-				dup_function = type.data_type.get_dup_function ();
-			} else if (type is ValueType) {
-				if (type.nullable) {
-					dup_function = generate_struct_dup_wrapper ((ValueType) type);
-				} else {
-					dup_function = "";
-				}
-			} else {
-				// duplicating non-reference counted objects may cause side-effects (and performance issues)
-				Report.error (source_reference, "duplicating %s instance, use weak variable or explicitly invoke copy method".printf (type.data_type.name));
-				return null;
-			}
-
-			return new CCodeIdentifier (dup_function);
-		} else if (type.type_parameter != null && current_type_symbol is Class) {
-			string func_name = "%s_dup_func".printf (type.type_parameter.name.down ());
-			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
-		} else if (type is ArrayType) {
-			return new CCodeIdentifier (generate_array_dup_wrapper ((ArrayType) type));
-		} else if (type is PointerType) {
-			var pointer_type = (PointerType) type;
-			return get_dup_func_expression (pointer_type.base_type, source_reference);
-		} else {
-			return new CCodeConstant ("NULL");
-		}
-	}
-
-	string generate_array_dup_wrapper (ArrayType array_type) {
-		string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
-
-		if (!add_wrapper (dup_func)) {
-			// wrapper already defined
-			return dup_func;
-		}
-
-		// declaration
-
-		var function = new CCodeFunction (dup_func, array_type.get_cname ());
-		function.modifiers = CCodeModifiers.STATIC;
-
-		function.add_parameter (new CCodeFormalParameter ("self", array_type.get_cname ()));
-		// total length over all dimensions
-		function.add_parameter (new CCodeFormalParameter ("length", "int"));
-
-		// definition
-
-		var block = new CCodeBlock ();
-
-		if (requires_copy (array_type.element_type)) {
-			var old_temp_vars = temp_vars;
-
-			var cdecl = new CCodeDeclaration (array_type.get_cname ());
-			var cvardecl = new CCodeVariableDeclarator ("result");
-			cdecl.add_declarator (cvardecl);
-			var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
-			gnew.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
-			gnew.add_argument (new CCodeIdentifier ("length"));
-			cvardecl.initializer = gnew;
-			block.add_statement (cdecl);
-
-			var idx_decl = new CCodeDeclaration ("int");
-			idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
-			block.add_statement (idx_decl);
-
-			var loop_body = new CCodeBlock ();
-			loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("result"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
-
-			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);
-
-			block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
-
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			block.add_statement (cfrag);
-			temp_vars = old_temp_vars;
-		} else {
-			var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
-			dup_call.add_argument (new CCodeIdentifier ("self"));
-
-			var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
-			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));
-		}
-
-		// append to file
-
-		source_type_member_declaration.append (function.copy ());
-
-		function.block = block;
-		source_type_member_definition.append (function);
-
-		return dup_func;
-	}
-
-	private string generate_struct_dup_wrapper (ValueType value_type) {
-		string dup_func = "_%sdup".printf (value_type.type_symbol.get_lower_case_cprefix ());
-
-		if (!add_wrapper (dup_func)) {
-			// wrapper already defined
-			return dup_func;
-		}
-
-		// declaration
-
-		var function = new CCodeFunction (dup_func, value_type.get_cname ());
-		function.modifiers = CCodeModifiers.STATIC;
-
-		function.add_parameter (new CCodeFormalParameter ("self", value_type.get_cname ()));
-
-		// definition
-
-		var block = new CCodeBlock ();
-
-		var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("g_memdup"));
-		dup_call.add_argument (new CCodeIdentifier ("self"));
-
-		var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
-		sizeof_call.add_argument (new CCodeIdentifier (value_type.type_symbol.get_cname ()));
-		dup_call.add_argument (sizeof_call);
-
-		block.add_statement (new CCodeReturnStatement (dup_call));
-
-		// append to file
-
-		source_type_member_declaration.append (function.copy ());
-
-		function.block = block;
-		source_type_member_definition.append (function);
-
-		return dup_func;
-	}
-
-	public CCodeExpression? get_destroy_func_expression (DataType type) {
-		if (type.data_type == glist_type || type.data_type == gslist_type) {
-			// create wrapper function to free list elements if necessary
-
-			bool elements_require_free = false;
-			CCodeExpression element_destroy_func_expression = null;
-
-			foreach (DataType type_arg in type.get_type_arguments ()) {
-				elements_require_free = requires_destroy (type_arg);
-				if (elements_require_free) {
-					element_destroy_func_expression = get_destroy_func_expression (type_arg);
-				}
-			}
-			
-			if (elements_require_free && element_destroy_func_expression is CCodeIdentifier) {
-				return new CCodeIdentifier (generate_glist_free_wrapper (type, (CCodeIdentifier) element_destroy_func_expression));
-			} else {
-				return new CCodeIdentifier (type.data_type.get_free_function ());
-			}
-		} else if (type is ErrorType) {
-			return new CCodeIdentifier ("g_error_free");
-		} else if (type.data_type != null) {
-			string unref_function;
-			if (type is ReferenceType) {
-				if (type.data_type.is_reference_counting ()) {
-					unref_function = type.data_type.get_unref_function ();
-					if (type.data_type is Interface && unref_function == null) {
-						Report.error (type.source_reference, "missing class prerequisite for interface `%s'".printf (type.data_type.get_full_name ()));
-						return null;
-					}
-				} else {
-					unref_function = type.data_type.get_free_function ();
-				}
-			} else {
-				if (type.nullable) {
-					unref_function = type.data_type.get_free_function ();
-					if (unref_function == null) {
-						unref_function = "g_free";
-					}
-				} else {
-					var st = (Struct) type.data_type;
-					unref_function = st.get_destroy_function ();
-				}
-			}
-			if (unref_function == null) {
-				return new CCodeConstant ("NULL");
-			}
-			return new CCodeIdentifier (unref_function);
-		} else if (type.type_parameter != null && current_type_symbol is Class) {
-			string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ());
-			return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
-		} else if (type is ArrayType) {
-			return new CCodeIdentifier ("g_free");
-		} else if (type is PointerType) {
-			return new CCodeIdentifier ("g_free");
-		} else {
-			return new CCodeConstant ("NULL");
-		}
-	}
-
-	private string generate_glist_free_wrapper (DataType list_type, CCodeIdentifier element_destroy_func_expression) {
-		string destroy_func = "_%s_%s".printf (list_type.data_type.get_free_function (), element_destroy_func_expression.name);
-
-		if (!add_wrapper (destroy_func)) {
-			// wrapper already defined
-			return destroy_func;
-		}
-
-		// declaration
-
-		var function = new CCodeFunction (destroy_func, "void");
-		function.modifiers = CCodeModifiers.STATIC;
-
-		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
-
-		function.add_parameter (new CCodeFormalParameter ("self", list_type.get_cname ()));
-
-		// definition
-
-		var block = new CCodeBlock ();
-
-		CCodeFunctionCall element_free_call;
-		if (list_type.data_type == glist_type) {
-			element_free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_list_foreach"));
-		} else {
-			element_free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_slist_foreach"));
-		}
-		element_free_call.add_argument (new CCodeIdentifier ("self"));
-		element_free_call.add_argument (new CCodeCastExpression (element_destroy_func_expression, "GFunc"));
-		element_free_call.add_argument (new CCodeConstant ("NULL"));
-		block.add_statement (new CCodeExpressionStatement (element_free_call));
-
-		var cfreecall = new CCodeFunctionCall (new CCodeIdentifier (list_type.data_type.get_free_function ()));
-		cfreecall.add_argument (new CCodeIdentifier ("self"));
-		block.add_statement (new CCodeExpressionStatement (cfreecall));
-
-		// append to file
-
-		source_type_member_declaration.append (function.copy ());
-
-		function.block = block;
-		source_type_member_definition.append (function);
-
-		return destroy_func;
-	}
-
-	public CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
-		var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
-
-		if (type is ValueType && !type.nullable) {
-			// normal value type, no null check
-			ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cvar));
-			return ccall;
-		}
-
-		/* (foo == NULL ? NULL : foo = (unref (foo), NULL)) */
-		
-		/* can be simplified to
-		 * foo = (unref (foo), NULL)
-		 * if foo is of static type non-null
-		 */
-
-		var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL"));
-		if (type.type_parameter != null) {
-			if (!(current_type_symbol is Class) || current_class.is_compact) {
-				return new CCodeConstant ("NULL");
-			}
-
-			// unref functions are optional for type parameters
-			var cunrefisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_destroy_func_expression (type), new CCodeConstant ("NULL"));
-			cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cunrefisnull);
-		}
-
-		ccall.add_argument (cvar);
-
-		/* set freed references to NULL to prevent further use */
-		var ccomma = new CCodeCommaExpression ();
-
-		if (type.data_type == gstringbuilder_type) {
-			ccall.add_argument (new CCodeConstant ("TRUE"));
-		} else if (type is ArrayType) {
-			var array_type = (ArrayType) type;
-			if (array_type.element_type.data_type == null || array_type.element_type.data_type.is_reference_type ()) {
-				requires_array_free = true;
-
-				bool first = true;
-				CCodeExpression csizeexpr = null;
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					if (first) {
-						csizeexpr = head.get_array_length_cexpression (expr, dim);
-						first = false;
-					} else {
-						csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, head.get_array_length_cexpression (expr, dim));
-					}
-				}
-
-				ccall.call = new CCodeIdentifier ("_vala_array_free");
-				ccall.add_argument (csizeexpr);
-				ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
-			}
-		}
-		
-		ccomma.append_expression (ccall);
-		ccomma.append_expression (new CCodeConstant ("NULL"));
-		
-		var cassign = new CCodeAssignment (cvar, ccomma);
-
-		// g_free (NULL) is allowed
-		bool uses_gfree = (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free");
-		uses_gfree = uses_gfree || type is ArrayType;
-		if (uses_gfree) {
-			return new CCodeParenthesizedExpression (cassign);
-		}
-
-		return new CCodeConditionalExpression (cisnull, new CCodeConstant ("NULL"), new CCodeParenthesizedExpression (cassign));
+		head.visit_initializer_list (list);
 	}
-	
+
 	public override void visit_end_full_expression (Expression expr) {
-		/* expr is a full expression, i.e. an initializer, the
-		 * expression in an expression statement, the controlling
-		 * expression in if, while, for, or foreach statements
-		 *
-		 * 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 (((Gee.List<LocalVariable>) temp_ref_vars).size == 0) {
-			/* nothing to do without temporary variables */
-			return;
-		}
-
-		var expr_type = expr.value_type;
-		if (expr.target_type != null) {
-			expr_type = expr.target_type;
-		}
-
-		var full_expr_var = get_temp_variable (expr_type, true, expr);
-		expr.temp_vars.add (full_expr_var);
-		
-		var expr_list = new CCodeCommaExpression ();
-		expr_list.append_expression (new CCodeAssignment (new CCodeIdentifier (full_expr_var.name), (CCodeExpression) expr.ccodenode));
-		
-		foreach (LocalVariable local in temp_ref_vars) {
-			var ma = new MemberAccess.simple (local.name);
-			ma.symbol_reference = local;
-			expr_list.append_expression (get_unref_expression (new CCodeIdentifier (local.name), local.variable_type, ma));
-		}
-		
-		expr_list.append_expression (new CCodeIdentifier (full_expr_var.name));
-		
-		expr.ccodenode = expr_list;
-		
-		temp_ref_vars.clear ();
+		head.visit_end_full_expression (expr);
 	}
 	
-	private void append_temp_decl (CCodeFragment cfrag, Gee.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);
-			// sets #line
-			local.ccodenode = vardecl;
-			cdecl.add_declarator (vardecl);
-
-			var st = local.variable_type.data_type as Struct;
-
-			if (local.variable_type.is_reference_type_or_type_parameter ()) {
-				vardecl.initializer = new CCodeConstant ("NULL");
-			} else if (st != null && !st.is_simple_type ()) {
-				// 0-initialize struct with struct initializer { 0 }
-				// necessary as they will be passed by reference
-				var clist = new CCodeInitializerList ();
-				clist.append (new CCodeConstant ("0"));
-
-				vardecl.initializer = clist;
-			}
-			
-			cfrag.append (cdecl);
-		}
-	}
-
 	public override void visit_expression_statement (ExpressionStatement stmt) {
-		if (stmt.expression.error) {
-			stmt.error = true;
-			return;
-		}
-
-		stmt.ccodenode = new CCodeExpressionStatement ((CCodeExpression) stmt.expression.ccodenode);
-
-		var invoc = stmt.expression as InvocationExpression;
-		if (invoc != null) {
-			var m = invoc.call.symbol_reference as Method;
-			var ma = invoc.call as MemberAccess;
-			if (m != null && m.coroutine && (ma == null || ma.member_name != "begin"
-				                         || ma.inner.symbol_reference != ma.symbol_reference)) {
-				var cfrag = new CCodeFragment ();
-
-				int state = next_coroutine_state++;
-
-				cfrag.append (stmt.ccodenode);
-				cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "state"), new CCodeConstant (state.to_string ()))));
-				cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-				cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
-
-				stmt.ccodenode = cfrag;
-			}
-		}
-
-		if (stmt.tree_can_fail && stmt.expression.tree_can_fail) {
-			// simple case, no node breakdown necessary
-
-			var cfrag = new CCodeFragment ();
-
-			cfrag.append (stmt.ccodenode);
-
-			head.add_simple_check (stmt.expression, cfrag);
-
-			stmt.ccodenode = cfrag;
-		}
-
-		/* free temporary objects */
-
-		if (((Gee.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)));
-		}
-		
-		stmt.ccodenode = cfrag;
-		
-		temp_vars.clear ();
-		temp_ref_vars.clear ();
-	}
-	
-	public void create_temp_decl (Statement stmt, Gee.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);
-		
-		// FIXME cast to CodeNode shouldn't be necessary as Statement requires CodeNode
-		cfrag.append (((CodeNode) stmt).ccodenode);
-		
-		((CodeNode) stmt).ccodenode = cfrag;
+		head.visit_expression_statement (stmt);
 	}
 
 	public override void visit_if_statement (IfStatement stmt) {
-		stmt.accept_children (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);
-	}
-
-	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, true, stmt);
-		stmt.expression.temp_vars.insert (0, temp_var);
-
-		var ctemp = new CCodeIdentifier (temp_var.name);
-		var cinit = new CCodeAssignment (ctemp, (CCodeExpression) stmt.expression.ccodenode);
-		var czero = new CCodeConstant ("0");
-
-		var cswitchblock = new CCodeFragment ();
-		stmt.ccodenode = cswitchblock;
-
-		var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
-		var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
-		cquark.add_argument (ctemp);
-
-		var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
-
-		temp_var = get_temp_variable (gquark_type);
-		stmt.expression.temp_vars.insert (0, temp_var);
-
-		int label_count = 0;
-
-		foreach (SwitchSection section in stmt.get_sections ()) {
-			if (section.has_default_label ()) {
-				continue;
-			}
-
-			foreach (SwitchLabel label in section.get_labels ()) {
-				var cexpr = (CCodeExpression) label.expression.ccodenode;
-
-				if (is_constant_ccode_expression (cexpr)) {
-					var cname = "%s_label%d".printf (temp_var.name, label_count++);
-					var cdecl = new CCodeDeclaration (gquark_type.get_cname ());
-
-					cdecl.modifiers = CCodeModifiers.STATIC;
-					cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (cname, czero));
-
-					cswitchblock.append (cdecl);
-				}
-			}
-		}
-
-		cswitchblock.append (new CCodeExpressionStatement (cinit));
-
-		ctemp = new CCodeIdentifier (temp_var.name);
-		cinit = new CCodeAssignment (ctemp, ccond);
-
-		cswitchblock.append (new CCodeExpressionStatement (cinit));
-		create_temp_decl (stmt, stmt.expression.temp_vars);
-
-		Gee.List<Statement> default_statements = null;
-		label_count = 0;
-
-		// generate nested if statements		
-		CCodeStatement ctopstmt = null;
-		CCodeIfStatement coldif = null;
-
-		foreach (SwitchSection section in stmt.get_sections ()) {
-			if (section.has_default_label ()) {
-				default_statements = section.get_statements ();
-				continue;
-			}
-
-			CCodeBinaryExpression cor = null;
-			foreach (SwitchLabel label in section.get_labels ()) {
-				var cexpr = (CCodeExpression) label.expression.ccodenode;
-
-				if (is_constant_ccode_expression (cexpr)) {
-					var cname = new CCodeIdentifier ("%s_label%d".printf (temp_var.name, label_count++));
-					var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
-					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
-					var cinit = new CCodeParenthesizedExpression (new CCodeAssignment (cname, ccall));
-
-					ccall.add_argument (cexpr);
-
-					cexpr = new CCodeConditionalExpression (ccond, cname, cinit);
-				} else {
-					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
-					ccall.add_argument (cexpr);
-					cexpr = ccall;
-				}
-
-				var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
-
-				if (cor == null) {
-					cor = ccmp;
-				} else {
-					cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
-				}
-			}
-
-			var cblock = new CCodeBlock ();
-			foreach (CodeNode body_stmt in section.get_statements ()) {
-				if (body_stmt.ccodenode is CCodeFragment) {
-					foreach (CCodeNode cstmt in ((CCodeFragment) body_stmt.ccodenode).get_children ()) {
-						cblock.add_statement (cstmt);
-					}
-				} else {
-					cblock.add_statement (body_stmt.ccodenode);
-				}
-			}
-
-			var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
-			var cif = new CCodeIfStatement (cor, cdo);
-
-			if (coldif != null) {
-				coldif.false_statement = cif;
-			} else {
-				ctopstmt = cif;
-			}
-
-			coldif = cif;
-		}
-	
-		if (default_statements != null) {
-			var cblock = new CCodeBlock ();
-			foreach (CodeNode body_stmt in default_statements) {
-				cblock.add_statement (body_stmt.ccodenode);
-			}
-		
-			var cdo = new CCodeDoStatement (cblock, new CCodeConstant ("0"));
-
-			if (coldif == null) {
-				// there is only one section and that section
-				// contains a default label
-				ctopstmt = cdo;
-			} else {
-				coldif.false_statement = cdo;
-			}
-		}
-	
-		cswitchblock.append (ctopstmt);
+		head.visit_if_statement (stmt);
 	}
 
 	public override void visit_switch_statement (SwitchStatement stmt) {
-		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;
-
-		foreach (SwitchSection section in stmt.get_sections ()) {
-			if (section.has_default_label ()) {
-				cswitch.add_statement (new CCodeLabel ("default"));
-				var cdefaultblock = new CCodeBlock ();
-				cswitch.add_statement (cdefaultblock);
-				foreach (CodeNode default_stmt in section.get_statements ()) {
-					cdefaultblock.add_statement (default_stmt.ccodenode);
-				}
-				continue;
-			}
-
-			foreach (SwitchLabel label in section.get_labels ()) {
-				cswitch.add_statement (new CCodeCaseStatement ((CCodeExpression) label.expression.ccodenode));
-			}
-
-			var cblock = new CCodeBlock ();
-			cswitch.add_statement (cblock);
-			foreach (CodeNode body_stmt in section.get_statements ()) {
-				cblock.add_statement (body_stmt.ccodenode);
-			}
-		}
+		head.visit_switch_statement (stmt);
 	}
 
 	public override void visit_switch_section (SwitchSection section) {
-		visit_block (section);
+		head.visit_switch_section (section);
 	}
 
 	public override void visit_while_statement (WhileStatement stmt) {
-		stmt.accept_children (this);
-
-		stmt.ccodenode = new CCodeWhileStatement ((CCodeExpression) stmt.condition.ccodenode, (CCodeStatement) stmt.body.ccodenode);
-		
-		create_temp_decl (stmt, stmt.condition.temp_vars);
+		head.visit_while_statement (stmt);
 	}
 
 	public override void visit_do_statement (DoStatement stmt) {
-		stmt.accept_children (this);
-
-		stmt.ccodenode = new CCodeDoStatement ((CCodeStatement) stmt.body.ccodenode, (CCodeExpression) stmt.condition.ccodenode);
-		
-		create_temp_decl (stmt, stmt.condition.temp_vars);
+		head.visit_do_statement (stmt);
 	}
 
 	public override void visit_for_statement (ForStatement stmt) {
-		stmt.accept_children (this);
-
-		CCodeExpression ccondition = null;
-		if (stmt.condition != null) {
-			ccondition = (CCodeExpression) stmt.condition.ccodenode;
-		}
-
-		var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode);
-		stmt.ccodenode = cfor;
-		
-		foreach (Expression init_expr in stmt.get_initializer ()) {
-			cfor.add_initializer ((CCodeExpression) init_expr.ccodenode);
-			create_temp_decl (stmt, init_expr.temp_vars);
-		}
-		
-		foreach (Expression it_expr in stmt.get_iterator ()) {
-			cfor.add_iterator ((CCodeExpression) it_expr.ccodenode);
-			create_temp_decl (stmt, it_expr.temp_vars);
-		}
-
-		if (stmt.condition != null) {
-			create_temp_decl (stmt, stmt.condition.temp_vars);
-		}
+		head.visit_for_statement (stmt);
 	}
 
 	public override void visit_foreach_statement (ForeachStatement stmt) {
-		stmt.element_variable.active = true;
-		stmt.collection_variable.active = true;
-		if (stmt.iterator_variable != null) {
-			stmt.iterator_variable.active = true;
-		}
-
-		visit_block (stmt);
-
-		var cblock = new CCodeBlock ();
-		// sets #line
-		stmt.ccodenode = cblock;
-
-		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 ();
-		var ccoldecl = new CCodeDeclaration (collection_type.get_cname ());
-		var ccolvardecl = new CCodeVariableDeclarator.with_initializer (collection_backup.name, (CCodeExpression) stmt.collection.ccodenode);
-		ccolvardecl.line = cblock.line;
-		ccoldecl.add_declarator (ccolvardecl);
-		cblock.add_statement (ccoldecl);
-		
-		if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
-			// exception handling
-			var cfrag = new CCodeFragment ();
-			head.add_simple_check (stmt.collection, cfrag);
-			cblock.add_statement (cfrag);
-		}
-
-		if (stmt.collection.value_type is ArrayType) {
-			var array_type = (ArrayType) stmt.collection.value_type;
-			
-			var array_len = head.get_array_length_cexpression (stmt.collection);
-
-			// store array length for use by _vala_array_free
-			var clendecl = new CCodeDeclaration ("int");
-			clendecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (collection_backup.name, 1), array_len));
-			cblock.add_statement (clendecl);
-
-			if (array_len is CCodeConstant) {
-				// the array has no length parameter i.e. it is NULL-terminated array
-
-				var it_name = "%s_it".printf (stmt.variable_name);
-			
-				var citdecl = new CCodeDeclaration (collection_type.get_cname ());
-				citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-				cblock.add_statement (citdecl);
-				
-				var cbody = new CCodeBlock ();
-
-				CCodeExpression element_expr = new CCodeIdentifier ("*%s".printf (it_name));
-
-				var element_type = array_type.element_type.copy ();
-				element_type.value_owned = false;
-				element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-				var cfrag = new CCodeFragment ();
-				append_temp_decl (cfrag, temp_vars);
-				cbody.add_statement (cfrag);
-				temp_vars.clear ();
-
-				var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
-				cbody.add_statement (cdecl);
-
-				// add array length variable for stacked arrays
-				if (stmt.type_reference is ArrayType) {
-					var inner_array_type = (ArrayType) stmt.type_reference;
-					for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-						cdecl = new CCodeDeclaration ("int");
-						cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
-						cbody.add_statement (cdecl);
-					}
-				}
-
-				cbody.add_statement (stmt.body.ccodenode);
-				
-				var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("*%s".printf (it_name)), new CCodeConstant ("NULL"));
-				
-				var cfor = new CCodeForStatement (ccond, cbody);
-
-				cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
-		
-				cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-				cblock.add_statement (cfor);
-			} else {
-				// the array has a length parameter
-
-				var it_name = (stmt.variable_name + "_it");
-			
-				var citdecl = new CCodeDeclaration ("int");
-				citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-				cblock.add_statement (citdecl);
-				
-				var cbody = new CCodeBlock ();
-
-				CCodeExpression element_expr = new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name));
-
-				var element_type = array_type.element_type.copy ();
-				element_type.value_owned = false;
-				element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-				var cfrag = new CCodeFragment ();
-				append_temp_decl (cfrag, temp_vars);
-				cbody.add_statement (cfrag);
-				temp_vars.clear ();
-
-				var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-				cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
-				cbody.add_statement (cdecl);
-
-				// add array length variable for stacked arrays
-				if (stmt.type_reference is ArrayType) {
-					var inner_array_type = (ArrayType) stmt.type_reference;
-					for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-						cdecl = new CCodeDeclaration ("int");
-						cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (head.get_array_length_cname (stmt.variable_name, dim), new CCodeConstant ("-1")));
-						cbody.add_statement (cdecl);
-					}
-				}
-
-				cbody.add_statement (stmt.body.ccodenode);
-				
-				var ccond_ind1 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, array_len, new CCodeConstant ("-1"));
-				var ccond_ind2 = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), array_len);
-				var ccond_ind = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_ind1, ccond_ind2);
-				
-				/* only check for null if the containers elements are of reference-type */
-				CCodeBinaryExpression ccond;
-				if (array_type.element_type.is_reference_type_or_type_parameter ()) {
-					var ccond_term1 = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, array_len, new CCodeConstant ("-1"));
-					var ccond_term2 = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeElementAccess (new CCodeIdentifier (collection_backup.name), new CCodeIdentifier (it_name)), new CCodeConstant ("NULL"));
-					var ccond_term = new CCodeBinaryExpression (CCodeBinaryOperator.AND, ccond_term1, ccond_term2);
-
-					ccond = new CCodeBinaryExpression (CCodeBinaryOperator.OR, new CCodeParenthesizedExpression (ccond_ind), new CCodeParenthesizedExpression (ccond_term));
-				} else {
-					/* assert when trying to iterate over value-type arrays of unknown length */
-					var cassert = new CCodeFunctionCall (new CCodeIdentifier ("g_assert"));
-					cassert.add_argument (ccond_ind1);
-					cblock.add_statement (new CCodeExpressionStatement (cassert));
-
-					ccond = ccond_ind2;
-				}
-				
-				var cfor = new CCodeForStatement (ccond, cbody);
-				cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
-				cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-				cblock.add_statement (cfor);
-			}
-		} 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
-
-			var it_name = "%s_it".printf (stmt.variable_name);
-		
-			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);
-			
-			var cbody = new CCodeBlock ();
-
-			CCodeExpression element_expr = new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "data");
-
-			if (collection_type.get_type_arguments ().size != 1) {
-				Report.error (stmt.source_reference, "internal error: missing generic type argument");
-				stmt.error = true;
-				return;
-			}
-
-			var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
-			element_data_type.value_owned = false;
-			element_data_type.is_type_argument = true;
-			element_expr = transform_expression (element_expr, element_data_type, stmt.type_reference);
-
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			cbody.add_statement (cfrag);
-			temp_vars.clear ();
-
-			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-			cvardecl.line = cblock.line;
-			cdecl.add_declarator (cvardecl);
-			cbody.add_statement (cdecl);
-			
-			cbody.add_statement (stmt.body.ccodenode);
-			
-			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (it_name), new CCodeConstant ("NULL"));
-			
-			var cfor = new CCodeForStatement (ccond, cbody);
-			
-			cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeIdentifier (collection_backup.name)));
-
-			cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
-			cblock.add_statement (cfor);
-		} else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
-			// iterating over a Gee.List, use integer to avoid the cost of an iterator object
-
-			var it_name = "%s_it".printf (stmt.variable_name);
-
-			var citdecl = new CCodeDeclaration ("int");
-			citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-			cblock.add_statement (citdecl);
-			
-			var cbody = new CCodeBlock ();
-
-			var get_method = (Method) list_type.scope.lookup ("get");
-			var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
-			get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
-			get_ccall.add_argument (new CCodeIdentifier (it_name));
-			CCodeExpression element_expr = get_ccall;
-
-			var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, get_method, get_method.return_type, stmt);
-
-			element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			cbody.add_statement (cfrag);
-			temp_vars.clear ();
-
-			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-			cvardecl.line = cblock.line;
-			cdecl.add_declarator (cvardecl);
-			cbody.add_statement (cdecl);
-
-			cbody.add_statement (stmt.body.ccodenode);
-
-			var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
-			list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
-
-			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
-
-			var cfor = new CCodeForStatement (ccond, cbody);
-			cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
-			cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-			cfor.line = cblock.line;
-			cblock.add_statement (cfor);
-		} else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
-			// iterating over a Gee.Iterable, use iterator
-
-			var it_name = "%s_it".printf (stmt.variable_name);
-
-			var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
-			var it_method = (Method) iterable_type.scope.lookup ("iterator");
-			var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
-			it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
-			var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
-			citvardecl.line = cblock.line;
-			citdecl.add_declarator (citvardecl);
-			cblock.add_statement (citdecl);
-			
-			var cbody = new CCodeBlock ();
-
-			var get_method = (Method) iterator_type.scope.lookup ("get");
-			var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
-			get_ccall.add_argument (new CCodeIdentifier (it_name));
-			CCodeExpression element_expr = get_ccall;
-
-			Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
-			type_arg_it.next ();
-			var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, it_method, type_arg_it.get (), stmt);
-
-			element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
-
-			var cfrag = new CCodeFragment ();
-			append_temp_decl (cfrag, temp_vars);
-			cbody.add_statement (cfrag);
-			temp_vars.clear ();
-
-			var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-			var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-			cvardecl.line = cblock.line;
-			cdecl.add_declarator (cvardecl);
-			cbody.add_statement (cdecl);
-			
-			cbody.add_statement (stmt.body.ccodenode);
-
-			var next_method = (Method) iterator_type.scope.lookup ("next");
-			var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
-			next_ccall.add_argument (new CCodeIdentifier (it_name));
-
-			var cwhile = new CCodeWhileStatement (next_ccall, cbody);
-			cwhile.line = cblock.line;
-			cblock.add_statement (cwhile);
-		}
-
-		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 (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
-				cunref.line = cblock.line;
-				cblock.add_statement (cunref);
-			}
-		}
+		head.visit_foreach_statement (stmt);
 	}
 
 	public override void visit_break_statement (BreakStatement stmt) {
-		stmt.ccodenode = new CCodeBreakStatement ();
-
-		create_local_free (stmt, true);
+		head.visit_break_statement (stmt);
 	}
 
 	public override void visit_continue_statement (ContinueStatement stmt) {
-		stmt.ccodenode = new CCodeContinueStatement ();
-
-		create_local_free (stmt, true);
-	}
-
-	public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) {
-		var b = (Block) sym;
-
-		var local_vars = b.get_local_variables ();
-		foreach (LocalVariable local in local_vars) {
-			if (local.active && requires_destroy (local.variable_type)) {
-				var ma = new MemberAccess.simple (local.name);
-				ma.symbol_reference = local;
-				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma)));
-			}
-		}
-		
-		if (stop_at_loop) {
-			if (b.parent_node is DoStatement || b.parent_node is WhileStatement ||
-			    b.parent_node is ForStatement || b.parent_node is ForeachStatement ||
-			    b.parent_node is SwitchStatement) {
-				return;
-			}
-		}
-
-		if (sym.parent_symbol is Block) {
-			append_local_free (sym.parent_symbol, cfrag, stop_at_loop);
-		} else if (sym.parent_symbol is Method) {
-			append_param_free ((Method) sym.parent_symbol, cfrag);
-		}
-	}
-
-	private void append_param_free (Method m, CCodeFragment cfrag) {
-		foreach (FormalParameter param in m.get_parameters ()) {
-			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
-				var ma = new MemberAccess.simple (param.name);
-				ma.symbol_reference = param;
-				cfrag.append (new CCodeExpressionStatement (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma)));
-			}
-		}
-	}
-
-	private 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;
-	}
-
-	private bool append_local_free_expr (Symbol sym, CCodeCommaExpression ccomma, bool stop_at_loop) {
-		bool found = false;
-	
-		var b = (Block) sym;
-
-		var local_vars = b.get_local_variables ();
-		foreach (LocalVariable local in local_vars) {
-			if (local.active && requires_destroy (local.variable_type)) {
-				found = true;
-				var ma = new MemberAccess.simple (local.name);
-				ma.symbol_reference = local;
-				ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (local.name)), local.variable_type, ma));
-			}
-		}
-		
-		if (sym.parent_symbol is Block) {
-			found = append_local_free_expr (sym.parent_symbol, ccomma, stop_at_loop) || found;
-		} else if (sym.parent_symbol is Method) {
-			found = append_param_free_expr ((Method) sym.parent_symbol, ccomma) || found;
-		}
-		
-		return found;
-	}
-
-	private bool append_param_free_expr (Method m, CCodeCommaExpression ccomma) {
-		bool found = false;
-
-		foreach (FormalParameter param in m.get_parameters ()) {
-			if (requires_destroy (param.parameter_type) && param.direction == ParameterDirection.IN) {
-				found = true;
-				var ma = new MemberAccess.simple (param.name);
-				ma.symbol_reference = param;
-				ccomma.append_expression (get_unref_expression (new CCodeIdentifier (get_variable_cname (param.name)), param.parameter_type, ma));
-			}
-		}
-
-		return found;
-	}
-
-	private void create_local_free_expr (Expression expr) {
-		var expr_type = expr.value_type;
-		if (expr.target_type != null) {
-			expr_type = expr.target_type;
-		}
-
-		var return_expr_decl = get_temp_variable (expr_type, true, expr);
-		
-		var ccomma = new CCodeCommaExpression ();
-		ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (return_expr_decl.name), (CCodeExpression) expr.ccodenode));
-
-		if (!append_local_free_expr (current_symbol, ccomma, false)) {
-			/* no local variables need to be freed */
-			return;
-		}
-
-		ccomma.append_expression (new CCodeIdentifier (return_expr_decl.name));
-		
-		expr.ccodenode = ccomma;
-		expr.temp_vars.add (return_expr_decl);
+		head.visit_continue_statement (stmt);
 	}
 
 	public override void visit_return_statement (ReturnStatement stmt) {
-		// avoid unnecessary ref/unref pair
-		if (stmt.return_expression != null) {
-			var local = stmt.return_expression.symbol_reference as LocalVariable;
-			if (current_return_type.value_owned
-			    && local != null && local.variable_type.value_owned) {
-				/* return expression is local variable taking ownership and
-				 * current method is transferring ownership */
-
-				// don't ref expression
-				stmt.return_expression.value_type.value_owned = true;
-			}
-		}
-
-		stmt.accept_children (this);
-
-		if (stmt.return_expression == null) {
-			stmt.ccodenode = new CCodeReturnStatement ();
-			
-			create_local_free (stmt);
-		} else {
-			Symbol return_expression_symbol = null;
-
-			// avoid unnecessary ref/unref pair
-			var local = stmt.return_expression.symbol_reference as LocalVariable;
-			if (current_return_type.value_owned
-			    && local != null && local.variable_type.value_owned) {
-				/* return expression is local variable taking ownership and
-				 * current method is transferring ownership */
-
-				// don't unref variable
-				return_expression_symbol = local;
-				return_expression_symbol.active = false;
-			}
-
-			// return array length if appropriate
-			if (current_method != null && !current_method.no_array_length && current_return_type is ArrayType) {
-				var return_expr_decl = get_temp_variable (stmt.return_expression.value_type, true, stmt);
-
-				var ccomma = new CCodeCommaExpression ();
-				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (return_expr_decl.name), (CCodeExpression) stmt.return_expression.ccodenode));
-
-				var array_type = (ArrayType) current_return_type;
-
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var len_l = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (head.get_array_length_cname ("result", dim)));
-					var len_r = head.get_array_length_cexpression (stmt.return_expression, dim);
-					ccomma.append_expression (new CCodeAssignment (len_l, len_r));
-				}
-
-				ccomma.append_expression (new CCodeIdentifier (return_expr_decl.name));
-				
-				stmt.return_expression.ccodenode = ccomma;
-				stmt.return_expression.temp_vars.add (return_expr_decl);
-			}
-
-			create_local_free_expr (stmt.return_expression);
-
-			// Property getters of non simple structs shall return the struct value as out parameter,
-			// therefore replace any return statement with an assignment statement to the out formal
-			// paramenter and insert an empty return statement afterwards.
-			if (current_property_accessor != null &&
-			    current_property_accessor.readable &&
-			    current_property_accessor.prop.property_type.is_real_struct_type()) {
-			    	var cfragment = new CCodeFragment ();
-				cfragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("*value"), (CCodeExpression) stmt.return_expression.ccodenode)));
-				cfragment.append (new CCodeReturnStatement ());
-				stmt.ccodenode = cfragment;
-			} else {
-				stmt.ccodenode = new CCodeReturnStatement ((CCodeExpression) stmt.return_expression.ccodenode);
-			}
-
-			create_temp_decl (stmt, stmt.return_expression.temp_vars);
-
-			if (return_expression_symbol != null) {
-				return_expression_symbol.active = true;
-			}
-		}
+		head.visit_return_statement (stmt);
 	}
 
 	public override void visit_yield_statement (YieldStatement stmt) {
-		if (stmt.yield_expression == null) {
-			var cfrag = new CCodeFragment ();
-			stmt.ccodenode = cfrag;
-
-			var idle_call = new CCodeFunctionCall (new CCodeIdentifier ("g_idle_add"));
-			idle_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (current_method.get_real_cname ()), "GSourceFunc"));
-			idle_call.add_argument (new CCodeIdentifier ("data"));
-
-			int state = next_coroutine_state++;
-
-			cfrag.append (new CCodeExpressionStatement (idle_call));
-			cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "state"), new CCodeConstant (state.to_string ()))));
-			cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
-			cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ())));
-
-			return;
-		}
-
-		stmt.accept_children (this);
-
-		if (stmt.yield_expression.error) {
-			stmt.error = true;
-			return;
-		}
-
-		stmt.ccodenode = new CCodeExpressionStatement ((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);
-
-			head.add_simple_check (stmt.yield_expression, cfrag);
-
-			stmt.ccodenode = cfrag;
-		}
-
-		/* free temporary objects */
-
-		if (((Gee.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)));
-		}
-		
-		stmt.ccodenode = cfrag;
-		
-		temp_vars.clear ();
-		temp_ref_vars.clear ();
+		head.visit_yield_statement (stmt);
 	}
 
 	public override void visit_throw_statement (ThrowStatement stmt) {
@@ -2689,137 +212,23 @@
 	}
 
 	public override void visit_try_statement (TryStatement stmt) {
-		int this_try_id = next_try_id++;
-
-		var old_try = current_try;
-		var old_try_id = current_try_id;
-		current_try = stmt;
-		current_try_id = this_try_id;
-
-		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
-			clause.clabel_name = "__catch%d_%s".printf (this_try_id, clause.error_type.get_lower_case_cname ());
-		}
-
-		if (stmt.finally_body != null) {
-			stmt.finally_body.accept (this);
-		}
-
-		stmt.body.accept (this);
-
-		current_try = old_try;
-		current_try_id = old_try_id;
-
-		foreach (CatchClause clause in stmt.get_catch_clauses ()) {
-			clause.accept (this);
-		}
-
-		if (stmt.finally_body != null) {
-			stmt.finally_body.accept (this);
-		}
-
-		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)));
-		if (stmt.finally_body != null) {
-			cfrag.append (stmt.finally_body.ccodenode);
-		} else {
-			// avoid gcc error: label at end of compound statement
-			cfrag.append (new CCodeEmptyStatement ());
-		}
-
-		stmt.ccodenode = cfrag;
+		head.visit_try_statement (stmt);
 	}
 
 	public override void visit_catch_clause (CatchClause clause) {
-		if (clause.error_variable != null) {
-			clause.error_variable.active = true;
-		}
-
-		current_method_inner_error = true;
-
-		clause.accept_children (this);
-
-		var cfrag = new CCodeFragment ();
-		cfrag.append (new CCodeLabel (clause.clabel_name));
-
-		var cblock = new CCodeBlock ();
-
-		string variable_name = clause.variable_name;
-		if (variable_name == null) {
-			variable_name = "__err";
-		}
-
-		var cdecl = new CCodeDeclaration ("GError *");
-		cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (variable_name, new CCodeIdentifier ("inner_error")));
-		cblock.add_statement (cdecl);
-		cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("inner_error"), new CCodeConstant ("NULL"))));
-
-		cblock.add_statement (clause.body.ccodenode);
-
-		cfrag.append (cblock);
-
-		clause.ccodenode = cfrag;
-	}
-
-	private string get_symbol_lock_name (Symbol sym) {
-		return "__lock_%s".printf (sym.name);
+		head.visit_catch_clause (clause);
 	}
 
 	public override void visit_lock_statement (LockStatement stmt) {
-		var cn = new CCodeFragment ();
-		CCodeExpression l = null;
-		CCodeFunctionCall fc;
-		var inner_node = ((MemberAccess)stmt.resource).inner;
-		
-		if (inner_node  == null) {
-			l = new CCodeIdentifier ("self");
-		} else if (stmt.resource.symbol_reference.parent_symbol != current_type_symbol) {
-			 l = new InstanceCast ((CCodeExpression) inner_node.ccodenode, (TypeSymbol) stmt.resource.symbol_reference.parent_symbol);
-		} else {
-			l = (CCodeExpression) inner_node.ccodenode;
-		}
-		l = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (l, "priv"), get_symbol_lock_name (stmt.resource.symbol_reference));
-		
-		fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("lock")).get_cname ()));
-		fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-
-		cn.append (new CCodeExpressionStatement (fc));
-		
-		cn.append (stmt.body.ccodenode);
-		
-		fc = new CCodeFunctionCall (new CCodeIdentifier (((Method) mutex_type.scope.lookup ("unlock")).get_cname ()));
-		fc.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, l));
-		cn.append (new CCodeExpressionStatement (fc));
-		
-		stmt.ccodenode = cn;
+		head.visit_lock_statement (stmt);
 	}
 
 	public override void visit_delete_statement (DeleteStatement stmt) {
-		stmt.accept_children (this);
-
-		var pointer_type = (PointerType) stmt.expression.value_type;
-		DataType type = pointer_type;
-		if (pointer_type.base_type.data_type != null && pointer_type.base_type.data_type.is_reference_type ()) {
-			type = pointer_type.base_type;
-		}
-
-		var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
-		ccall.add_argument ((CCodeExpression) stmt.expression.ccodenode);
-		stmt.ccodenode = new CCodeExpressionStatement (ccall);
+		head.visit_delete_statement (stmt);
 	}
 
 	public override void visit_expression (Expression expr) {
-		if (expr.ccodenode != null && !expr.lvalue) {
-			// memory management, implicit casts, and boxing/unboxing
-			expr.ccodenode = transform_expression ((CCodeExpression) expr.ccodenode, expr.value_type, expr.target_type, expr);
-		}
+		head.visit_expression (expr);
 	}
 
 	public override void visit_array_creation_expression (ArrayCreationExpression expr) {
@@ -2827,37 +236,31 @@
 	}
 
 	public override void visit_boolean_literal (BooleanLiteral expr) {
-		expr.ccodenode = new CCodeConstant (expr.value ? "TRUE" : "FALSE");
+		head.visit_boolean_literal (expr);
 	}
 
 	public override void visit_character_literal (CharacterLiteral expr) {
-		if (expr.get_char () >= 0x20 && expr.get_char () < 0x80) {
-			expr.ccodenode = new CCodeConstant (expr.value);
-		} else {
-			expr.ccodenode = new CCodeConstant ("%uU".printf (expr.get_char ()));
-		}
+		head.visit_character_literal (expr);
 	}
 
 	public override void visit_integer_literal (IntegerLiteral expr) {
-		expr.ccodenode = new CCodeConstant (expr.value);
+		head.visit_integer_literal (expr);
 	}
 
 	public override void visit_real_literal (RealLiteral expr) {
-		expr.ccodenode = new CCodeConstant (expr.value);
+		head.visit_real_literal (expr);
 	}
 
 	public override void visit_string_literal (StringLiteral expr) {
-		expr.ccodenode = new CCodeConstant (expr.value);
+		head.visit_string_literal (expr);
 	}
 
 	public override void visit_null_literal (NullLiteral expr) {
-		expr.ccodenode = new CCodeConstant ("NULL");
+		head.visit_null_literal (expr);
 	}
 
 	public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
-		expr.accept_children (this);
-
-		expr.ccodenode = new CCodeParenthesizedExpression ((CCodeExpression) expr.inner.ccodenode);
+		head.visit_parenthesized_expression (expr);
 	}
 
 	public override void visit_member_access (MemberAccess expr) {
@@ -2868,1426 +271,67 @@
 		head.visit_invocation_expression (expr);
 	}
 	
-	public string get_delegate_target_cname (string delegate_cname) {
-		return "%s_target".printf (delegate_cname);
-	}
-
-	public CCodeExpression get_delegate_target_cexpression (Expression delegate_expr) {
-		bool is_out = false;
-	
-		if (delegate_expr is UnaryExpression) {
-			var unary_expr = (UnaryExpression) delegate_expr;
-			if (unary_expr.operator == UnaryOperator.OUT || unary_expr.operator == UnaryOperator.REF) {
-				delegate_expr = unary_expr.inner;
-				is_out = true;
-			}
-		}
-		
-		if (delegate_expr is InvocationExpression) {
-			var invocation_expr = (InvocationExpression) delegate_expr;
-			return invocation_expr.delegate_target;
-		} else if (delegate_expr is LambdaExpression) {
-			if ((current_method != null && current_method.binding == MemberBinding.INSTANCE) || in_constructor) {
-				return new CCodeIdentifier ("self");
-			} else {
-				return new CCodeConstant ("NULL");
-			}
-		} else if (delegate_expr.symbol_reference != null) {
-			if (delegate_expr.symbol_reference is FormalParameter) {
-				var param = (FormalParameter) delegate_expr.symbol_reference;
-				CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (param.name));
-				if (param.direction != ParameterDirection.IN) {
-					// accessing argument of out/ref param
-					target_expr = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr));
-				}
-				if (is_out) {
-					// passing array as out/ref
-					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
-				} else {
-					return target_expr;
-				}
-			} else if (delegate_expr.symbol_reference is LocalVariable) {
-				var local = (LocalVariable) delegate_expr.symbol_reference;
-				var target_expr = new CCodeIdentifier (get_delegate_target_cname (local.name));
-				if (is_out) {
-					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
-				} else {
-					return target_expr;
-				}
-			} else if (delegate_expr.symbol_reference is Field) {
-				var field = (Field) delegate_expr.symbol_reference;
-				var target_cname = get_delegate_target_cname (field.name);
-
-				var ma = (MemberAccess) delegate_expr;
-
-				var base_type = ma.inner.value_type;
-				CCodeExpression target_expr = null;
-
-				var pub_inst = (CCodeExpression) get_ccodenode (ma.inner);
-
-				if (field.binding == MemberBinding.INSTANCE) {
-					var instance_expression_type = base_type;
-					var instance_target_type = get_data_type_for_symbol ((TypeSymbol) field.parent_symbol);
-					CCodeExpression typed_inst = transform_expression (pub_inst, instance_expression_type, instance_target_type);
-
-					CCodeExpression inst;
-					if (field.access == SymbolAccessibility.PRIVATE) {
-						inst = new CCodeMemberAccess.pointer (typed_inst, "priv");
-					} else {
-						inst = typed_inst;
-					}
-					if (((TypeSymbol) field.parent_symbol).is_reference_type ()) {
-						target_expr = new CCodeMemberAccess.pointer (inst, target_cname);
-					} else {
-						target_expr = new CCodeMemberAccess (inst, target_cname);
-					}
-				} else {
-					target_expr = new CCodeIdentifier (target_cname);
-				}
-
-				if (is_out) {
-					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
-				} else {
-					return target_expr;
-				}
-			} else if (delegate_expr.symbol_reference is Method) {
-				var m = (Method) delegate_expr.symbol_reference;
-				var ma = (MemberAccess) delegate_expr;
-				if (m.binding == MemberBinding.STATIC) {
-					return new CCodeConstant ("NULL");
-				} else {
-					return (CCodeExpression) get_ccodenode (ma.inner);
-				}
-			}
-		}
-
-		return new CCodeConstant ("NULL");
-	}
-
-	public string get_delegate_target_destroy_notify_cname (string delegate_cname) {
-		return "%s_target_destroy_notify".printf (delegate_cname);
-	}
-
 	public override void visit_element_access (ElementAccess expr) {
 		head.visit_element_access (expr);
 	}
 
 	public override void visit_base_access (BaseAccess expr) {
-		expr.ccodenode = new InstanceCast (new CCodeIdentifier ("self"), expr.value_type.data_type);
+		head.visit_base_access (expr);
 	}
 
 	public override void visit_postfix_expression (PostfixExpression expr) {
-		MemberAccess ma = find_property_access (expr.inner);
-		if (ma != null) {
-			// property postfix expression
-			var prop = (Property) ma.symbol_reference;
-			
-			var ccomma = new CCodeCommaExpression ();
-			
-			// assign current value to temp variable
-			var temp_decl = get_temp_variable (prop.property_type, true, expr);
-			temp_vars.insert (0, temp_decl);
-			ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), (CCodeExpression) expr.inner.ccodenode));
-			
-			// increment/decrement property
-			var op = expr.increment ? CCodeBinaryOperator.PLUS : CCodeBinaryOperator.MINUS;
-			var cexpr = new CCodeBinaryExpression (op, new CCodeIdentifier (temp_decl.name), new CCodeConstant ("1"));
-			var ccall = get_property_set_call (prop, ma, cexpr);
-			ccomma.append_expression (ccall);
-			
-			// return previous value
-			ccomma.append_expression (new CCodeIdentifier (temp_decl.name));
-			
-			expr.ccodenode = ccomma;
-			return;
-		}
-	
-		var op = expr.increment ? CCodeUnaryOperator.POSTFIX_INCREMENT : CCodeUnaryOperator.POSTFIX_DECREMENT;
-	
-		expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
-	}
-	
-	private MemberAccess? find_property_access (Expression expr) {
-		if (expr is ParenthesizedExpression) {
-			var pe = (ParenthesizedExpression) expr;
-			return find_property_access (pe.inner);
-		}
-	
-		if (!(expr is MemberAccess)) {
-			return null;
-		}
-		
-		var ma = (MemberAccess) expr;
-		if (ma.symbol_reference is Property) {
-			return ma;
-		}
-		
-		return null;
-	}
-
-	public bool requires_copy (DataType type) {
-		if (!type.is_disposable ()) {
-			return false;
-		}
-
-		if (type.type_parameter != null) {
-			if (!(current_type_symbol is Class) || current_class.is_compact) {
-				return false;
-			}
-		}
-
-		return true;
-	}
-
-	public bool requires_destroy (DataType type) {
-		if (!type.is_disposable ()) {
-			return false;
-		}
-
-		if (type.type_parameter != null) {
-			if (!(current_type_symbol is Class) || current_class.is_compact) {
-				return false;
-			}
-		}
-
-		return true;
-	}
-
-	private CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
-		if (expression_type is ValueType && !expression_type.nullable) {
-			// normal value type, no null check
-			// (copy (&expr, &temp), temp)
-
-			var decl = get_temp_variable (expression_type, false, node);
-			temp_vars.insert (0, decl);
-
-			var ctemp = new CCodeIdentifier (decl.name);
-			
-			var vt = (ValueType) expression_type;
-			var st = (Struct) vt.type_symbol;
-			var copy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_copy_function ()));
-			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr));
-			copy_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
-
-			var ccomma = new CCodeCommaExpression ();
-			ccomma.append_expression (copy_call);
-			ccomma.append_expression (ctemp);
-
-			return ccomma;
-		}
-
-		/* (temp = expr, temp == NULL ? NULL : ref (temp))
-		 *
-		 * can be simplified to
-		 * ref (expr)
-		 * if static type of expr is non-null
-		 */
-		 
-		var dupexpr = get_dup_func_expression (expression_type, node.source_reference);
-
-		if (dupexpr == null) {
-			node.error = true;
-			return null;
-		}
-
-		var ccall = new CCodeFunctionCall (dupexpr);
-
-		if (expr != null && expr.is_non_null ()) {
-			// expression is non-null
-			ccall.add_argument ((CCodeExpression) expr.ccodenode);
-			
-			return ccall;
-		} else {
-			var decl = get_temp_variable (expression_type, false, node);
-			temp_vars.insert (0, decl);
-
-			var ctemp = new CCodeIdentifier (decl.name);
-			
-			var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, new CCodeConstant ("NULL"));
-			if (expression_type.type_parameter != null) {
-				if (!(current_type_symbol is Class)) {
-					return cexpr;
-				}
-
-				// dup functions are optional for type parameters
-				var cdupisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, get_dup_func_expression (expression_type, node.source_reference), new CCodeConstant ("NULL"));
-				cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cisnull, cdupisnull);
-			}
-
-			if (expression_type.type_parameter != null) {
-				// cast from gconstpointer to gpointer as GBoxedCopyFunc expects gpointer
-				ccall.add_argument (new CCodeCastExpression (ctemp, "gpointer"));
-			} else {
-				ccall.add_argument (ctemp);
-			}
-
-			if (expression_type is ArrayType) {
-				var array_type = (ArrayType) expression_type;
-				bool first = true;
-				CCodeExpression csizeexpr = null;
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					if (first) {
-						csizeexpr = head.get_array_length_cexpression (expr, dim);
-						first = false;
-					} else {
-						csizeexpr = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeexpr, head.get_array_length_cexpression (expr, dim));
-					}
-				}
-
-				ccall.add_argument (csizeexpr);
-			}
-
-			var ccomma = new CCodeCommaExpression ();
-			ccomma.append_expression (new CCodeAssignment (ctemp, cexpr));
-
-			CCodeExpression cifnull;
-			if (expression_type.data_type != null) {
-				cifnull = new CCodeConstant ("NULL");
-			} else {
-				// the value might be non-null even when the dup function is null,
-				// so we may not just use NULL for type parameters
-
-				// cast from gconstpointer to gpointer as methods in
-				// generic classes may not return gconstpointer
-				cifnull = new CCodeCastExpression (ctemp, "gpointer");
-			}
-			ccomma.append_expression (new CCodeConditionalExpression (cisnull, cifnull, ccall));
-
-			return ccomma;
-		}
+		head.visit_postfix_expression (expr);
 	}
 
 	public override void visit_object_creation_expression (ObjectCreationExpression expr) {
-		expr.accept_children (this);
-
-		CCodeExpression instance = null;
-		CCodeExpression creation_expr = null;
-
-		var st = expr.type_reference.data_type as Struct;
-		if ((st != null && !st.is_simple_type ()) || expr.get_object_initializer ().size > 0) {
-			// value-type initialization or object creation expression with object initializer
-			var temp_decl = get_temp_variable (expr.type_reference, false, expr);
-			temp_vars.add (temp_decl);
-
-			instance = new CCodeIdentifier (get_variable_cname (temp_decl.name));
-		}
-
-		if (expr.symbol_reference == null) {
-			CCodeFunctionCall creation_call;
-
-			// no creation method
-			if (expr.type_reference.data_type == glist_type ||
-			    expr.type_reference.data_type == gslist_type) {
-				// NULL is an empty list
-				expr.ccodenode = new CCodeConstant ("NULL");
-			} else if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) {
-				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_object_new"));
-				creation_call.add_argument (new CCodeConstant (expr.type_reference.data_type.get_type_id ()));
-				creation_call.add_argument (new CCodeConstant ("NULL"));
-			} else if (expr.type_reference.data_type is Class) {
-				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
-				creation_call.add_argument (new CCodeConstant (expr.type_reference.data_type.get_cname ()));
-				creation_call.add_argument (new CCodeConstant ("1"));
-			} else if (expr.type_reference.data_type is Struct) {
-				// memset needs string.h
-				string_h_needed = true;
-				creation_call = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
-				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
-				creation_call.add_argument (new CCodeConstant ("0"));
-				creation_call.add_argument (new CCodeIdentifier ("sizeof (%s)".printf (expr.type_reference.get_cname ())));
-			}
-
-			creation_expr = creation_call;
-		} else if (expr.symbol_reference is Method) {
-			// use creation method
-			var m = (Method) expr.symbol_reference;
-			var params = m.get_parameters ();
-			CCodeFunctionCall creation_call;
-
-			creation_call = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
-
-			if ((st != null && !st.is_simple_type ()) && !(m.cinstance_parameter_position < 0)) {
-				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
-			}
-
-			var cl = expr.type_reference.data_type as Class;
-			if (cl != null && !cl.is_compact) {
-				foreach (DataType type_arg in expr.type_reference.get_type_arguments ()) {
-					creation_call.add_argument (get_type_id_expression (type_arg));
-					if (requires_copy (type_arg)) {
-						var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference);
-						if (dup_func == null) {
-							// type doesn't contain a copy function
-							expr.error = true;
-							return;
-						}
-						creation_call.add_argument (new CCodeCastExpression (dup_func, "GBoxedCopyFunc"));
-						creation_call.add_argument (get_destroy_func_expression (type_arg));
-					} else {
-						creation_call.add_argument (new CCodeConstant ("NULL"));
-						creation_call.add_argument (new CCodeConstant ("NULL"));
-					}
-				}
-			}
-
-			var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
-
-			bool ellipsis = false;
-
-			int i = 1;
-			int arg_pos;
-			Iterator<FormalParameter> params_it = params.iterator ();
-			foreach (Expression arg in expr.get_argument_list ()) {
-				CCodeExpression cexpr = (CCodeExpression) arg.ccodenode;
-				FormalParameter param = null;
-				if (params_it.next ()) {
-					param = params_it.get ();
-					ellipsis = param.ellipsis;
-					if (!ellipsis) {
-						if (!param.no_array_length && param.parameter_type is ArrayType) {
-							var array_type = (ArrayType) param.parameter_type;
-							for (int dim = 1; dim <= array_type.rank; dim++) {
-								carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), head.get_array_length_cexpression (arg, dim));
-							}
-						} else if (param.parameter_type is DelegateType) {
-							var deleg_type = (DelegateType) param.parameter_type;
-							var d = deleg_type.delegate_symbol;
-							if (d.has_target) {
-								var delegate_target = get_delegate_target_cexpression (arg);
-								carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
-							}
-						}
-
-						cexpr = handle_struct_argument (param, arg, cexpr);
-					}
-
-					arg_pos = get_param_pos (param.cparameter_position, ellipsis);
-				} else {
-					// default argument position
-					arg_pos = get_param_pos (i, ellipsis);
-				}
-			
-				carg_map.set (arg_pos, cexpr);
-
-				i++;
-			}
-			while (params_it.next ()) {
-				var param = params_it.get ();
-				
-				if (param.ellipsis) {
-					ellipsis = true;
-					break;
-				}
-				
-				if (param.default_expression == null) {
-					Report.error (expr.source_reference, "no default expression for argument %d".printf (i));
-					return;
-				}
-				
-				/* evaluate default expression here as the code
-				 * generator might not have visited the formal
-				 * parameter yet */
-				param.default_expression.accept (this);
-			
-				carg_map.set (get_param_pos (param.cparameter_position), (CCodeExpression) param.default_expression.ccodenode);
-				i++;
-			}
-
-			// append C arguments in the right order
-			int last_pos = -1;
-			int min_pos;
-			while (true) {
-				min_pos = -1;
-				foreach (int pos in carg_map.get_keys ()) {
-					if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
-						min_pos = pos;
-					}
-				}
-				if (min_pos == -1) {
-					break;
-				}
-				creation_call.add_argument (carg_map.get (min_pos));
-				last_pos = min_pos;
-			}
-
-			if ((st != null && !st.is_simple_type ()) && m.cinstance_parameter_position < 0) {
-				// instance parameter is at the end in a struct creation method
-				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
-			}
-
-			if (expr.tree_can_fail) {
-				// method can fail
-				current_method_inner_error = true;
-				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
-			}
-
-			if (ellipsis) {
-				/* ensure variable argument list ends with NULL
-				 * except when using printf-style arguments */
-				if (!m.printf_format && m.sentinel != "") {
-					creation_call.add_argument (new CCodeConstant (m.sentinel));
-				}
-			}
-
-			creation_expr = creation_call;
-
-			// cast the return value of the creation method back to the intended type if
-			// it requested a special C return type
-			if (head.get_custom_creturn_type (m) != null) {
-				creation_expr = new CCodeCastExpression (creation_expr, expr.type_reference.get_cname ());
-			}
-		} else if (expr.symbol_reference is ErrorCode) {
-			var ecode = (ErrorCode) expr.symbol_reference;
-			var edomain = (ErrorDomain) ecode.parent_symbol;
-			CCodeFunctionCall creation_call;
-
-			creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_new"));
-			creation_call.add_argument (new CCodeIdentifier (edomain.get_upper_case_cname ()));
-			creation_call.add_argument (new CCodeIdentifier (ecode.get_cname ()));
-
-			foreach (Expression arg in expr.get_argument_list ()) {
-				creation_call.add_argument ((CCodeExpression) arg.ccodenode);
-			}
-
-			creation_expr = creation_call;
-		} else {
-			assert (false);
-		}
-			
-		if (instance != null) {
-			var ccomma = new CCodeCommaExpression ();
-
-			if (expr.type_reference.data_type is Struct) {
-				ccomma.append_expression (creation_expr);
-			} else {
-				ccomma.append_expression (new CCodeAssignment (instance, creation_expr));
-			}
-
-			foreach (MemberInitializer init in expr.get_object_initializer ()) {
-				if (init.symbol_reference is Field) {
-					var f = (Field) init.symbol_reference;
-					var instance_target_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
-					var typed_inst = transform_expression (instance, expr.type_reference, instance_target_type);
-					CCodeExpression lhs;
-					if (expr.type_reference.data_type is Struct) {
-						lhs = new CCodeMemberAccess (typed_inst, f.get_cname ());
-					} else {
-						lhs = new CCodeMemberAccess.pointer (typed_inst, f.get_cname ());
-					}
-					ccomma.append_expression (new CCodeAssignment (lhs, (CCodeExpression) init.initializer.ccodenode));
-				} else if (init.symbol_reference is Property) {
-					var inst_ma = new MemberAccess.simple ("new");
-					inst_ma.value_type = expr.type_reference;
-					inst_ma.ccodenode = instance;
-					var ma = new MemberAccess (inst_ma, init.name);
-					ccomma.append_expression (get_property_set_call ((Property) init.symbol_reference, ma, (CCodeExpression) init.initializer.ccodenode));
-				}
-			}
-
-			ccomma.append_expression (instance);
-
-			expr.ccodenode = ccomma;
-		} else if (creation_expr != null) {
-			expr.ccodenode = creation_expr;
-		}
-	}
-
-	public CCodeExpression? handle_struct_argument (FormalParameter param, Expression arg, CCodeExpression? cexpr) {
-		// pass non-simple struct instances always by reference
-		if (!(arg.value_type is NullType) && param.parameter_type.data_type is Struct && !((Struct) param.parameter_type.data_type).is_simple_type ()) {
-			// we already use a reference for arguments of ref, out, and nullable parameters
-			if (param.direction == ParameterDirection.IN && !param.parameter_type.nullable) {
-				var unary = cexpr as CCodeUnaryExpression;
-				if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
-					// *expr => expr
-					return unary.inner;
-				} else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
-					return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
-				} else {
-					// if cexpr is e.g. a function call, we can't take the address of the expression
-					// (tmp = expr, &tmp)
-					var ccomma = new CCodeCommaExpression ();
-
-					var temp_var = get_temp_variable (arg.value_type);
-					temp_vars.insert (0, temp_var);
-					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), cexpr));
-					ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
-
-					return ccomma;
-				}
-			}
-		}
-
-		return cexpr;
+		head.visit_object_creation_expression (expr);
 	}
 
 	public override void visit_sizeof_expression (SizeofExpression expr) {
-		var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
-		csizeof.add_argument (new CCodeIdentifier (expr.type_reference.get_cname ()));
-		expr.ccodenode = csizeof;
+		head.visit_sizeof_expression (expr);
 	}
 
 	public override void visit_typeof_expression (TypeofExpression expr) {
-		expr.ccodenode = get_type_id_expression (expr.type_reference);
+		head.visit_typeof_expression (expr);
 	}
 
 	public override void visit_unary_expression (UnaryExpression expr) {
-		expr.accept_children (this);
-
-		CCodeUnaryOperator op;
-		if (expr.operator == UnaryOperator.PLUS) {
-			op = CCodeUnaryOperator.PLUS;
-		} else if (expr.operator == UnaryOperator.MINUS) {
-			op = CCodeUnaryOperator.MINUS;
-		} else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) {
-			op = CCodeUnaryOperator.LOGICAL_NEGATION;
-		} else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
-			op = CCodeUnaryOperator.BITWISE_COMPLEMENT;
-		} else if (expr.operator == UnaryOperator.INCREMENT) {
-			op = CCodeUnaryOperator.PREFIX_INCREMENT;
-		} else if (expr.operator == UnaryOperator.DECREMENT) {
-			op = CCodeUnaryOperator.PREFIX_DECREMENT;
-		} else if (expr.operator == UnaryOperator.REF) {
-			op = CCodeUnaryOperator.ADDRESS_OF;
-		} else if (expr.operator == UnaryOperator.OUT) {
-			op = CCodeUnaryOperator.ADDRESS_OF;
-		}
-		expr.ccodenode = new CCodeUnaryExpression (op, (CCodeExpression) expr.inner.ccodenode);
+		head.visit_unary_expression (expr);
 	}
 
 	public override void visit_cast_expression (CastExpression expr) {
-		var cl = expr.type_reference.data_type as Class;
-		var iface = expr.type_reference.data_type as Interface;
-		if (iface != null || (cl != null && !cl.is_compact)) {
-			// checked cast for strict subtypes of GTypeInstance
-			if (expr.is_silent_cast) {
-				var ccomma = new CCodeCommaExpression ();
-				var temp_decl = get_temp_variable (expr.inner.value_type, true, expr);
-
-				temp_vars.add (temp_decl);
-
-				var ctemp = new CCodeIdentifier (temp_decl.name);
-				var cinit = new CCodeAssignment (ctemp, (CCodeExpression) expr.inner.ccodenode);
-				var ccheck = create_type_check (ctemp, expr.type_reference);
-				var ccast = new CCodeCastExpression (ctemp, expr.type_reference.get_cname ());
-				var cnull = new CCodeConstant ("NULL");
-
-				ccomma.append_expression (cinit);
-				ccomma.append_expression (new CCodeConditionalExpression (ccheck, ccast, cnull));
-	
-				expr.ccodenode = ccomma;
-			} else {
-				expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type);
-			}
-		} else {
-			if (expr.is_silent_cast) {
-				expr.error = true;
-				Report.error (expr.source_reference, "Operation not supported for this type");
-				return;
-			}
-			expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
-		}
+		head.visit_cast_expression (expr);
 	}
 	
 	public override void visit_pointer_indirection (PointerIndirection expr) {
-		expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, (CCodeExpression) expr.inner.ccodenode);
+		head.visit_pointer_indirection (expr);
 	}
 
 	public override void visit_addressof_expression (AddressofExpression expr) {
-		expr.ccodenode = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode);
+		head.visit_addressof_expression (expr);
 	}
 
 	public override void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
-		expr.accept_children (this);
-
-		/* (tmp = var, var = null, tmp) */
-		var ccomma = new CCodeCommaExpression ();
-		var temp_decl = get_temp_variable (expr.value_type, true, expr);
-		temp_vars.insert (0, temp_decl);
-		var cvar = new CCodeIdentifier (temp_decl.name);
-
-		ccomma.append_expression (new CCodeAssignment (cvar, (CCodeExpression) expr.inner.ccodenode));
-		ccomma.append_expression (new CCodeAssignment ((CCodeExpression) expr.inner.ccodenode, new CCodeConstant ("NULL")));
-		ccomma.append_expression (cvar);
-		expr.ccodenode = ccomma;
+		head.visit_reference_transfer_expression (expr);
 	}
 
 	public override void visit_binary_expression (BinaryExpression expr) {
-		var cleft = (CCodeExpression) expr.left.ccodenode;
-		var cright = (CCodeExpression) expr.right.ccodenode;
-		
-		CCodeBinaryOperator op;
-		if (expr.operator == BinaryOperator.PLUS) {
-			op = CCodeBinaryOperator.PLUS;
-		} else if (expr.operator == BinaryOperator.MINUS) {
-			op = CCodeBinaryOperator.MINUS;
-		} else if (expr.operator == BinaryOperator.MUL) {
-			op = CCodeBinaryOperator.MUL;
-		} else if (expr.operator == BinaryOperator.DIV) {
-			op = CCodeBinaryOperator.DIV;
-		} else if (expr.operator == BinaryOperator.MOD) {
-			op = CCodeBinaryOperator.MOD;
-		} else if (expr.operator == BinaryOperator.SHIFT_LEFT) {
-			op = CCodeBinaryOperator.SHIFT_LEFT;
-		} else if (expr.operator == BinaryOperator.SHIFT_RIGHT) {
-			op = CCodeBinaryOperator.SHIFT_RIGHT;
-		} else if (expr.operator == BinaryOperator.LESS_THAN) {
-			op = CCodeBinaryOperator.LESS_THAN;
-		} else if (expr.operator == BinaryOperator.GREATER_THAN) {
-			op = CCodeBinaryOperator.GREATER_THAN;
-		} else if (expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL) {
-			op = CCodeBinaryOperator.LESS_THAN_OR_EQUAL;
-		} else if (expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
-			op = CCodeBinaryOperator.GREATER_THAN_OR_EQUAL;
-		} else if (expr.operator == BinaryOperator.EQUALITY) {
-			op = CCodeBinaryOperator.EQUALITY;
-		} else if (expr.operator == BinaryOperator.INEQUALITY) {
-			op = CCodeBinaryOperator.INEQUALITY;
-		} else if (expr.operator == BinaryOperator.BITWISE_AND) {
-			op = CCodeBinaryOperator.BITWISE_AND;
-		} else if (expr.operator == BinaryOperator.BITWISE_OR) {
-			op = CCodeBinaryOperator.BITWISE_OR;
-		} else if (expr.operator == BinaryOperator.BITWISE_XOR) {
-			op = CCodeBinaryOperator.BITWISE_XOR;
-		} else if (expr.operator == BinaryOperator.AND) {
-			op = CCodeBinaryOperator.AND;
-		} else if (expr.operator == BinaryOperator.OR) {
-			op = CCodeBinaryOperator.OR;
-		} else if (expr.operator == BinaryOperator.IN) {
-			var container_type = expr.right.value_type.data_type;
-			if (container_type != null && collection_type != null && map_type != null &&
-		           (container_type.is_subtype_of (collection_type) || container_type.is_subtype_of (map_type))) {
-				Method contains_method;
-				if (container_type.is_subtype_of (collection_type)) {
-					contains_method = (Method) collection_type.scope.lookup ("contains");
-					assert (contains_method != null);
-					var contains_ccall = new CCodeFunctionCall (new CCodeIdentifier (contains_method.get_cname ()));
-					contains_ccall.add_argument (new InstanceCast (cright, collection_type));
-					contains_ccall.add_argument (cleft);
-					expr.ccodenode = contains_ccall;
-				} else {
-					contains_method = (Method) map_type.scope.lookup ("contains");
-					assert (contains_method != null);
-					var contains_ccall = new CCodeFunctionCall (new CCodeIdentifier (contains_method.get_cname ()));
-					contains_ccall.add_argument (new InstanceCast (cright, map_type));
-					contains_ccall.add_argument (cleft);
-					expr.ccodenode = contains_ccall;
-				}
-				return;
-			}
-		
-			expr.ccodenode = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeParenthesizedExpression (new CCodeBinaryExpression (CCodeBinaryOperator.BITWISE_AND, new CCodeParenthesizedExpression (cright), new CCodeParenthesizedExpression (cleft))), new CCodeParenthesizedExpression (cleft));
-			return;
-		}
-		
-		if (expr.operator == BinaryOperator.EQUALITY ||
-		    expr.operator == BinaryOperator.INEQUALITY) {
-			var left_type_as_struct = expr.left.value_type.data_type as Struct;
-			var right_type_as_struct = expr.right.value_type.data_type as Struct;
-
-			if (expr.left.value_type.data_type is Class && !((Class) expr.left.value_type.data_type).is_compact &&
-			    expr.right.value_type.data_type is Class && !((Class) expr.right.value_type.data_type).is_compact) {
-				var left_cl = (Class) expr.left.value_type.data_type;
-				var right_cl = (Class) expr.right.value_type.data_type;
-				
-				if (left_cl != right_cl) {
-					if (left_cl.is_subtype_of (right_cl)) {
-						cleft = new InstanceCast (cleft, right_cl);
-					} else if (right_cl.is_subtype_of (left_cl)) {
-						cright = new InstanceCast (cright, left_cl);
-					}
-				}
-			} else if (left_type_as_struct != null && expr.right.value_type is NullType) {
-				cleft = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cleft);
-			} else if (right_type_as_struct != null && expr.left.value_type is NullType) {
-				cright = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cright);
-			}
-		}
-
-		if (!(expr.left.value_type is NullType)
-		    && expr.left.value_type.compatible (string_type)
-		    && !(expr.right.value_type is NullType)
-		    && expr.right.value_type.compatible (string_type)) {
-			if (expr.operator == BinaryOperator.PLUS) {
-				// string concatenation
-				if (expr.left.is_constant () && expr.right.is_constant ()) {
-					string left, right;
-
-					if (cleft is CCodeIdentifier) {
-						left = ((CCodeIdentifier) cleft).name;
-					} else if (cleft is CCodeConstant) {
-						left = ((CCodeConstant) cleft).name;
-					}
-					if (cright is CCodeIdentifier) {
-						right = ((CCodeIdentifier) cright).name;
-					} else if (cright is CCodeConstant) {
-						right = ((CCodeConstant) cright).name;
-					}
-
-					expr.ccodenode = new CCodeConstant ("%s %s".printf (left, right));
-					return;
-				} else {
-					// convert to g_strconcat (a, b, NULL)
-					var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat"));
-					ccall.add_argument (cleft);
-					ccall.add_argument (cright);
-					ccall.add_argument (new CCodeConstant("NULL"));
-					expr.ccodenode = ccall;
-					return;
-				}
-			} else if (expr.operator == BinaryOperator.EQUALITY
-			           || expr.operator == BinaryOperator.INEQUALITY
-			           || expr.operator == BinaryOperator.LESS_THAN
-			           || expr.operator == BinaryOperator.GREATER_THAN
-			           || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
-			           || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
-				requires_strcmp0 = true;
-				var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_strcmp0"));
-				ccall.add_argument (cleft);
-				ccall.add_argument (cright);
-				cleft = ccall;
-				cright = new CCodeConstant ("0");
-			}
-		}
-
-		expr.ccodenode = new CCodeBinaryExpression (op, cleft, cright);
-	}
-
-	public string get_type_check_function (TypeSymbol type) {
-		var cl = type as Class;
-		if (cl != null && cl.type_check_function != null) {
-			return cl.type_check_function;
-		} else {
-			return type.get_upper_case_cname ("IS_");
-		}
-	}
-
-	CCodeExpression create_type_check (CCodeNode ccodenode, DataType type) {
-		var et = type as ErrorType;
-		if (et != null && et.error_code != null) {
-			var matches_call = new CCodeFunctionCall (new CCodeIdentifier ("g_error_matches"));
-			matches_call.add_argument ((CCodeExpression) ccodenode);
-			matches_call.add_argument (new CCodeIdentifier (et.error_domain.get_upper_case_cname ()));
-			matches_call.add_argument (new CCodeIdentifier (et.error_code.get_cname ()));
-			return matches_call;
-		} else if (et != null && et.error_domain != null) {
-			var instance_domain = new CCodeMemberAccess.pointer ((CCodeExpression) ccodenode, "domain");
-			var type_domain = new CCodeIdentifier (et.error_domain.get_upper_case_cname ());
-			return new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, instance_domain, type_domain);
-		} else {
-			var ccheck = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (type.data_type)));
-			ccheck.add_argument ((CCodeExpression) ccodenode);
-			return ccheck;
-		}
+		head.visit_binary_expression (expr);
 	}
 
 	public override void visit_type_check (TypeCheck expr) {
-		expr.ccodenode = create_type_check (expr.expression.ccodenode, expr.type_reference);
+		head.visit_type_check (expr);
 	}
 
 	public override void visit_conditional_expression (ConditionalExpression expr) {
-		expr.ccodenode = new CCodeConditionalExpression ((CCodeExpression) expr.condition.ccodenode, (CCodeExpression) expr.true_expression.ccodenode, (CCodeExpression) expr.false_expression.ccodenode);
+		head.visit_conditional_expression (expr);
 	}
 
 	public override void visit_lambda_expression (LambdaExpression l) {
-		// use instance position from delegate
-		var dt = (DelegateType) l.target_type;
-		l.method.cinstance_parameter_position = dt.delegate_symbol.cinstance_parameter_position;
-
-		var old_temp_vars = temp_vars;
-		var old_temp_ref_vars = temp_ref_vars;
-		temp_vars = new ArrayList<LocalVariable> ();
-		temp_ref_vars = new ArrayList<LocalVariable> ();
-
-		l.accept_children (this);
-
-		temp_vars = old_temp_vars;
-		temp_ref_vars = old_temp_ref_vars;
-
-		l.ccodenode = new CCodeIdentifier (l.method.get_cname ());
-	}
-
-	public CCodeExpression convert_from_generic_pointer (CCodeExpression cexpr, DataType actual_type) {
-		var result = cexpr;
-		if (actual_type.data_type is Struct) {
-			var st = (Struct) actual_type.data_type;
-			if (st == uint_type.data_type) {
-				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_UINT"));
-				cconv.add_argument (cexpr);
-				result = cconv;
-			} else if (st == bool_type.data_type || st.is_integer_type ()) {
-				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_INT"));
-				cconv.add_argument (cexpr);
-				result = cconv;
-			}
-		} else if (actual_type.data_type != null && actual_type.data_type.is_reference_type ()) {
-			result = new CCodeCastExpression (cexpr, actual_type.get_cname ());
-		}
-		return result;
-	}
-
-	public CCodeExpression convert_to_generic_pointer (CCodeExpression cexpr, DataType actual_type) {
-		var result = cexpr;
-		if (actual_type.data_type is Struct) {
-			var st = (Struct) actual_type.data_type;
-			if (st == uint_type.data_type) {
-				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GUINT_TO_POINTER"));
-				cconv.add_argument (cexpr);
-				result = cconv;
-			} else if (st == bool_type.data_type || st.is_integer_type ()) {
-				var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GINT_TO_POINTER"));
-				cconv.add_argument (cexpr);
-				result = cconv;
-			}
-		}
-		return result;
-	}
-
-	// manage memory and implicit casts
-	public CCodeExpression transform_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
-		var cexpr = source_cexpr;
-		if (expression_type == null) {
-			return cexpr;
-		}
-
-
-		if (expression_type.value_owned
-		    && expression_type.floating_reference) {
-			/* constructor of GInitiallyUnowned subtype
-			 * returns floating reference, sink it
-			 */
-			var csink = new CCodeFunctionCall (new CCodeIdentifier ("g_object_ref_sink"));
-			csink.add_argument (cexpr);
-			
-			cexpr = csink;
-		}
-
-		bool boxing = (expression_type is ValueType && !expression_type.nullable
-		               && target_type is ValueType && target_type.nullable);
-		bool unboxing = (expression_type is ValueType && expression_type.nullable
-		                 && target_type is ValueType && !target_type.nullable);
-
-		if (expression_type.value_owned
-		    && (target_type == null || !target_type.value_owned || boxing || unboxing)) {
-			// value leaked, destroy it
-			var pointer_type = target_type as PointerType;
-			if (pointer_type != null && !(pointer_type.base_type is VoidType)) {
-				// manual memory management for non-void pointers
-				// 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.insert (0, decl);
-				temp_ref_vars.insert (0, decl);
-				cexpr = new CCodeParenthesizedExpression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), cexpr));
-
-				if (expression_type is ArrayType && expr != null) {
-					var array_type = (ArrayType) expression_type;
-					var ccomma = new CCodeCommaExpression ();
-					ccomma.append_expression (cexpr);
-					for (int dim = 1; dim <= array_type.rank; dim++) {
-						var len_decl = new LocalVariable (int_type.copy (), head.get_array_length_cname (decl.name, dim));
-						temp_vars.insert (0, len_decl);
-						ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (len_decl.name)), head.get_array_length_cexpression (expr, dim)));
-					}
-					ccomma.append_expression (new CCodeIdentifier (get_variable_cname (decl.name)));
-					cexpr = ccomma;
-				}
-			}
-		}
-
-		if (target_type == null) {
-			// value will be destroyed, no need for implicit casts
-			return cexpr;
-		}
-
-		if (boxing) {
-			// value needs to be boxed
-
-			var unary = cexpr as CCodeUnaryExpression;
-			if (unary != null && unary.operator == CCodeUnaryOperator.POINTER_INDIRECTION) {
-				// *expr => expr
-				cexpr = unary.inner;
-			} else if (cexpr is CCodeIdentifier || cexpr is CCodeMemberAccess) {
-				cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
-			} else {
-				var decl = get_temp_variable (expression_type, expression_type.value_owned, expression_type);
-				temp_vars.insert (0, decl);
-
-				var ccomma = new CCodeCommaExpression ();
-				ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (get_variable_cname (decl.name)), cexpr));
-				ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (get_variable_cname (decl.name))));
-				cexpr = ccomma;
-			}
-		} else if (unboxing) {
-			// unbox value
-
-			cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, cexpr);
-		} else {
-			cexpr = get_implicit_cast_expression (cexpr, expression_type, target_type, expr);
-		}
-
-		if (expression_type.is_type_argument) {
-			cexpr = convert_from_generic_pointer (cexpr, target_type);
-		} else if (target_type.is_type_argument) {
-			cexpr = convert_to_generic_pointer (cexpr, expression_type);
-		}
-
-		if (target_type.value_owned && (!expression_type.value_owned || boxing || unboxing)) {
-			// need to copy value
-			if (requires_copy (target_type) && !(expression_type is NullType)) {
-				CodeNode node = expr;
-				if (node == null) {
-					node = expression_type;
-				}
-				cexpr = get_ref_cexpression (target_type, cexpr, expr, node);
-			}
-		}
-
-		return cexpr;
-	}
-
-	private CCodeExpression get_implicit_cast_expression (CCodeExpression source_cexpr, DataType? expression_type, DataType? target_type, Expression? expr = null) {
-		var cexpr = source_cexpr;
-
-		if (expression_type.data_type != null && expression_type.data_type == target_type.data_type) {
-			// same type, no cast required
-			return cexpr;
-		}
-
-		if (expression_type is NullType) {
-			// null literal, no cast required when not converting to generic type pointer
-			return cexpr;
-		}
-
-		var cl = target_type.data_type as Class;
-		var iface = target_type.data_type as Interface;
-		if (context.checking && (iface != null || (cl != null && !cl.is_compact))) {
-			// checked cast for strict subtypes of GTypeInstance
-			return new InstanceCast (cexpr, target_type.data_type);
-		} else if (target_type.data_type != null && expression_type.get_cname () != target_type.get_cname ()) {
-			var st = target_type.data_type as Struct;
-			if (target_type.data_type.is_reference_type () || (st != null && st.is_simple_type ())) {
-				// don't cast non-simple structs
-				return new CCodeCastExpression (cexpr, target_type.get_cname ());
-			} else {
-				return cexpr;
-			}
-		} else if (target_type is DelegateType && expression_type is MethodType) {
-			var dt = (DelegateType) target_type;
-			var mt = (MethodType) expression_type;
-
-			var method = mt.method_symbol;
-			if (method.base_method != null) {
-				method = method.base_method;
-			} else if (method.base_interface_method != null) {
-				method = method.base_interface_method;
-			}
-
-			return new CCodeIdentifier (generate_delegate_wrapper (method, dt.delegate_symbol));
-		} else {
-			return cexpr;
-		}
-	}
-
-	private string generate_delegate_wrapper (Method m, Delegate d) {
-		string delegate_name;
-		var sig = d.parent_symbol as Signal;
-		var dynamic_sig = sig as DynamicSignal;
-		if (dynamic_sig != null) {
-			delegate_name = head.get_dynamic_signal_cname (dynamic_sig);
-		} else if (sig != null) {
-			delegate_name = sig.parent_symbol.get_lower_case_cprefix () + sig.get_cname ();
-		} else {
-			delegate_name = Symbol.camel_case_to_lower_case (d.get_cname ());
-		}
-
-		string wrapper_name = "_%s_%s".printf (m.get_cname (), delegate_name);
-
-		if (!add_wrapper (wrapper_name)) {
-			// wrapper already defined
-			return wrapper_name;
-		}
-
-		// declaration
-
-		var function = new CCodeFunction (wrapper_name, m.return_type.get_cname ());
-		function.modifiers = CCodeModifiers.STATIC;
-		m.ccodenode = function;
-
-		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
-
-		if (d.has_target) {
-			var cparam = new CCodeFormalParameter ("self", "gpointer");
-			cparam_map.set (get_param_pos (d.cinstance_parameter_position), cparam);
-		}
-
-		var d_params = d.get_parameters ();
-		foreach (FormalParameter param in d_params) {
-			// ensure that C code node has been generated
-			param.accept (this);
-
-			cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
-
-			// handle array parameters
-			if (!param.no_array_length && param.parameter_type is ArrayType) {
-				var array_type = (ArrayType) param.parameter_type;
-				
-				var length_ctype = "int";
-				if (param.direction != ParameterDirection.IN) {
-					length_ctype = "int*";
-				}
-				
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
-					cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
-				}
-			}
-
-		}
-
-		if (m.get_error_types ().size > 0) {
-			var cparam = new CCodeFormalParameter ("error", "GError**");
-			cparam_map.set (get_param_pos (-1), cparam);
-		}
-
-		// append C parameters in the right order
-		int last_pos = -1;
-		int min_pos;
-		while (true) {
-			min_pos = -1;
-			foreach (int pos in cparam_map.get_keys ()) {
-				if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
-					min_pos = pos;
-				}
-			}
-			if (min_pos == -1) {
-				break;
-			}
-			function.add_parameter (cparam_map.get (min_pos));
-			last_pos = min_pos;
-		}
-
-
-		// definition
-
-		var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
-
-		int i = 0;
-		if (m.binding == MemberBinding.INSTANCE) {
-			CCodeExpression arg;
-			if (d.has_target) {
-				arg = new CCodeIdentifier ("self");
-			} else {
-				// use first delegate parameter as instance
-				arg = new CCodeIdentifier ((d_params.get (0).ccodenode as CCodeFormalParameter).name);
-				i = 1;
-			}
-			carg_map.set (get_param_pos (m.cinstance_parameter_position), arg);
-		}
-
-		foreach (FormalParameter param in m.get_parameters ()) {
-			CCodeExpression arg;
-			arg = new CCodeIdentifier ((d_params.get (i).ccodenode as CCodeFormalParameter).name);
-			carg_map.set (get_param_pos (param.cparameter_position), arg);
-
-			// handle array arguments
-			if (!param.no_array_length && param.parameter_type is ArrayType) {
-				var array_type = (ArrayType) param.parameter_type;
-				for (int dim = 1; dim <= array_type.rank; dim++) {
-					CCodeExpression clength;
-					if (d_params.get (i).no_array_length) {
-						clength = new CCodeConstant ("-1");
-					} else {
-						clength = new CCodeIdentifier (head.get_array_length_cname (d_params.get (i).name, dim));
-					}
-					carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), clength);
-				}
-			}
-
-			i++;
-		}
-
-		if (m.get_error_types ().size > 0) {
-			carg_map.set (get_param_pos (-1), new CCodeIdentifier ("error"));
-		}
-
-		var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ()));
-
-		// append C arguments in the right order
-		last_pos = -1;
-		while (true) {
-			min_pos = -1;
-			foreach (int pos in carg_map.get_keys ()) {
-				if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
-					min_pos = pos;
-				}
-			}
-			if (min_pos == -1) {
-				break;
-			}
-			ccall.add_argument (carg_map.get (min_pos));
-			last_pos = min_pos;
-		}
-
-		var block = new CCodeBlock ();
-		if (m.return_type is VoidType) {
-			block.add_statement (new CCodeExpressionStatement (ccall));
-		} else {
-			block.add_statement (new CCodeReturnStatement (ccall));
-		}
-
-		// append to file
-
-		source_type_member_declaration.append (function.copy ());
-
-		function.block = block;
-		source_type_member_definition.append (function);
-
-		return wrapper_name;
+		head.visit_lambda_expression (l);
 	}
 
 	public override void visit_assignment (Assignment a) {
 		head.visit_assignment (a);
 	}
-
-	public CCodeFunctionCall get_property_set_call (Property prop, MemberAccess ma, CCodeExpression cexpr) {
-		if (ma.inner is BaseAccess) {
-			if (prop.base_property != null) {
-				var base_class = (Class) prop.base_property.parent_symbol;
-				var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
-				vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
-				
-				var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "set_%s".printf (prop.name)));
-				ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
-				ccall.add_argument (cexpr);
-				return ccall;
-			} else if (prop.base_interface_property != null) {
-				var base_iface = (Interface) prop.base_interface_property.parent_symbol;
-				string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
-
-				var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), "set_%s".printf (prop.name)));
-				ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
-				ccall.add_argument (cexpr);
-				return ccall;
-			}
-		}
-
-		var set_func = "g_object_set";
-		
-		var base_property = prop;
-		if (!prop.no_accessor_method) {
-			if (prop.base_property != null) {
-				base_property = prop.base_property;
-			} else if (prop.base_interface_property != null) {
-				base_property = prop.base_interface_property;
-			}
-			var base_property_type = (TypeSymbol) base_property.parent_symbol;
-			set_func = "%s_set_%s".printf (base_property_type.get_lower_case_cname (null), base_property.name);
-			if (prop is DynamicProperty) {
-				set_func = head.get_dynamic_property_setter_cname ((DynamicProperty) prop);
-			}
-		}
-		
-		var ccall = new CCodeFunctionCall (new CCodeIdentifier (set_func));
-
-		if (prop.binding == MemberBinding.INSTANCE) {
-			/* target instance is first argument */
-			ccall.add_argument ((CCodeExpression) get_ccodenode (ma.inner));
-		}
-
-		if (prop.no_accessor_method) {
-			/* property name is second argument of g_object_set */
-			ccall.add_argument (prop.get_canonical_cconstant ());
-		}
-			
-		ccall.add_argument (cexpr);
-		
-		if (prop.no_accessor_method) {
-			ccall.add_argument (new CCodeConstant ("NULL"));
-		}
-
-		return ccall;
-	}
-
-	/* indicates whether a given Expression eligable for an ADDRESS_OF operator
-	 * from a vala to C point of view all expressions denoting locals, fields and
-	 * parameters are eligable to an ADDRESS_OF operator */
-	public bool is_address_of_possible (Expression e) {
-		var ma = e as MemberAccess;
-
-		if (ma == null) {
-			return false;
-		}
-		if (ma.symbol_reference == null) {
-			return false;
-		}
-		if (ma.symbol_reference is FormalParameter) {
-			return true;
-		}
-		if (ma.symbol_reference is LocalVariable) {
-			return true;
-		}
-		if (ma.symbol_reference is Field) {
-			return true;
-		}
-		return false;
-	}
-
-	/* retrieve the correct address_of expression for a give expression, creates temporary variables
-	 * where necessary, ce is the corresponding ccode expression for e */
-	public CCodeExpression get_address_of_expression (Expression e, CCodeExpression ce) {
-		// is address of trivially possible?
-		if (is_address_of_possible (e)) {
-			return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ce);
-		}
-
-		var ccomma = new CCodeCommaExpression ();
-		var temp_decl = get_temp_variable (e.value_type);
-		var ctemp = new CCodeIdentifier (temp_decl.name);
-		temp_vars.add (temp_decl);
-		ccomma.append_expression (new CCodeAssignment (ctemp, ce));
-		ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
-		return ccomma;
-	}
-
-	public bool add_wrapper (string wrapper_name) {
-		return wrappers.add (wrapper_name);
-	}
-
-	public static DataType get_data_type_for_symbol (TypeSymbol sym) {
-		DataType type = null;
-
-		if (sym is Class) {
-			type = new ObjectType ((Class) sym);
-		} else if (sym is Interface) {
-			type = new ObjectType ((Interface) sym);
-		} else if (sym is Struct) {
-			type = new ValueType ((Struct) sym);
-		} else if (sym is Enum) {
-			type = new ValueType ((Enum) sym);
-		} else if (sym is ErrorDomain) {
-			type = new ErrorType ((ErrorDomain) sym, null);
-		} else if (sym is ErrorCode) {
-			type = new ErrorType ((ErrorDomain) sym.parent_symbol, (ErrorCode) sym);
-		} else {
-			Report.error (null, "internal error: `%s' is not a supported type".printf (sym.get_full_name ()));
-			return new InvalidType ();
-		}
-
-		return type;
-	}
-
-	public CCodeExpression? default_value_for_type (DataType type, bool initializer_expression) {
-		if ((type.data_type != null && type.data_type.is_reference_type ()) || type is PointerType || type is ArrayType) {
-			return new CCodeConstant ("NULL");
-		} else if (type.data_type != null && type.data_type.get_default_value () != null) {
-			return new CCodeConstant (type.data_type.get_default_value ());
-		} else if (type.data_type is Struct && initializer_expression) {
-			// 0-initialize struct with struct initializer { 0 }
-			// only allowed as initializer expression in C
-			var clist = new CCodeInitializerList ();
-			clist.append (new CCodeConstant ("0"));
-			return clist;
-		} else if (type.type_parameter != null) {
-			return new CCodeConstant ("NULL");
-		} else if (type is ErrorType) {
-			return new CCodeConstant ("NULL");
-		}
-		return null;
-	}
-	
-	private CCodeStatement create_property_type_check_statement (Property prop, bool check_return_type, TypeSymbol t, bool non_null, string var_name) {
-		if (check_return_type) {
-			return create_type_check_statement (prop, prop.property_type, t, non_null, var_name);
-		} else {
-			return create_type_check_statement (prop, new VoidType (), t, non_null, var_name);
-		}
-	}
-
-	public CCodeStatement? create_type_check_statement (CodeNode method_node, DataType ret_type, TypeSymbol t, bool non_null, string var_name) {
-		var ccheck = new CCodeFunctionCall ();
-		
-		if (context.checking && ((t is Class && !((Class) t).is_compact) || t is Interface)) {
-			var ctype_check = new CCodeFunctionCall (new CCodeIdentifier (get_type_check_function (t)));
-			ctype_check.add_argument (new CCodeIdentifier (var_name));
-			
-			CCodeExpression cexpr = ctype_check;
-			if (!non_null) {
-				var cnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
-			
-				cexpr = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cnull, ctype_check);
-			}
-			ccheck.add_argument (cexpr);
-		} else if (!non_null) {
-			return null;
-		} else {
-			var cnonnull = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier (var_name), new CCodeConstant ("NULL"));
-			ccheck.add_argument (cnonnull);
-		}
-		
-		if (ret_type is VoidType) {
-			/* void function */
-			ccheck.call = new CCodeIdentifier ("g_return_if_fail");
-		} else {
-			ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
-
-			var cdefault = default_value_for_type (ret_type, false);
-			if (cdefault != null) {
-				ccheck.add_argument (cdefault);
-			} else {
-				return new CCodeExpressionStatement (new CCodeConstant ("0"));
-			}
-		}
-		
-		return new CCodeExpressionStatement (ccheck);
-	}
-
-	public int get_param_pos (double param_pos, bool ellipsis = false) {
-		if (!ellipsis) {
-			if (param_pos >= 0) {
-				return (int) (param_pos * 1000);
-			} else {
-				return (int) ((100 + param_pos) * 1000);
-			}
-		} else {
-			if (param_pos >= 0) {
-				return (int) ((100 + param_pos) * 1000);
-			} else {
-				return (int) ((200 + param_pos) * 1000);
-			}
-		}
-	}
-
-	public bool dbus_use_ptr_array (ArrayType array_type) {
-		if (array_type.element_type.data_type == string_type.data_type) {
-			// use char**
-			return false;
-		} else if (array_type.element_type.data_type == bool_type.data_type
-		           || array_type.element_type.data_type == char_type.data_type
-		           || array_type.element_type.data_type == uchar_type.data_type
-		           || array_type.element_type.data_type == int_type.data_type
-		           || array_type.element_type.data_type == uint_type.data_type
-		           || array_type.element_type.data_type == long_type.data_type
-		           || array_type.element_type.data_type == ulong_type.data_type
-		           || array_type.element_type.data_type == int8_type.data_type
-		           || array_type.element_type.data_type == uint8_type.data_type
-		           || array_type.element_type.data_type == int32_type.data_type
-		           || array_type.element_type.data_type == uint32_type.data_type
-		           || array_type.element_type.data_type == int64_type.data_type
-		           || array_type.element_type.data_type == uint64_type.data_type
-		           || array_type.element_type.data_type == double_type.data_type) {
-			// use GArray
-			return false;
-		} else {
-			// use GPtrArray
-			return true;
-		}
-	}
-
-	public CCodeNode? get_ccodenode (CodeNode node) {
-		if (node.ccodenode == null) {
-			node.accept (this);
-		}
-		return node.ccodenode;
-	}
 }

Modified: trunk/gobject/valaccodeinvocationexpressionmodule.vala
==============================================================================
--- trunk/gobject/valaccodeinvocationexpressionmodule.vala	(original)
+++ trunk/gobject/valaccodeinvocationexpressionmodule.vala	Mon Nov  3 20:50:43 2008
@@ -68,9 +68,9 @@
 
 		if (m is ArrayResizeMethod) {
 			var array_type = (ArrayType) ma.inner.value_type;
-			carg_map.set (codegen.get_param_pos (0), new CCodeIdentifier (array_type.element_type.get_cname ()));
+			carg_map.set (get_param_pos (0), new CCodeIdentifier (array_type.element_type.get_cname ()));
 		} else if (m is ArrayMoveMethod) {
-			codegen.requires_array_move = true;
+			requires_array_move = true;
 		}
 
 		CCodeExpression instance;
@@ -91,8 +91,8 @@
 					// (tmp = expr, &tmp)
 					var ccomma = new CCodeCommaExpression ();
 
-					var temp_var = codegen.get_temp_variable (ma.inner.target_type);
-					codegen.temp_vars.insert (0, temp_var);
+					var temp_var = get_temp_variable (ma.inner.target_type);
+					temp_vars.insert (0, temp_var);
 					ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), instance));
 					ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
 
@@ -100,7 +100,7 @@
 				}
 			}
 
-			carg_map.set (codegen.get_param_pos (m.cinstance_parameter_position), instance);
+			carg_map.set (get_param_pos (m.cinstance_parameter_position), instance);
 		} else if (m != null && m.binding == MemberBinding.CLASS) {
 			var cl = (Class) m.parent_symbol;
 			var cast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null) + "_CLASS"));
@@ -108,7 +108,7 @@
 			CCodeExpression klass;
 			var ma = expr.call as MemberAccess;
 			if (ma.inner == null) {
-				if (codegen.in_static_or_class_ctor) {
+				if (in_static_or_class_ctor) {
 					// Accessing the method from a static or class constructor
 					klass = new CCodeIdentifier ("klass");
 				} else {
@@ -125,14 +125,14 @@
 			}
 
 			cast.add_argument (klass);
-			carg_map.set (codegen.get_param_pos (m.cinstance_parameter_position), cast);
+			carg_map.set (get_param_pos (m.cinstance_parameter_position), cast);
 		}
 
 		if (m is ArrayMoveMethod) {
 			var array_type = (ArrayType) ma.inner.value_type;
 			var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
 			csizeof.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
-			carg_map.set (codegen.get_param_pos (0.1), csizeof);
+			carg_map.set (get_param_pos (0.1), csizeof);
 		} else if (m is DynamicMethod) {
 			m.clear_parameters ();
 			int param_nr = 1;
@@ -159,7 +159,7 @@
 			}
 			head.generate_dynamic_method_wrapper ((DynamicMethod) m);
 		} else if (m is CreationMethod) {
-			ccall_expr = new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, codegen.current_class.get_cname () + "*"));
+			ccall_expr = new CCodeAssignment (new CCodeIdentifier ("self"), new CCodeCastExpression (ccall, current_class.get_cname () + "*"));
 		}
 
 		bool ellipsis = false;
@@ -184,14 +184,14 @@
 					if (!param.no_array_length && param.parameter_type is ArrayType) {
 						var array_type = (ArrayType) param.parameter_type;
 						for (int dim = 1; dim <= array_type.rank; dim++) {
-							carg_map.set (codegen.get_param_pos (param.carray_length_parameter_position + 0.01 * dim), head.get_array_length_cexpression (arg, dim));
+							carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), head.get_array_length_cexpression (arg, dim));
 						}
 						multiple_cargs = true;
 					} else if (param.parameter_type is DelegateType) {
 						var deleg_type = (DelegateType) param.parameter_type;
 						var d = deleg_type.delegate_symbol;
 						if (d.has_target) {
-							var delegate_target = codegen.get_delegate_target_cexpression (arg);
+							var delegate_target = get_delegate_target_cexpression (arg);
 							if (deleg_type.value_owned) {
 								CCodeExpression delegate_target_destroy_notify;
 								var delegate_method = arg.symbol_reference as Method;
@@ -199,24 +199,24 @@
 								if (delegate_method != null && delegate_method.binding == MemberBinding.INSTANCE
 								    && ma.inner != null && ma.inner.value_type.data_type != null
 								    && ma.inner.value_type.data_type.is_reference_counting ()) {
-									var ref_call = new CCodeFunctionCall (codegen.get_dup_func_expression (ma.inner.value_type, arg.source_reference));
+									var ref_call = new CCodeFunctionCall (get_dup_func_expression (ma.inner.value_type, arg.source_reference));
 									ref_call.add_argument (delegate_target);
 									delegate_target = ref_call;
-									delegate_target_destroy_notify = codegen.get_destroy_func_expression (ma.inner.value_type);
+									delegate_target_destroy_notify = get_destroy_func_expression (ma.inner.value_type);
 								} else {
 									delegate_target_destroy_notify = new CCodeConstant ("NULL");
 								}
-								carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position + 0.01), delegate_target_destroy_notify);
+								carg_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), delegate_target_destroy_notify);
  							}
-							carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
+							carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), delegate_target);
 							multiple_cargs = true;
 						}
 					} else if (param.parameter_type is MethodType) {
-						carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), codegen.get_delegate_target_cexpression (arg));
+						carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), get_delegate_target_cexpression (arg));
 						multiple_cargs = true;
 					}
 
-					cexpr = codegen.handle_struct_argument (param, arg, cexpr);
+					cexpr = handle_struct_argument (param, arg, cexpr);
 
 					if (multiple_cargs && arg is InvocationExpression) {
 						// if vala argument is invocation expression
@@ -226,8 +226,8 @@
 
 						var ccomma = new CCodeCommaExpression ();
 
-						var temp_decl = codegen.get_temp_variable (arg.value_type);
-						codegen.temp_vars.insert (0, temp_decl);
+						var temp_decl = get_temp_variable (arg.value_type);
+						temp_vars.insert (0, temp_decl);
 						ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_decl.name), cexpr));
 
 						cexpr = new CCodeIdentifier (temp_decl.name);
@@ -240,15 +240,15 @@
 					// unref old value for non-null non-weak ref/out arguments
 					// disabled for arrays for now as that requires special handling
 					// (ret_tmp = call (&tmp), var1 = (assign_tmp = dup (tmp), free (var1), assign_tmp), ret_tmp)
-					if (param.direction != ParameterDirection.IN && codegen.requires_destroy (arg.value_type)
+					if (param.direction != ParameterDirection.IN && requires_destroy (arg.value_type)
 					    && (param.direction == ParameterDirection.OUT || !param.parameter_type.value_owned)
 					    && !(param.parameter_type is ArrayType)) {
 						var unary = (UnaryExpression) arg;
 
 						var ccomma = new CCodeCommaExpression ();
 
-						var temp_var = codegen.get_temp_variable (param.parameter_type, param.parameter_type.value_owned);
-						codegen.temp_vars.insert (0, temp_var);
+						var temp_var = get_temp_variable (param.parameter_type, param.parameter_type.value_owned);
+						temp_vars.insert (0, temp_var);
 						cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name));
 
 						if (param.direction == ParameterDirection.REF) {
@@ -263,20 +263,20 @@
 						if (m.return_type is VoidType) {
 							ccomma.append_expression (ccall_expr);
 						} else {
-							ret_temp_var = codegen.get_temp_variable (m.return_type);
-							codegen.temp_vars.insert (0, ret_temp_var);
+							ret_temp_var = get_temp_variable (m.return_type);
+							temp_vars.insert (0, ret_temp_var);
 							ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (ret_temp_var.name), ccall_expr));
 						}
 
 						var cassign_comma = new CCodeCommaExpression ();
 
-						var assign_temp_var = codegen.get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned);
-						codegen.temp_vars.insert (0, assign_temp_var);
+						var assign_temp_var = get_temp_variable (unary.inner.value_type, unary.inner.value_type.value_owned);
+						temp_vars.insert (0, assign_temp_var);
 
-						cassign_comma.append_expression (new CCodeAssignment (new CCodeIdentifier (assign_temp_var.name), codegen.transform_expression (new CCodeIdentifier (temp_var.name), param.parameter_type, unary.inner.value_type, arg)));
+						cassign_comma.append_expression (new CCodeAssignment (new CCodeIdentifier (assign_temp_var.name), transform_expression (new CCodeIdentifier (temp_var.name), param.parameter_type, unary.inner.value_type, arg)));
 
 						// unref old value
-						cassign_comma.append_expression (codegen.get_unref_expression ((CCodeExpression) unary.inner.ccodenode, arg.value_type, arg));
+						cassign_comma.append_expression (get_unref_expression ((CCodeExpression) unary.inner.ccodenode, arg.value_type, arg));
 
 						cassign_comma.append_expression (new CCodeIdentifier (assign_temp_var.name));
 
@@ -295,10 +295,10 @@
 						cexpr = new CCodeCastExpression (cexpr, param.ctype);
 					}
 				}
-				arg_pos = codegen.get_param_pos (param.cparameter_position, ellipsis);
+				arg_pos = get_param_pos (param.cparameter_position, ellipsis);
 			} else {
 				// default argument position
-				arg_pos = codegen.get_param_pos (i, ellipsis);
+				arg_pos = get_param_pos (i, ellipsis);
 			}
 
 			carg_map.set (arg_pos, cexpr);
@@ -321,12 +321,12 @@
 			var array_type = (ArrayType) m.return_type;
 			for (int dim = 1; dim <= array_type.rank; dim++) {
 				if (!m.no_array_length) {
-					var temp_var = codegen.get_temp_variable (codegen.int_type);
+					var temp_var = get_temp_variable (int_type);
 					var temp_ref = new CCodeIdentifier (temp_var.name);
 
-					codegen.temp_vars.insert (0, temp_var);
+					temp_vars.insert (0, temp_var);
 
-					carg_map.set (codegen.get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+					carg_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
 					expr.append_array_size (temp_ref);
 				} else {
@@ -337,12 +337,12 @@
 			var deleg_type = (DelegateType) m.return_type;
 			var d = deleg_type.delegate_symbol;
 			if (d.has_target) {
-				var temp_var = codegen.get_temp_variable (new PointerType (new VoidType ()));
+				var temp_var = get_temp_variable (new PointerType (new VoidType ()));
 				var temp_ref = new CCodeIdentifier (temp_var.name);
 
-				codegen.temp_vars.insert (0, temp_var);
+				temp_vars.insert (0, temp_var);
 
-				carg_map.set (codegen.get_param_pos (m.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+				carg_map.set (get_param_pos (m.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 
 				expr.delegate_target = temp_ref;
 			}
@@ -351,32 +351,32 @@
 		if (m != null && m.coroutine) {
 			if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) {
 				// asynchronous begin call
-				carg_map.set (codegen.get_param_pos (-1), new CCodeConstant ("NULL"));
-				carg_map.set (codegen.get_param_pos (-0.9), new CCodeConstant ("NULL"));
+				carg_map.set (get_param_pos (-1), new CCodeConstant ("NULL"));
+				carg_map.set (get_param_pos (-0.9), new CCodeConstant ("NULL"));
 			} else {
-				carg_map.set (codegen.get_param_pos (-1), new CCodeIdentifier (codegen.current_method.get_cname () + "_ready"));
-				carg_map.set (codegen.get_param_pos (-0.9), new CCodeIdentifier ("data"));
+				carg_map.set (get_param_pos (-1), new CCodeIdentifier (current_method.get_cname () + "_ready"));
+				carg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("data"));
 			}
 		}
 
 		if (expr.tree_can_fail) {
 			// method can fail
-			codegen.current_method_inner_error = true;
+			current_method_inner_error = true;
 			// add &inner_error before the ellipsis arguments
-			carg_map.set (codegen.get_param_pos (-1), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
+			carg_map.set (get_param_pos (-1), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
 		}
 
 		if (ellipsis) {
 			/* ensure variable argument list ends with NULL
 			 * except when using printf-style arguments */
 			if (!m.printf_format && m.sentinel != "") {
-				carg_map.set (codegen.get_param_pos (-1, true), new CCodeConstant (m.sentinel));
+				carg_map.set (get_param_pos (-1, true), new CCodeConstant (m.sentinel));
 			}
 		} else if (itype is DelegateType) {
 			var deleg_type = (DelegateType) itype;
 			var d = deleg_type.delegate_symbol;
 			if (d.has_target) {
-				carg_map.set (codegen.get_param_pos (d.cinstance_parameter_position), codegen.get_delegate_target_cexpression (expr.call));
+				carg_map.set (get_param_pos (d.cinstance_parameter_position), get_delegate_target_cexpression (expr.call));
 			}
 		}
 
@@ -385,12 +385,12 @@
 			var sig = ((SignalType) itype).signal_symbol;
 
 			if (!sig.has_emitter) {
-				var temp_var = codegen.get_temp_variable (itype.get_return_type ());
+				var temp_var = get_temp_variable (itype.get_return_type ());
 				var temp_ref = new CCodeIdentifier (temp_var.name);
 
-				codegen.temp_vars.insert (0, temp_var);
+				temp_vars.insert (0, temp_var);
 
-				carg_map.set (codegen.get_param_pos (-1, true), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
+				carg_map.set (get_param_pos (-1, true), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
 			
 				var ccomma = new CCodeCommaExpression ();
 				ccomma.append_expression ((CCodeExpression) ccall_expr);
@@ -422,7 +422,7 @@
 		} else {
 			/* cast pointer to actual type if this is a generic method return value */
 			if (m != null && m.return_type.type_parameter != null && expr.value_type.data_type != null) {
-				expr.ccodenode = codegen.convert_from_generic_pointer (ccall_expr, expr.value_type);
+				expr.ccodenode = convert_from_generic_pointer (ccall_expr, expr.value_type);
 			} else {
 				expr.ccodenode = ccall_expr;
 			}
@@ -434,13 +434,13 @@
 			arg_it.next ();
 			var new_size = (CCodeExpression) arg_it.get ().ccodenode;
 
-			var temp_decl = codegen.get_temp_variable (codegen.int_type);
+			var temp_decl = get_temp_variable (int_type);
 			var temp_ref = new CCodeIdentifier (temp_decl.name);
 
-			codegen.temp_vars.insert (0, temp_decl);
+			temp_vars.insert (0, temp_decl);
 
 			/* memset needs string.h */
-			codegen.string_h_needed = true;
+			string_h_needed = true;
 
 			var clen = head.get_array_length_cexpression (ma.inner, 1);
 			var celems = (CCodeExpression) ma.inner.ccodenode;
@@ -461,11 +461,11 @@
 			ccomma.append_expression (new CCodeAssignment (head.get_array_length_cexpression (ma.inner, 1), temp_ref));
 
 			expr.ccodenode = ccomma;
-		} else if (m == codegen.substring_method) {
-			var temp_decl = codegen.get_temp_variable (codegen.string_type);
+		} else if (m == substring_method) {
+			var temp_decl = get_temp_variable (string_type);
 			var temp_ref = new CCodeIdentifier (temp_decl.name);
 
-			codegen.temp_vars.insert (0, temp_decl);
+			temp_vars.insert (0, temp_decl);
 
 			Gee.List<CCodeExpression> args = ccall.get_arguments ();
 

Modified: trunk/gobject/valaccodememberaccessmodule.vala
==============================================================================
--- trunk/gobject/valaccodememberaccessmodule.vala	(original)
+++ trunk/gobject/valaccodememberaccessmodule.vala	Mon Nov  3 20:50:43 2008
@@ -36,13 +36,13 @@
 				if (m.base_method != null) {
 					var base_class = (Class) m.base_method.parent_symbol;
 					var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
-					vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (codegen.current_class.get_lower_case_cname (null))));
+					vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
 					
 					expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
 					return;
 				} else if (m.base_interface_method != null) {
 					var base_iface = (Interface) m.base_interface_method.parent_symbol;
-					string parent_iface_var = "%s_%s_parent_iface".printf (codegen.current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
+					string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
 
 					expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.name);
 					return;
@@ -55,8 +55,8 @@
 					if (expr.inner != null && !expr.inner.is_pure ()) {
 						// instance expression has side-effects
 						// store in temp. variable
-						var temp_var = codegen.get_temp_variable (expr.inner.value_type);
-						codegen.temp_vars.insert (0, temp_var);
+						var temp_var = get_temp_variable (expr.inner.value_type);
+						temp_vars.insert (0, temp_var);
 						var ctemp = new CCodeIdentifier (temp_var.name);
 						inst = new CCodeAssignment (ctemp, pub_inst);
 						expr.inner.ccodenode = ctemp;
@@ -79,7 +79,7 @@
 			var f = (Field) expr.symbol_reference;
 			if (f.binding == MemberBinding.INSTANCE) {
 				var instance_expression_type = base_type;
-				var instance_target_type = codegen.get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
+				var instance_target_type = get_data_type_for_symbol ((TypeSymbol) f.parent_symbol);
 
 				var cl = instance_target_type.data_type as Class;
 				bool is_gtypeinstance = ((instance_target_type.data_type == cl) && (cl == null || !cl.is_compact));
@@ -101,7 +101,7 @@
 
 				CCodeExpression klass;
 				if (expr.inner == null) {
-					if (codegen.in_static_or_class_ctor) {
+					if (in_static_or_class_ctor) {
 						// Accessing the field from a static or class constructor
 						klass = new CCodeIdentifier ("klass");
 					} else {
@@ -123,7 +123,7 @@
 			}
 
 			if (f.field_type.type_parameter != null && expr.value_type.type_parameter == null) {
-				expr.ccodenode = codegen.convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type);
+				expr.ccodenode = convert_from_generic_pointer ((CCodeExpression) expr.ccodenode, expr.value_type);
 			}
 		} else if (expr.symbol_reference is Constant) {
 			var c = (Constant) expr.symbol_reference;
@@ -135,7 +135,7 @@
 				if (prop.base_property != null) {
 					var base_class = (Class) prop.base_property.parent_symbol;
 					var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
-					vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (codegen.current_class.get_lower_case_cname (null))));
+					vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
 					
 					var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, "get_%s".printf (prop.name)));
 					ccall.add_argument ((CCodeExpression) expr.inner.ccodenode);
@@ -143,7 +143,7 @@
 					return;
 				} else if (prop.base_interface_property != null) {
 					var base_iface = (Interface) prop.base_interface_property.parent_symbol;
-					string parent_iface_var = "%s_%s_parent_iface".printf (codegen.current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
+					string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
 
 					var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), "get_%s".printf (prop.name)));
 					ccall.add_argument ((CCodeExpression) expr.inner.ccodenode);
@@ -153,7 +153,7 @@
 			}
 
 			if (prop.get_accessor.automatic_body &&
-			    codegen.current_type_symbol == prop.parent_symbol &&
+			    current_type_symbol == prop.parent_symbol &&
 			    prop.base_property == null &&
 			    prop.base_interface_property == null) {
 				CCodeExpression inst;
@@ -182,9 +182,9 @@
 				// They are returned as out parameter.
 				if (base_property.property_type.is_real_struct_type ()) {
 					var ccomma = new CCodeCommaExpression ();
-					var temp_var = codegen.get_temp_variable (base_property.property_type);
+					var temp_var = get_temp_variable (base_property.property_type);
 					var ctemp = new CCodeIdentifier (temp_var.name);
-					codegen.temp_vars.add (temp_var);
+					temp_vars.add (temp_var);
 					ccall.add_argument (new CCodeUnaryExpression(CCodeUnaryOperator.ADDRESS_OF, ctemp));
 					ccomma.append_expression (ccall);
 					ccomma.append_expression (ctemp);
@@ -207,11 +207,11 @@
 				temp_type.value_owned = true;
 
 				// we need a temporary variable to save the property value
-				var temp_var = codegen.get_temp_variable (expr.value_type);
-				codegen.temp_vars.insert (0, temp_var);
+				var temp_var = get_temp_variable (expr.value_type);
+				temp_vars.insert (0, temp_var);
 
-				if (codegen.requires_destroy (temp_type)) {
-					codegen.temp_ref_vars.insert (0, temp_var);
+				if (requires_destroy (temp_type)) {
+					temp_ref_vars.insert (0, temp_var);
 				}
 
 				var ctemp = new CCodeIdentifier (temp_var.name);
@@ -230,11 +230,11 @@
 			expr.ccodenode = new CCodeConstant (ev.get_cname ());
 		} else if (expr.symbol_reference is LocalVariable) {
 			var local = (LocalVariable) expr.symbol_reference;
-			expr.ccodenode = new CCodeIdentifier (codegen.get_variable_cname (local.name));
+			expr.ccodenode = new CCodeIdentifier (get_variable_cname (local.name));
 		} else if (expr.symbol_reference is FormalParameter) {
 			var p = (FormalParameter) expr.symbol_reference;
 			if (p.name == "this") {
-				var st = codegen.current_type_symbol as Struct;
+				var st = current_type_symbol as Struct;
 				if (st != null && !st.is_simple_type ()) {
 					expr.ccodenode = new CCodeIdentifier ("(*self)");
 				} else {
@@ -249,10 +249,10 @@
 					// Property setters of non simple structs shall replace all occurences
 					// of the "value" formal parameter with a dereferencing version of that
 					// parameter.
-					if (codegen.current_property_accessor != null &&
-					    codegen.current_property_accessor.writable &&
-					    codegen.current_property_accessor.value_parameter == p &&
-					    codegen.current_property_accessor.prop.property_type.is_real_struct_type ()) {
+					if (current_property_accessor != null &&
+					    current_property_accessor.writable &&
+					    current_property_accessor.value_parameter == p &&
+					    current_property_accessor.prop.property_type.is_real_struct_type ()) {
 						expr.ccodenode = new CCodeIdentifier ("(*value)");
 					} else {
 						expr.ccodenode = new CCodeIdentifier (p.name);
@@ -267,7 +267,7 @@
 				var m = sig.get_method_handler ();
 				var base_class = (Class) m.parent_symbol;
 				var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
-				vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (codegen.current_class.get_lower_case_cname (null))));
+				vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
 				
 				expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
 				return;

Modified: trunk/gobject/valaccodemethodmodule.vala
==============================================================================
--- trunk/gobject/valaccodemethodmodule.vala	(original)
+++ trunk/gobject/valaccodemethodmodule.vala	Mon Nov  3 20:50:43 2008
@@ -60,30 +60,30 @@
 	}
 
 	public override void visit_method (Method m) {
-		Method old_method = codegen.current_method;
-		DataType old_return_type = codegen.current_return_type;
-		bool old_method_inner_error = codegen.current_method_inner_error;
-		int old_next_temp_var_id = codegen.next_temp_var_id;
-		codegen.current_symbol = m;
-		codegen.current_method = m;
-		codegen.current_return_type = m.return_type;
-		codegen.current_method_inner_error = false;
-		codegen.next_temp_var_id = 0;
+		Method old_method = current_method;
+		DataType old_return_type = current_return_type;
+		bool old_method_inner_error = current_method_inner_error;
+		int old_next_temp_var_id = next_temp_var_id;
+		current_symbol = m;
+		current_method = m;
+		current_return_type = m.return_type;
+		current_method_inner_error = false;
+		next_temp_var_id = 0;
 
 		bool in_gtypeinstance_creation_method = false;
 		bool in_gobject_creation_method = false;
 		bool in_fundamental_creation_method = false;
 
-		var creturn_type = codegen.current_return_type;
+		var creturn_type = current_return_type;
 
 		if (m is CreationMethod) {
-			codegen.in_creation_method = true;
-			var cl = codegen.current_type_symbol as Class;
+			in_creation_method = true;
+			var cl = current_type_symbol as Class;
 			if (cl != null && !cl.is_compact) {
 				in_gtypeinstance_creation_method = true;
 				if (cl.base_class == null) {
 					in_fundamental_creation_method = true;
-				} else if (cl.is_subtype_of (codegen.gobject_type)) {
+				} else if (cl.is_subtype_of (gobject_type)) {
 					in_gobject_creation_method = true;
 				}
 			}
@@ -117,9 +117,9 @@
 						}
 					}
 
-					add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0);
+					add_object_creation (cblock, ((CreationMethod) m).n_construction_params > 0 || current_class.get_type_parameters ().size > 0);
 				} else {
-					var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) codegen.current_type_symbol).get_cname ()));
+					var cdeclaration = new CCodeDeclaration ("%s *".printf (((Class) current_type_symbol).get_cname ()));
 					cdeclaration.add_declarator (new CCodeVariableDeclarator ("self"));
 		
 					cblock.add_statement (cdeclaration);
@@ -146,22 +146,22 @@
 				m.body.ccodenode = cblock;
 			}
 
-			codegen.in_creation_method = false;
+			in_creation_method = false;
 		}
 
-		bool inner_error = codegen.current_method_inner_error;
+		bool inner_error = current_method_inner_error;
 
-		codegen.current_symbol = codegen.current_symbol.parent_symbol;
-		codegen.current_method = old_method;
-		codegen.current_return_type = old_return_type;
-		codegen.current_method_inner_error = old_method_inner_error;
-		codegen.next_temp_var_id = old_next_temp_var_id;
+		current_symbol = current_symbol.parent_symbol;
+		current_method = old_method;
+		current_return_type = old_return_type;
+		current_method_inner_error = old_method_inner_error;
+		next_temp_var_id = old_next_temp_var_id;
 
-		codegen.function = new CCodeFunction (m.get_real_cname (), get_creturn_type (m, creturn_type.get_cname ()));
-		m.ccodenode = codegen.function;
+		function = new CCodeFunction (m.get_real_cname (), get_creturn_type (m, creturn_type.get_cname ()));
+		m.ccodenode = function;
 
 		if (m.is_inline) {
-			codegen.function.modifiers |= CCodeModifiers.INLINE;
+			function.modifiers |= CCodeModifiers.INLINE;
 		}
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
@@ -171,7 +171,7 @@
 		if (m.parent_symbol is Class && m is CreationMethod) {
 			var cl = (Class) m.parent_symbol;
 			if (!cl.is_compact) {
-				cparam_map.set (codegen.get_param_pos (m.cinstance_parameter_position), new CCodeFormalParameter ("object_type", "GType"));
+				cparam_map.set (get_param_pos (m.cinstance_parameter_position), new CCodeFormalParameter ("object_type", "GType"));
 			}
 		} else if (m.binding == MemberBinding.INSTANCE || (m.parent_symbol is Struct && m is CreationMethod)) {
 			TypeSymbol parent_type = find_parent_type (m);
@@ -198,55 +198,55 @@
 					instance_param = new CCodeFormalParameter ("self", this_type.get_cname ());
 				}
 			}
-			cparam_map.set (codegen.get_param_pos (m.cinstance_parameter_position), instance_param);
+			cparam_map.set (get_param_pos (m.cinstance_parameter_position), instance_param);
 
 			if (m.is_abstract || m.is_virtual) {
 				var vdecl = new CCodeDeclaration (get_creturn_type (m, creturn_type.get_cname ()));
 				vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name);
 				vdecl.add_declarator (vdeclarator);
-				codegen.type_struct.add_declaration (vdecl);
+				type_struct.add_declaration (vdecl);
 			}
 		} else if (m.binding == MemberBinding.CLASS) {
 			TypeSymbol parent_type = find_parent_type (m);
 			DataType this_type;
 			this_type = new ClassType ((Class) parent_type);
 			var class_param = new CCodeFormalParameter ("klass", this_type.get_cname ());
-			cparam_map.set (codegen.get_param_pos (m.cinstance_parameter_position), class_param);
+			cparam_map.set (get_param_pos (m.cinstance_parameter_position), class_param);
 		}
 
 		if (!m.coroutine) {
-			generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, codegen.function, vdeclarator);
+			generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, function, vdeclarator);
 		} else {
 			// data struct to hold parameters, local variables, and the return value
-			cparam_map.set (codegen.get_param_pos (0), new CCodeFormalParameter ("data", Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data*"));
+			cparam_map.set (get_param_pos (0), new CCodeFormalParameter ("data", Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data*"));
 
-			generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, codegen.function, vdeclarator, null, null, 0);
+			generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, function, vdeclarator, null, null, 0);
 		}
 
 		bool visible = !m.is_internal_symbol ();
 
 		// generate *_real_* functions for virtual methods
 		// also generate them for abstract methods of classes to prevent faulty subclassing
-		if (!m.is_abstract || (m.is_abstract && codegen.current_type_symbol is Class)) {
+		if (!m.is_abstract || (m.is_abstract && current_type_symbol is Class)) {
 			if (visible && m.base_method == null && m.base_interface_method == null) {
 				/* public methods need function declaration in
 				 * header file except virtual/overridden methods */
-				codegen.header_type_member_declaration.append (codegen.function.copy ());
+				header_type_member_declaration.append (function.copy ());
 			} else {
 				/* declare all other functions in source file to
 				 * avoid dependency on order within source file */
-				codegen.function.modifiers |= CCodeModifiers.STATIC;
-				codegen.source_type_member_declaration.append (codegen.function.copy ());
+				function.modifiers |= CCodeModifiers.STATIC;
+				source_type_member_declaration.append (function.copy ());
 			}
 		
 			/* Methods imported from a plain C file don't
 			 * have a body, e.g. Vala.Parser.parse_file () */
 			if (m.body != null) {
-				codegen.function.block = (CCodeBlock) m.body.ccodenode;
-				codegen.function.block.line = codegen.function.line;
+				function.block = (CCodeBlock) m.body.ccodenode;
+				function.block.line = function.line;
 
 				var cinit = new CCodeFragment ();
-				codegen.function.block.prepend_statement (cinit);
+				function.block.prepend_statement (cinit);
 
 				if (m.coroutine) {
 					var cswitch = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "state"));
@@ -255,7 +255,7 @@
 					cswitch.add_statement (new CCodeCaseStatement (new CCodeConstant ("0")));
 
 					// coroutine body
-					cswitch.add_statement (codegen.function.block);
+					cswitch.add_statement (function.block);
 
 					// complete async call by invoking callback
 					var object_creation = new CCodeFunctionCall (new CCodeIdentifier ("g_object_newv"));
@@ -275,8 +275,8 @@
 
 					cswitch.add_statement (new CCodeReturnStatement (new CCodeConstant ("FALSE")));
 
-					codegen.function.block = new CCodeBlock ();
-					codegen.function.block.add_statement (cswitch);
+					function.block = new CCodeBlock ();
+					function.block.add_statement (cswitch);
 				}
 
 				if (m.parent_symbol is Class) {
@@ -292,7 +292,7 @@
 							base_expression_type = new ObjectType ((Interface) base_method.parent_symbol);
 						}
 						var self_target_type = new ObjectType (cl);
-						CCodeExpression cself = codegen.transform_expression (new CCodeIdentifier ("base"), base_expression_type, self_target_type);
+						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.with_initializer ("self", cself));
@@ -301,7 +301,7 @@
 					} else if (m.binding == MemberBinding.INSTANCE
 					           && !(m is CreationMethod)) {
 						var ccheckstmt = create_method_type_check_statement (m, creturn_type, cl, true, "self");
-						ccheckstmt.line = codegen.function.line;
+						ccheckstmt.line = function.line;
 						cinit.append (ccheckstmt);
 					}
 				}
@@ -313,9 +313,9 @@
 					var t = param.parameter_type.data_type;
 					if (t != null && t.is_reference_type ()) {
 						if (param.direction != ParameterDirection.OUT) {
-							var type_check = create_method_type_check_statement (m, creturn_type, t, (codegen.context.non_null && !param.parameter_type.nullable), param.name);
+							var type_check = create_method_type_check_statement (m, creturn_type, t, (context.non_null && !param.parameter_type.nullable), param.name);
 							if (type_check != null) {
-								type_check.line = codegen.function.line;
+								type_check.line = function.line;
 								cinit.append (type_check);
 							}
 						} else {
@@ -336,19 +336,19 @@
 				}
 
 				if (m.source_reference != null && m.source_reference.comment != null) {
-					codegen.source_type_member_definition.append (new CCodeComment (m.source_reference.comment));
+					source_type_member_definition.append (new CCodeComment (m.source_reference.comment));
 				}
-				codegen.source_type_member_definition.append (codegen.function);
+				source_type_member_definition.append (function);
 			
 				if (m is CreationMethod) {
 					if (in_gobject_creation_method) {
 						int n_params = ((CreationMethod) m).n_construction_params;
 
-						if (n_params > 0 || codegen.current_class.get_type_parameters ().size > 0) {
+						if (n_params > 0 || 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 ((n_params + 3 * codegen.current_class.get_type_parameters ().size).to_string ()));
+							cparamsinit.add_argument (new CCodeConstant ((n_params + 3 * current_class.get_type_parameters ().size).to_string ()));
 						
 							var cdecl = new CCodeDeclaration ("GParameter *");
 							cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params", cparamsinit));
@@ -360,13 +360,13 @@
 						}
 
 						/* type, dup func, and destroy func properties for generic types */
-						foreach (TypeParameter type_param in codegen.current_class.get_type_parameters ()) {
+						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 ()));
-							cinit.append (new CCodeExpressionStatement (get_construct_property_assignment (prop_name, new ValueType (codegen.gtype_type), param_name)));
+							cinit.append (new CCodeExpressionStatement (get_construct_property_assignment (prop_name, new ValueType (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 ()));
@@ -385,7 +385,7 @@
 						cinit.append (cdecl);
 
 						/* type, dup func, and destroy func fields for generic types */
-						foreach (TypeParameter type_param in codegen.current_class.get_type_parameters ()) {
+						foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
 							CCodeIdentifier param_name;
 							CCodeAssignment assign;
 
@@ -403,7 +403,7 @@
 							assign = new CCodeAssignment (new CCodeMemberAccess.pointer (priv_access, param_name.name), param_name);
 							cinit.append (new CCodeExpressionStatement (assign));
 						}
-					} else if (codegen.current_type_symbol is Class) {
+					} else if (current_type_symbol is Class) {
 						var cl = (Class) m.parent_symbol;
 						var cdecl = new CCodeDeclaration (cl.get_cname () + "*");
 						var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0"));
@@ -418,7 +418,7 @@
 						var st = (Struct) m.parent_symbol;
 
 						// memset needs string.h
-						codegen.string_h_needed = true;
+						string_h_needed = true;
 						var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
 						czero.add_argument (new CCodeIdentifier ("self"));
 						czero.add_argument (new CCodeConstant ("0"));
@@ -427,9 +427,9 @@
 					}
 				}
 
-				if (codegen.context.module_init_method == m && codegen.in_plugin) {
+				if (context.module_init_method == m && in_plugin) {
 					// GTypeModule-based plug-in, register types
-					cinit.append (codegen.module_init_fragment);
+					cinit.append (module_init_fragment);
 				}
 
 				foreach (Expression precondition in m.get_preconditions ()) {
@@ -443,7 +443,7 @@
 				var cblock = new CCodeBlock ();
 
 				// add a typecheck statement for "self"
-				cblock.add_statement (create_method_type_check_statement (m, creturn_type, codegen.current_type_symbol, true, "self"));
+				cblock.add_statement (create_method_type_check_statement (m, creturn_type, current_type_symbol, true, "self"));
 
 				// add critical warning that this method should not have been called
 				var type_from_instance_call = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE"));
@@ -461,16 +461,16 @@
 				cblock.add_statement (new CCodeExpressionStatement (cerrorcall));
 
 				// add return statement
-				cblock.add_statement (new CCodeReturnStatement (codegen.default_value_for_type (creturn_type, false)));
+				cblock.add_statement (new CCodeReturnStatement (default_value_for_type (creturn_type, false)));
 
-				codegen.function.block = cblock;
-				codegen.source_type_member_definition.append (codegen.function);
+				function.block = cblock;
+				source_type_member_definition.append (function);
 			}
 		}
 
 		if (m.is_abstract || m.is_virtual) {
 			var vfunc = new CCodeFunction (m.get_cname (), creturn_type.get_cname ());
-			vfunc.line = codegen.function.line;
+			vfunc.line = function.line;
 
 			ReferenceType this_type;
 			if (m.parent_symbol is Class) {
@@ -483,7 +483,7 @@
 			var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
 			var cparam = new CCodeFormalParameter ("self", this_type.get_cname ());
-			cparam_map.set (codegen.get_param_pos (m.cinstance_parameter_position), cparam);
+			cparam_map.set (get_param_pos (m.cinstance_parameter_position), cparam);
 			
 			var vblock = new CCodeBlock ();
 
@@ -504,7 +504,7 @@
 			vcast.add_argument (new CCodeIdentifier ("self"));
 		
 			var vcall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (vcast, m.vfunc_name));
-			carg_map.set (codegen.get_param_pos (m.cinstance_parameter_position), new CCodeIdentifier ("self"));
+			carg_map.set (get_param_pos (m.cinstance_parameter_position), new CCodeIdentifier ("self"));
 
 			generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, vfunc, null, carg_map, vcall);
 
@@ -536,24 +536,24 @@
 			}
 
 			if (visible) {
-				codegen.header_type_member_declaration.append (vfunc.copy ());
+				header_type_member_declaration.append (vfunc.copy ());
 			} else {
 				vfunc.modifiers |= CCodeModifiers.STATIC;
-				codegen.source_type_member_declaration.append (vfunc.copy ());
+				source_type_member_declaration.append (vfunc.copy ());
 			}
 			
 			vfunc.block = vblock;
 
 			if (m.is_abstract && m.source_reference != null && m.source_reference.comment != null) {
-				codegen.source_type_member_definition.append (new CCodeComment (m.source_reference.comment));
+				source_type_member_definition.append (new CCodeComment (m.source_reference.comment));
 			}
-			codegen.source_type_member_definition.append (vfunc);
+			source_type_member_definition.append (vfunc);
 		}
 
 		if (m is CreationMethod) {
-			if (codegen.current_class != null && !codegen.current_class.is_compact) {
+			if (current_class != null && !current_class.is_compact) {
 				var vfunc = new CCodeFunction (m.get_cname (), creturn_type.get_cname ());
-				vfunc.line = codegen.function.line;
+				vfunc.line = function.line;
 
 				ReferenceType this_type = new ObjectType ((Class) m.parent_symbol);
 
@@ -563,7 +563,7 @@
 				var vblock = new CCodeBlock ();
 
 				var vcall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
-				vcall.add_argument (new CCodeIdentifier (codegen.current_class.get_type_id ()));
+				vcall.add_argument (new CCodeIdentifier (current_class.get_type_id ()));
 
 				generate_cparameters (m, creturn_type, in_gtypeinstance_creation_method, cparam_map, vfunc, null, carg_map, vcall);
 				CCodeStatement cstmt = new CCodeReturnStatement (vcall);
@@ -571,33 +571,33 @@
 				vblock.add_statement (cstmt);
 
 				if (visible) {
-					codegen.header_type_member_declaration.append (vfunc.copy ());
+					header_type_member_declaration.append (vfunc.copy ());
 				} else {
 					vfunc.modifiers |= CCodeModifiers.STATIC;
-					codegen.source_type_member_declaration.append (vfunc.copy ());
+					source_type_member_declaration.append (vfunc.copy ());
 				}
 			
 				vfunc.block = vblock;
 
-				codegen.source_type_member_definition.append (vfunc);
+				source_type_member_definition.append (vfunc);
 			}
 
-			if (codegen.current_class != null && codegen.current_class.is_subtype_of (codegen.gobject_type)
-			    && (((CreationMethod) m).n_construction_params > 0 || codegen.current_class.get_type_parameters ().size > 0)) {
+			if (current_class != null && current_class.is_subtype_of (gobject_type)
+			    && (((CreationMethod) m).n_construction_params > 0 || current_class.get_type_parameters ().size > 0)) {
 				var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, new CCodeIdentifier ("__params_it"), new CCodeIdentifier ("__params"));
 				var cdofreeparam = new CCodeBlock ();
 				cdofreeparam.add_statement (new CCodeExpressionStatement (new CCodeUnaryExpression (CCodeUnaryOperator.PREFIX_DECREMENT, new CCodeIdentifier ("__params_it"))));
 				var cunsetcall = new CCodeFunctionCall (new CCodeIdentifier ("g_value_unset"));
 				cunsetcall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeMemberAccess.pointer (new CCodeIdentifier ("__params_it"), "value")));
 				cdofreeparam.add_statement (new CCodeExpressionStatement (cunsetcall));
-				codegen.function.block.add_statement (new CCodeWhileStatement (ccond, cdofreeparam));
+				function.block.add_statement (new CCodeWhileStatement (ccond, cdofreeparam));
 
 				var cfreeparams = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
 				cfreeparams.add_argument (new CCodeIdentifier ("__params"));
-				codegen.function.block.add_statement (new CCodeExpressionStatement (cfreeparams));
+				function.block.add_statement (new CCodeExpressionStatement (cfreeparams));
 			}
 
-			if (codegen.current_type_symbol is Class) {
+			if (current_type_symbol is Class) {
 				CCodeExpression cresult = new CCodeIdentifier ("self");
 				if (get_custom_creturn_type (m) != null) {
 					cresult = new CCodeCastExpression (cresult, get_custom_creturn_type (m));
@@ -605,7 +605,7 @@
 
 				var creturn = new CCodeReturnStatement ();
 				creturn.return_expression = cresult;
-				codegen.function.block.add_statement (creturn);
+				function.block.add_statement (creturn);
 			}
 		}
 		
@@ -614,12 +614,12 @@
 		if (is_possible_entry_point (m, ref return_value, ref args_parameter)) {
 			// m is possible entry point, add appropriate startup code
 			var cmain = new CCodeFunction ("main", "int");
-			cmain.line = codegen.function.line;
+			cmain.line = function.line;
 			cmain.add_parameter (new CCodeFormalParameter ("argc", "int"));
 			cmain.add_parameter (new CCodeFormalParameter ("argv", "char **"));
 			var main_block = new CCodeBlock ();
 
-			if (codegen.context.thread) {
+			if (context.thread) {
 				var thread_init_call = new CCodeFunctionCall (new CCodeIdentifier ("g_thread_init"));
 				thread_init_call.line = cmain.line;
 				thread_init_call.add_argument (new CCodeConstant ("NULL"));
@@ -630,7 +630,7 @@
 			type_init_call.line = cmain.line;
 			main_block.add_statement (type_init_call);
 
-			var main_call = new CCodeFunctionCall (new CCodeIdentifier (codegen.function.name));
+			var main_call = new CCodeFunctionCall (new CCodeIdentifier (function.name));
 			if (args_parameter) {
 				main_call.add_argument (new CCodeIdentifier ("argv"));
 				main_call.add_argument (new CCodeIdentifier ("argc"));
@@ -649,7 +649,7 @@
 				main_block.add_statement (ret_stmt);
 			}
 			cmain.block = main_block;
-			codegen.source_type_member_definition.append (cmain);
+			source_type_member_definition.append (cmain);
 		}
 	}
 
@@ -657,14 +657,14 @@
 		if (in_gtypeinstance_creation_method) {
 			// memory management for generic types
 			int type_param_index = 0;
-			foreach (TypeParameter type_param in codegen.current_class.get_type_parameters ()) {
-				cparam_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.01), new CCodeFormalParameter ("%s_type".printf (type_param.name.down ()), "GType"));
-				cparam_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.02), new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
-				cparam_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.03), new CCodeFormalParameter ("%s_destroy_func".printf (type_param.name.down ()), "GDestroyNotify"));
+			foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
+				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeFormalParameter ("%s_type".printf (type_param.name.down ()), "GType"));
+				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
+				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeFormalParameter ("%s_destroy_func".printf (type_param.name.down ()), "GDestroyNotify"));
 				if (carg_map != null) {
-					carg_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
-					carg_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ())));
-					carg_map.set (codegen.get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ())));
+					carg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
+					carg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ())));
+					carg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ())));
 				}
 				type_param_index++;
 			}
@@ -693,40 +693,40 @@
 				
 				for (int dim = 1; dim <= array_type.rank; dim++) {
 					var cparam = new CCodeFormalParameter (head.get_array_length_cname (param.name, dim), length_ctype);
-					cparam_map.set (codegen.get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
+					cparam_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), cparam);
 					if (carg_map != null) {
-						carg_map.set (codegen.get_param_pos (param.carray_length_parameter_position + 0.01 * dim), new CCodeIdentifier (cparam.name));
+						carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), new CCodeIdentifier (cparam.name));
 					}
 				}
 			}
 
-			cparam_map.set (codegen.get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
+			cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode);
 			if (carg_map != null) {
-				carg_map.set (codegen.get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name));
+				carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name));
 			}
 
 			if (param.parameter_type is DelegateType) {
 				var deleg_type = (DelegateType) param.parameter_type;
 				var d = deleg_type.delegate_symbol;
 				if (d.has_target) {
-					var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname (param.name), "void*");
-					cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), cparam);
+					var cparam = new CCodeFormalParameter (get_delegate_target_cname (param.name), "void*");
+					cparam_map.set (get_param_pos (param.cdelegate_target_parameter_position), cparam);
 					if (carg_map != null) {
-						carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
+						carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
 					}
 					if (deleg_type.value_owned) {
-						cparam = new CCodeFormalParameter (codegen.get_delegate_target_destroy_notify_cname (param.name), "GDestroyNotify");
-						cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position + 0.01), cparam);
+						cparam = new CCodeFormalParameter (get_delegate_target_destroy_notify_cname (param.name), "GDestroyNotify");
+						cparam_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), cparam);
 						if (carg_map != null) {
-							carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position + 0.01), new CCodeIdentifier (cparam.name));
+							carg_map.set (get_param_pos (param.cdelegate_target_parameter_position + 0.01), new CCodeIdentifier (cparam.name));
 						}
 					}
 				}
 			} else if (param.parameter_type is MethodType) {
-				var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname (param.name), "void*");
-				cparam_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), cparam);
+				var cparam = new CCodeFormalParameter (get_delegate_target_cname (param.name), "void*");
+				cparam_map.set (get_param_pos (param.cdelegate_target_parameter_position), cparam);
 				if (carg_map != null) {
-					carg_map.set (codegen.get_param_pos (param.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
+					carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
 				}
 			}
 		}
@@ -738,9 +738,9 @@
 
 				for (int dim = 1; dim <= array_type.rank; dim++) {
 					var cparam = new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*");
-					cparam_map.set (codegen.get_param_pos (m.carray_length_parameter_position + 0.01 * dim), cparam);
+					cparam_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), cparam);
 					if (carg_map != null) {
-						carg_map.set (codegen.get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeIdentifier (cparam.name));
+						carg_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), new CCodeIdentifier (cparam.name));
 					}
 				}
 			} else if (creturn_type is DelegateType) {
@@ -748,19 +748,19 @@
 				var deleg_type = (DelegateType) creturn_type;
 				var d = deleg_type.delegate_symbol;
 				if (d.has_target) {
-					var cparam = new CCodeFormalParameter (codegen.get_delegate_target_cname ("result"), "void*");
-					cparam_map.set (codegen.get_param_pos (m.cdelegate_target_parameter_position), cparam);
+					var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void*");
+					cparam_map.set (get_param_pos (m.cdelegate_target_parameter_position), cparam);
 					if (carg_map != null) {
-						carg_map.set (codegen.get_param_pos (m.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
+						carg_map.set (get_param_pos (m.cdelegate_target_parameter_position), new CCodeIdentifier (cparam.name));
 					}
 				}
 			}
 
 			if (m.get_error_types ().size > 0) {
 				var cparam = new CCodeFormalParameter ("error", "GError**");
-				cparam_map.set (codegen.get_param_pos (-1), cparam);
+				cparam_map.set (get_param_pos (-1), cparam);
 				if (carg_map != null) {
-					carg_map.set (codegen.get_param_pos (-1), new CCodeIdentifier (cparam.name));
+					carg_map.set (get_param_pos (-1), new CCodeIdentifier (cparam.name));
 				}
 			}
 		}
@@ -790,7 +790,7 @@
 	}
 
 	private CCodeStatement create_method_type_check_statement (Method m, DataType return_type, TypeSymbol t, bool non_null, string var_name) {
-		return codegen.create_type_check_statement (m, return_type, t, non_null, var_name);
+		return create_type_check_statement (m, return_type, t, non_null, var_name);
 	}
 
 	private CCodeStatement create_precondition_statement (CodeNode method_node, DataType ret_type, Expression precondition) {
@@ -804,7 +804,7 @@
 		} else {
 			ccheck.call = new CCodeIdentifier ("g_return_val_if_fail");
 
-			var cdefault = codegen.default_value_for_type (ret_type, false);
+			var cdefault = default_value_for_type (ret_type, false);
 			if (cdefault != null) {
 				ccheck.add_argument (cdefault);
 			} else {
@@ -846,7 +846,7 @@
 		
 		if (m.return_type.data_type == null) {
 			return_value = false;
-		} else if (m.return_type.data_type == codegen.int_type.data_type) {
+		} else if (m.return_type.data_type == int_type.data_type) {
 			return_value = true;
 		} else {
 			// return type must be void or int
@@ -880,7 +880,7 @@
 		}
 		
 		var array_type = (ArrayType) param.parameter_type;
-		if (array_type.element_type.data_type != codegen.string_type.data_type) {
+		if (array_type.element_type.data_type != string_type.data_type) {
 			// parameter must be an array of strings
 			return false;
 		}
@@ -890,7 +890,7 @@
 	}
 
 	private void add_object_creation (CCodeBlock b, bool has_params) {
-		var cl = (Class) codegen.current_type_symbol;
+		var cl = (Class) current_type_symbol;
 
 		bool chain_up = false;
 		CreationMethod cm = null;
@@ -905,7 +905,7 @@
 		}
 
 		if (!has_params && !chain_up
-		    && cl.base_class != codegen.gobject_type) {
+		    && cl.base_class != gobject_type) {
 			// possibly report warning or error about missing base call
 		}
 
@@ -934,7 +934,7 @@
 	}
 
 	public override void visit_creation_method (CreationMethod m) {
-		if (m.body != null && codegen.current_type_symbol is Class && codegen.current_class.is_subtype_of (codegen.gobject_type)) {
+		if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) {
 			int n_params = 0;
 			foreach (Statement stmt in m.body.get_statements ()) {
 				var expr_stmt = stmt as ExpressionStatement;

Modified: trunk/gobject/valaccodemodule.vala
==============================================================================
--- trunk/gobject/valaccodemodule.vala	(original)
+++ trunk/gobject/valaccodemodule.vala	Mon Nov  3 20:50:43 2008
@@ -27,7 +27,7 @@
  */
 public abstract class Vala.CCodeModule {
 	public weak CCodeGenerator codegen { get; private set; }
-
+	
 	public CCodeModule head {
 		get { return _head; }
 		private set {
@@ -68,36 +68,268 @@
 		next.visit_struct (st);
 	}
 
+	public virtual void visit_enum (Enum en) {
+		next.visit_enum (en);
+	}
+
+	public virtual void visit_enum_value (EnumValue ev) {
+		next.visit_enum_value (ev);
+	}
+
+	public virtual void visit_error_domain (ErrorDomain edomain) {
+		next.visit_error_domain (edomain);
+	}
+
+	public virtual void visit_error_code (ErrorCode ecode) {
+		next.visit_error_code (ecode);
+	}
+
+	public virtual void visit_delegate (Delegate d) {
+		next.visit_delegate (d);
+	}
+	
+	public virtual void visit_member (Member m) {
+		next.visit_member (m);
+	}
+
+	public virtual void visit_constant (Constant c) {
+		next.visit_constant (c);
+	}
+
+	public virtual void visit_field (Field f) {
+		next.visit_field (f);
+	}
+
 	public virtual void visit_method (Method m) {
 		next.visit_method (m);
 	}
 
+	public virtual void visit_creation_method (CreationMethod m) {
+		next.visit_creation_method (m);
+	}
+
+	public virtual void visit_formal_parameter (FormalParameter p) {
+		next.visit_formal_parameter (p);
+	}
+
+	public virtual void visit_property (Property prop) {
+		next.visit_property (prop);
+	}
+
+	public virtual void visit_property_accessor (PropertyAccessor acc) {
+		next.visit_property_accessor (acc);
+	}
+
 	public virtual void visit_signal (Signal sig) {
 		next.visit_signal (sig);
 	}
 
-	public virtual void visit_creation_method (CreationMethod m) {
-		next.visit_creation_method (m);
+	public virtual void visit_constructor (Constructor c) {
+		next.visit_constructor (c);
+	}
+
+	public virtual void visit_destructor (Destructor d) {
+		next.visit_destructor (d);
+	}
+
+	public virtual void visit_block (Block b) {
+		next.visit_block (b);
+	}
+
+	public virtual void visit_empty_statement (EmptyStatement stmt) {
+		next.visit_empty_statement (stmt);
+	}
+
+	public virtual void visit_declaration_statement (DeclarationStatement stmt) {
+		next.visit_declaration_statement (stmt);
+	}
+
+	public virtual void visit_local_variable (LocalVariable local) {
+		next.visit_local_variable (local);
+	}
+
+	public virtual void visit_initializer_list (InitializerList list) {
+		next.visit_initializer_list (list);
+	}
+
+	public virtual void visit_end_full_expression (Expression expr) {
+		next.visit_end_full_expression (expr);
+	}
+	
+	public virtual void visit_expression_statement (ExpressionStatement stmt) {
+		next.visit_expression_statement (stmt);
+	}
+
+	public virtual void visit_if_statement (IfStatement stmt) {
+		next.visit_if_statement (stmt);
+	}
+
+	public virtual void visit_switch_statement (SwitchStatement stmt) {
+		next.visit_switch_statement (stmt);
+	}
+
+	public virtual void visit_switch_section (SwitchSection section) {
+		next.visit_switch_section (section);
+	}
+
+	public virtual void visit_while_statement (WhileStatement stmt) {
+		next.visit_while_statement (stmt);
+	}
+
+	public virtual void visit_do_statement (DoStatement stmt) {
+		next.visit_do_statement (stmt);
+	}
+
+	public virtual void visit_for_statement (ForStatement stmt) {
+		next.visit_for_statement (stmt);
+	}
+
+	public virtual void visit_foreach_statement (ForeachStatement stmt) {
+		next.visit_foreach_statement (stmt);
+	}
+
+	public virtual void visit_break_statement (BreakStatement stmt) {
+		next.visit_break_statement (stmt);
+	}
+
+	public virtual void visit_continue_statement (ContinueStatement stmt) {
+		next.visit_continue_statement (stmt);
+	}
+
+	public virtual void visit_return_statement (ReturnStatement stmt) {
+		next.visit_return_statement (stmt);
+	}
+
+	public virtual void visit_yield_statement (YieldStatement stmt) {
+		next.visit_yield_statement (stmt);
+	}
+
+	public virtual void visit_throw_statement (ThrowStatement stmt) {
+		next.visit_throw_statement (stmt);
+	}
+
+	public virtual void visit_try_statement (TryStatement stmt) {
+		next.visit_try_statement (stmt);
+	}
+
+	public virtual void visit_catch_clause (CatchClause clause) {
+		next.visit_catch_clause (clause);
+	}
+
+	public virtual void visit_lock_statement (LockStatement stmt) {
+		next.visit_lock_statement (stmt);
+	}
+
+	public virtual void visit_delete_statement (DeleteStatement stmt) {
+		next.visit_delete_statement (stmt);
+	}
+
+	public virtual void visit_expression (Expression expr) {
+		next.visit_expression (expr);
+	}
+
+	public virtual void visit_array_creation_expression (ArrayCreationExpression expr) {
+		next.visit_array_creation_expression (expr);
+	}
+
+	public virtual void visit_boolean_literal (BooleanLiteral expr) {
+		next.visit_boolean_literal (expr);
+	}
+
+	public virtual void visit_character_literal (CharacterLiteral expr) {
+		next.visit_character_literal (expr);
+	}
+
+	public virtual void visit_integer_literal (IntegerLiteral expr) {
+		next.visit_integer_literal (expr);
+	}
+
+	public virtual void visit_real_literal (RealLiteral expr) {
+		next.visit_real_literal (expr);
+	}
+
+	public virtual void visit_string_literal (StringLiteral expr) {
+		next.visit_string_literal (expr);
+	}
+
+	public virtual void visit_null_literal (NullLiteral expr) {
+		next.visit_null_literal (expr);
+	}
+
+	public virtual void visit_parenthesized_expression (ParenthesizedExpression expr) {
+		next.visit_parenthesized_expression (expr);
 	}
 
 	public virtual void visit_member_access (MemberAccess expr) {
 		next.visit_member_access (expr);
 	}
 
+	public virtual void visit_invocation_expression (InvocationExpression expr) {
+		next.visit_invocation_expression (expr);
+	}
+	
 	public virtual void visit_element_access (ElementAccess expr) {
 		next.visit_element_access (expr);
 	}
 
-	public virtual void visit_assignment (Assignment assignment) {
-		next.visit_assignment (assignment);
+	public virtual void visit_base_access (BaseAccess expr) {
+		next.visit_base_access (expr);
 	}
 
-	public virtual void visit_invocation_expression (InvocationExpression expr) {
-		next.visit_invocation_expression (expr);
+	public virtual void visit_postfix_expression (PostfixExpression expr) {
+		next.visit_postfix_expression (expr);
 	}
 
-	public virtual void visit_array_creation_expression (ArrayCreationExpression expr) {
-		next.visit_array_creation_expression (expr);
+	public virtual void visit_object_creation_expression (ObjectCreationExpression expr) {
+		next.visit_object_creation_expression (expr);
+	}
+
+	public virtual void visit_sizeof_expression (SizeofExpression expr) {
+		next.visit_sizeof_expression (expr);
+	}
+
+	public virtual void visit_typeof_expression (TypeofExpression expr) {
+		next.visit_typeof_expression (expr);
+	}
+
+	public virtual void visit_unary_expression (UnaryExpression expr) {
+		next.visit_unary_expression (expr);
+	}
+
+	public virtual void visit_cast_expression (CastExpression expr) {
+		next.visit_cast_expression (expr);
+	}
+	
+	public virtual void visit_pointer_indirection (PointerIndirection expr) {
+		next.visit_pointer_indirection (expr);
+	}
+
+	public virtual void visit_addressof_expression (AddressofExpression expr) {
+		next.visit_addressof_expression (expr);
+	}
+
+	public virtual void visit_reference_transfer_expression (ReferenceTransferExpression expr) {
+		next.visit_reference_transfer_expression (expr);
+	}
+
+	public virtual void visit_binary_expression (BinaryExpression expr) {
+		next.visit_binary_expression (expr);
+	}
+
+	public virtual void visit_type_check (TypeCheck expr) {
+		next.visit_type_check (expr);
+	}
+
+	public virtual void visit_conditional_expression (ConditionalExpression expr) {
+		next.visit_conditional_expression (expr);
+	}
+
+	public virtual void visit_lambda_expression (LambdaExpression l) {
+		next.visit_lambda_expression (l);
+	}
+
+	public virtual void visit_assignment (Assignment a) {
+		next.visit_assignment (a);
 	}
 
 	public virtual void generate_cparameters (Method m, DataType creturn_type, bool in_gtypeinstance_creation_method, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
@@ -172,10 +404,6 @@
 		return next.get_array_length_cexpression (array_expr, dim);
 	}
 
-	public virtual void visit_throw_statement (ThrowStatement stmt) {
-		next.visit_throw_statement (stmt);
-	}
-
 	public virtual void add_simple_check (CodeNode node, CCodeFragment cfrag) {
 		next.add_simple_check (node, cfrag);
 	}

Modified: trunk/gobject/valaccodestructmodule.vala
==============================================================================
--- trunk/gobject/valaccodestructmodule.vala	(original)
+++ trunk/gobject/valaccodestructmodule.vala	Mon Nov  3 20:50:43 2008
@@ -29,21 +29,21 @@
 	}
 
 	public override void visit_struct (Struct st) {
-		var old_type_symbol = codegen.current_type_symbol;
-		var old_instance_struct = codegen.instance_struct;
-		var old_instance_finalize_fragment = codegen.instance_finalize_fragment;
-		codegen.current_type_symbol = st;
-		codegen.instance_struct = new CCodeStruct ("_%s".printf (st.get_cname ()));
-		codegen.instance_finalize_fragment = new CCodeFragment ();
+		var old_type_symbol = current_type_symbol;
+		var old_instance_struct = instance_struct;
+		var old_instance_finalize_fragment = instance_finalize_fragment;
+		current_type_symbol = st;
+		instance_struct = new CCodeStruct ("_%s".printf (st.get_cname ()));
+		instance_finalize_fragment = new CCodeFragment ();
 
 		CCodeFragment decl_frag;
 		CCodeFragment def_frag;
 		if (st.access != SymbolAccessibility.PRIVATE) {
-			decl_frag = codegen.header_type_declaration;
-			def_frag = codegen.header_type_definition;
+			decl_frag = header_type_declaration;
+			def_frag = header_type_definition;
 		} else {
-			decl_frag = codegen.source_type_declaration;
-			def_frag = codegen.source_type_definition;
+			decl_frag = source_type_declaration;
+			def_frag = source_type_definition;
 		}
 
 		if (st.source_reference.file.cycle == null) {
@@ -53,7 +53,7 @@
 		if (st.source_reference.comment != null) {
 			def_frag.append (new CCodeComment (st.source_reference.comment));
 		}
-		def_frag.append (codegen.instance_struct);
+		def_frag.append (instance_struct);
 
 		st.accept_children (codegen);
 
@@ -62,9 +62,9 @@
 			add_struct_destroy_function (st);
 		}
 
-		codegen.current_type_symbol = old_type_symbol;
-		codegen.instance_struct = old_instance_struct;
-		codegen.instance_finalize_fragment = old_instance_finalize_fragment;
+		current_type_symbol = old_type_symbol;
+		instance_struct = old_instance_struct;
+		instance_finalize_fragment = old_instance_finalize_fragment;
 	}
 
 	void add_struct_copy_function (Struct st) {
@@ -77,16 +77,16 @@
 		function.add_parameter (new CCodeFormalParameter ("dest", st.get_cname () + "*"));
 
 		if (st.access != SymbolAccessibility.PRIVATE) {
-			codegen.header_type_member_declaration.append (function.copy ());
+			header_type_member_declaration.append (function.copy ());
 		} else {
-			codegen.source_type_member_declaration.append (function.copy ());
+			source_type_member_declaration.append (function.copy ());
 		}
 
 		var cblock = new CCodeBlock ();
 
 		function.block = cblock;
 
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	void add_struct_destroy_function (Struct st) {
@@ -98,18 +98,18 @@
 		function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
 
 		if (st.access != SymbolAccessibility.PRIVATE) {
-			codegen.header_type_member_declaration.append (function.copy ());
+			header_type_member_declaration.append (function.copy ());
 		} else {
-			codegen.source_type_member_declaration.append (function.copy ());
+			source_type_member_declaration.append (function.copy ());
 		}
 
 		var cblock = new CCodeBlock ();
 
-		cblock.add_statement (codegen.instance_finalize_fragment);
+		cblock.add_statement (instance_finalize_fragment);
 
 		function.block = cblock;
 
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 }
 

Modified: trunk/gobject/valaclassregisterfunction.vala
==============================================================================
--- trunk/gobject/valaclassregisterfunction.vala	(original)
+++ trunk/gobject/valaclassregisterfunction.vala	Mon Nov  3 20:50:43 2008
@@ -37,9 +37,9 @@
 	 * @param cl a class
 	 * @return   newly created class register function
 	 */
-	public ClassRegisterFunction (Class cl, CCodeGenerator codegen) {
+	public ClassRegisterFunction (Class cl, CodeContext context) {
 		class_reference = cl;
-		this.codegen = codegen;
+		this.context = context;
 	}
 	
 	public override TypeSymbol get_type_declaration () {

Modified: trunk/gobject/valadbusclientmodule.vala
==============================================================================
--- trunk/gobject/valadbusclientmodule.vala	(original)
+++ trunk/gobject/valadbusclientmodule.vala	Mon Nov  3 20:50:43 2008
@@ -41,22 +41,22 @@
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
 		var instance_param = new CCodeFormalParameter ("obj", dynamic_method.dynamic_type.get_cname ());
-		cparam_map.set (codegen.get_param_pos (method.cinstance_parameter_position), instance_param);
+		cparam_map.set (get_param_pos (method.cinstance_parameter_position), instance_param);
 
 		generate_cparameters (method, method.return_type, false, cparam_map, func);
 
 		var block = new CCodeBlock ();
-		if (dynamic_method.dynamic_type.data_type == codegen.dbus_object_type) {
+		if (dynamic_method.dynamic_type.data_type == dbus_object_type) {
 			generate_dbus_method_wrapper (method, block);
 		} else {
 			Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
 		}
 
 		// append to C source file
-		codegen.source_type_member_declaration.append (func.copy ());
+		source_type_member_declaration.append (func.copy ());
 
 		func.block = block;
-		codegen.source_type_member_definition.append (func);
+		source_type_member_definition.append (func);
 	}
 
 	void generate_dbus_method_wrapper (Method method, CCodeBlock block) {
@@ -136,10 +136,10 @@
 
 					break;
 				}
-				if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type != codegen.string_type.data_type) {
+				if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type != string_type.data_type) {
 					var array_type = (ArrayType) param.parameter_type;
 					CCodeDeclaration cdecl;
-					if (codegen.dbus_use_ptr_array (array_type)) {
+					if (dbus_use_ptr_array (array_type)) {
 						cdecl = new CCodeDeclaration ("GPtrArray*");
 					} else {
 						cdecl = new CCodeDeclaration ("GArray*");
@@ -148,13 +148,13 @@
 					cb_fun.block.add_statement (cdecl);
 					cend_call.add_argument (get_dbus_g_type (array_type));
 					cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
-					creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), codegen.dbus_use_ptr_array (array_type) ? "pdata" : "data"));
+					creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), dbus_use_ptr_array (array_type) ? "pdata" : "data"));
 					creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
 				} else {
 					var cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
 					cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
 					cb_fun.block.add_statement (cdecl);
-					if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == codegen.string_type.data_type) {
+					if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) {
 						// special case string array
 						cend_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
 					} else {
@@ -163,7 +163,7 @@
 					cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
 					creply_call.add_argument (new CCodeIdentifier (param.name));
 
-					if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == codegen.string_type.data_type) {
+					if (param.parameter_type is ArrayType && ((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) {
 						var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
 						cstrvlen.add_argument (new CCodeIdentifier (param.name));
 						creply_call.add_argument (cstrvlen);
@@ -175,7 +175,7 @@
 			cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
 			creply_call.add_argument (new CCodeIdentifier ("error"));
 			cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
-			codegen.source_type_member_definition.append (cb_fun);
+			source_type_member_definition.append (cb_fun);
 
 			ccall.add_argument (new CCodeIdentifier (cb_fun.name));
 			ccall.add_argument (new CCodeConstant ("param%d_target".printf (callback_index)));
@@ -202,7 +202,7 @@
 			var array_type = param.parameter_type as ArrayType;
 			if (array_type != null) {
 				// array parameter
-				if (array_type.element_type.data_type != codegen.string_type.data_type) {
+				if (array_type.element_type.data_type != string_type.data_type) {
 					// non-string arrays (use GArray)
 					ccall.add_argument (get_dbus_g_type (array_type));
 
@@ -211,7 +211,7 @@
 
 					CCodeDeclaration cdecl;
 					CCodeFunctionCall array_construct;
-					if (codegen.dbus_use_ptr_array (array_type)) {
+					if (dbus_use_ptr_array (array_type)) {
 						cdecl = new CCodeDeclaration ("GPtrArray*");
 
 						array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new"));
@@ -228,7 +228,7 @@
 					cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("dbus_%s".printf (param.name), array_construct));
 					block.add_statement (cdecl);
 
-					if (codegen.dbus_use_ptr_array (array_type)) {
+					if (dbus_use_ptr_array (array_type)) {
 						var memcpy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
 						memcpy_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata"));
 						memcpy_call.add_argument (new CCodeIdentifier (param.name));
@@ -363,12 +363,12 @@
 		if (!(method.return_type is VoidType)) {
 			// synchronous D-Bus method call with reply
 			var array_type = method.return_type as ArrayType;
-			if (array_type != null && array_type.element_type.data_type != codegen.string_type.data_type) {
+			if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
 				// non-string arrays (use GArray)
 				ccall.add_argument (get_dbus_g_type (array_type));
 
 				CCodeDeclaration cdecl;
-				if (codegen.dbus_use_ptr_array (array_type)) {
+				if (dbus_use_ptr_array (array_type)) {
 					cdecl = new CCodeDeclaration ("GPtrArray*");
 				} else {
 					cdecl = new CCodeDeclaration ("GArray*");
@@ -383,7 +383,7 @@
 
 				// don't access result when error occured
 				var creturnblock = new CCodeBlock ();
-				creturnblock.add_statement (new CCodeReturnStatement (codegen.default_value_for_type (method.return_type, false)));
+				creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
 				var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
 				block.add_statement (cerrorif);
 
@@ -396,7 +396,7 @@
 				block.add_statement (new CCodeExpressionStatement (assign));
 
 				// return result->data;
-				block.add_statement (new CCodeReturnStatement (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), codegen.dbus_use_ptr_array (array_type) ? "pdata" : "data"), method.return_type.get_cname ())));
+				block.add_statement (new CCodeReturnStatement (new CCodeCastExpression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), dbus_use_ptr_array (array_type) ? "pdata" : "data"), method.return_type.get_cname ())));
 			} else {
 				// string arrays or other datatypes
 
@@ -413,7 +413,7 @@
 
 				// don't access result when error occured
 				var creturnblock = new CCodeBlock ();
-				creturnblock.add_statement (new CCodeReturnStatement (codegen.default_value_for_type (method.return_type, false)));
+				creturnblock.add_statement (new CCodeReturnStatement (default_value_for_type (method.return_type, false)));
 				var cerrorif = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error")), creturnblock);
 				block.add_statement (cerrorif);
 
@@ -448,12 +448,12 @@
 	CCodeExpression get_dbus_g_type (DataType data_type) {
 		if (data_type is ArrayType) {
 			var array_type = data_type as ArrayType;
-			if (array_type.element_type.data_type == codegen.string_type.data_type) {
+			if (array_type.element_type.data_type == string_type.data_type) {
 				return new CCodeIdentifier ("G_TYPE_STRV");
 			}
 
 			var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
-			if (codegen.dbus_use_ptr_array (array_type)) {
+			if (dbus_use_ptr_array (array_type)) {
 				carray_type.add_argument (new CCodeConstant ("\"GPtrArray\""));
 			} else {
 				carray_type.add_argument (new CCodeConstant ("\"GArray\""));

Modified: trunk/gobject/valadbusservermodule.vala
==============================================================================
--- trunk/gobject/valadbusservermodule.vala	(original)
+++ trunk/gobject/valadbusservermodule.vala	Mon Nov  3 20:50:43 2008
@@ -69,7 +69,7 @@
 			return fragment;
 		}
 
-		codegen.dbus_glib_h_needed = true;
+		dbus_glib_h_needed = true;
 
 		var dbus_methods = new StringBuilder ();
 		dbus_methods.append ("{\n");
@@ -95,17 +95,17 @@
 			if (!(m.return_type is VoidType)) {
 				parameters.add (new FormalParameter ("result", new PointerType (new VoidType ())));
 			}
-			parameters.add (new FormalParameter ("error", codegen.gerror_type));
+			parameters.add (new FormalParameter ("error", gerror_type));
 
 			dbus_methods.append ("{ (GCallback) ");
 			dbus_methods.append (generate_dbus_wrapper (m, bindable));
 			dbus_methods.append (", ");
-			dbus_methods.append (head.get_marshaller_function (parameters, codegen.bool_type, null, true));
+			dbus_methods.append (head.get_marshaller_function (parameters, bool_type, null, true));
 			dbus_methods.append (", ");
 			dbus_methods.append (blob_len.to_string ());
 			dbus_methods.append (" },\n");
 
-			head.generate_marshaller (parameters, codegen.bool_type, true);
+			head.generate_marshaller (parameters, bool_type, true);
 
 			long start = blob.len;
 
@@ -243,8 +243,8 @@
 		foreach (FormalParameter param in m.get_parameters ()) {
 			string ptr = (param.direction == ParameterDirection.OUT ? "*" : "");
 			var array_type = param.parameter_type as ArrayType;
-			if (array_type != null && array_type.element_type.data_type != codegen.string_type.data_type) {
-				if (codegen.dbus_use_ptr_array (array_type)) {
+			if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
+				if (dbus_use_ptr_array (array_type)) {
 					function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GPtrArray*" + ptr));
 				} else {
 					function.add_parameter (new CCodeFormalParameter ("dbus_%s".printf (param.name), "GArray*" + ptr));
@@ -259,9 +259,9 @@
 		if (!(m.return_type is VoidType)) {
 			var array_type = m.return_type as ArrayType;
 			if (array_type != null) {
-				if (array_type.element_type.data_type == codegen.string_type.data_type) {
+				if (array_type.element_type.data_type == string_type.data_type) {
 					function.add_parameter (new CCodeFormalParameter ("result", array_type.get_cname () + "*"));
-				} else if (codegen.dbus_use_ptr_array (array_type)) {
+				} else if (dbus_use_ptr_array (array_type)) {
 					function.add_parameter (new CCodeFormalParameter ("dbus_result", "GPtrArray**"));
 				} else {
 					function.add_parameter (new CCodeFormalParameter ("dbus_result", "GArray**"));
@@ -306,7 +306,7 @@
 		if (!(m.return_type is VoidType)) {
 			var array_type = m.return_type as ArrayType;
 			if (array_type != null) {
-				if (array_type.element_type.data_type != codegen.string_type.data_type) {
+				if (array_type.element_type.data_type != string_type.data_type) {
 					var cdecl = new CCodeDeclaration (m.return_type.get_cname ());
 					cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
 					block.add_statement (cdecl);
@@ -326,14 +326,14 @@
 			var array_type = param.parameter_type as ArrayType;
 			if (array_type != null) {
 				if (param.direction == ParameterDirection.IN) {
-					if (array_type.element_type.data_type == codegen.string_type.data_type) {
+					if (array_type.element_type.data_type == string_type.data_type) {
 						ccall.add_argument (new CCodeIdentifier (param.name));
 						if (!m.no_array_length) {
 							var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
 							cstrvlen.add_argument (new CCodeIdentifier (param.name));
 							ccall.add_argument (cstrvlen);
 						}
-					} else if (codegen.dbus_use_ptr_array (array_type)) {
+					} else if (dbus_use_ptr_array (array_type)) {
 						ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "pdata"));
 						if (!m.no_array_length) {
 							ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dbus_%s".printf (param.name)), "len"));
@@ -345,7 +345,7 @@
 						}
 					}
 				} else {
-					if (array_type.element_type.data_type != codegen.string_type.data_type) {
+					if (array_type.element_type.data_type != string_type.data_type) {
 						var cdecl = new CCodeDeclaration (param.parameter_type.get_cname ());
 						cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
 						block.add_statement (cdecl);
@@ -378,7 +378,7 @@
 			var array_type = m.return_type as ArrayType;
 			if (array_type != null) {
 				ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result_length1")));
-				if (array_type.element_type.data_type != codegen.string_type.data_type) {
+				if (array_type.element_type.data_type != string_type.data_type) {
 					expr = new CCodeAssignment (new CCodeIdentifier ("result"), ccall);
 				} else {
 					expr = new CCodeAssignment (new CCodeIdentifier ("*result"), ccall);
@@ -449,13 +449,13 @@
 
 		if (!(m.return_type is VoidType)) {
 			var array_type = m.return_type as ArrayType;
-			if (array_type != null && array_type.element_type.data_type != codegen.string_type.data_type) {
+			if (array_type != null && array_type.element_type.data_type != string_type.data_type) {
 				var garray = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("dbus_result"));
 
 				var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
 				sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
 
-				if (codegen.dbus_use_ptr_array (array_type)) {
+				if (dbus_use_ptr_array (array_type)) {
 					var array_construct = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_sized_new"));
 					array_construct.add_argument (new CCodeIdentifier ("result_length1"));
 
@@ -491,10 +491,10 @@
 
 		// append to file
 
-		codegen.source_type_member_declaration.append (function.copy ());
+		source_type_member_declaration.append (function.copy ());
 
 		function.block = block;
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 
 		return wrapper_name;
 	}

Modified: trunk/gobject/valagasyncmodule.vala
==============================================================================
--- trunk/gobject/valagasyncmodule.vala	(original)
+++ trunk/gobject/valagasyncmodule.vala	Mon Nov  3 20:50:43 2008
@@ -38,7 +38,7 @@
 		var creturn_type = m.return_type;
 		bool visible = !m.is_internal_symbol ();
 
-		codegen.gio_h_needed = true;
+		gio_h_needed = true;
 
 		// generate struct to hold parameters, local variables, and the return value
 		string dataname = Symbol.lower_case_to_camel_case (m.get_cname ()) + "Data";
@@ -57,12 +57,12 @@
 			datastruct.add_field (m.return_type.get_cname (), "result");
 		}
 
-		codegen.source_type_definition.append (datastruct);
-		codegen.source_type_declaration.append (new CCodeTypeDefinition ("struct _" + dataname, new CCodeVariableDeclarator (dataname)));
+		source_type_definition.append (datastruct);
+		source_type_declaration.append (new CCodeTypeDefinition ("struct _" + dataname, new CCodeVariableDeclarator (dataname)));
 
 		// generate async function
 		var asyncfunc = new CCodeFunction (m.get_cname (), "void");
-		asyncfunc.line = codegen.function.line;
+		asyncfunc.line = function.line;
 
 		var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
@@ -87,48 +87,48 @@
 		ccall.add_argument (new CCodeIdentifier ("data"));
 		asyncblock.add_statement (new CCodeExpressionStatement (ccall));
 
-		cparam_map.set (codegen.get_param_pos (-1), new CCodeFormalParameter ("callback", "GAsyncReadyCallback"));
-		cparam_map.set (codegen.get_param_pos (-0.9), new CCodeFormalParameter ("user_data", "gpointer"));
+		cparam_map.set (get_param_pos (-1), new CCodeFormalParameter ("callback", "GAsyncReadyCallback"));
+		cparam_map.set (get_param_pos (-0.9), new CCodeFormalParameter ("user_data", "gpointer"));
 
 		generate_cparameters (m, creturn_type, false, cparam_map, asyncfunc, null, null, null, 1);
 
 		if (visible) {
-			codegen.header_type_member_declaration.append (asyncfunc.copy ());
+			header_type_member_declaration.append (asyncfunc.copy ());
 		} else {
 			asyncfunc.modifiers |= CCodeModifiers.STATIC;
-			codegen.source_type_member_declaration.append (asyncfunc.copy ());
+			source_type_member_declaration.append (asyncfunc.copy ());
 		}
 		
 		asyncfunc.block = asyncblock;
 
-		codegen.source_type_member_definition.append (asyncfunc);
+		source_type_member_definition.append (asyncfunc);
 
 		// generate finish function
 		var finishfunc = new CCodeFunction (m.get_cname () + "_finish", creturn_type.get_cname ());
-		finishfunc.line = codegen.function.line;
+		finishfunc.line = function.line;
 
 		cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
 
 		var finishblock = new CCodeBlock ();
 
-		cparam_map.set (codegen.get_param_pos (0.1), new CCodeFormalParameter ("res", "GAsyncResult*"));
+		cparam_map.set (get_param_pos (0.1), new CCodeFormalParameter ("res", "GAsyncResult*"));
 
 		generate_cparameters (m, creturn_type, false, cparam_map, finishfunc, null, null, null, 2);
 
 		if (visible) {
-			codegen.header_type_member_declaration.append (finishfunc.copy ());
+			header_type_member_declaration.append (finishfunc.copy ());
 		} else {
 			finishfunc.modifiers |= CCodeModifiers.STATIC;
-			codegen.source_type_member_declaration.append (finishfunc.copy ());
+			source_type_member_declaration.append (finishfunc.copy ());
 		}
 		
 		finishfunc.block = finishblock;
 
-		codegen.source_type_member_definition.append (finishfunc);
+		source_type_member_definition.append (finishfunc);
 
 		// generate ready callback handler
 		var readyfunc = new CCodeFunction (m.get_cname () + "_ready", "void");
-		readyfunc.line = codegen.function.line;
+		readyfunc.line = function.line;
 
 		readyfunc.add_parameter (new CCodeFormalParameter ("source_object", "GObject*"));
 		readyfunc.add_parameter (new CCodeFormalParameter ("res", "GAsyncResult*"));
@@ -147,10 +147,10 @@
 		readyblock.add_statement (new CCodeExpressionStatement (ccall));
 
 		readyfunc.modifiers |= CCodeModifiers.STATIC;
-		codegen.source_type_member_declaration.append (readyfunc.copy ());
+		source_type_member_declaration.append (readyfunc.copy ());
 
 		readyfunc.block = readyblock;
 
-		codegen.source_type_member_definition.append (readyfunc);
+		source_type_member_definition.append (readyfunc);
 	}
 }

Modified: trunk/gobject/valagerrormodule.vala
==============================================================================
--- trunk/gobject/valagerrormodule.vala	(original)
+++ trunk/gobject/valagerrormodule.vala	Mon Nov  3 20:50:43 2008
@@ -34,7 +34,7 @@
 		var cfrag = new CCodeFragment ();
 
 		// method will fail
-		codegen.current_method_inner_error = true;
+		current_method_inner_error = true;
 		var cassign = new CCodeAssignment (new CCodeIdentifier ("inner_error"), (CCodeExpression) stmt.error_expression.ccodenode);
 		cfrag.append (new CCodeExpressionStatement (cassign));
 
@@ -42,11 +42,11 @@
 
 		stmt.ccodenode = cfrag;
 
-		codegen.create_temp_decl (stmt, stmt.error_expression.temp_vars);
+		create_temp_decl (stmt, stmt.error_expression.temp_vars);
 	}
 
 	public override void add_simple_check (CodeNode node, CCodeFragment cfrag) {
-		codegen.current_method_inner_error = true;
+		current_method_inner_error = true;
 
 		var cprint_frag = new CCodeFragment ();
 		var ccritical = new CCodeFunctionCall (new CCodeIdentifier ("g_critical"));
@@ -59,16 +59,16 @@
 		cclear.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("inner_error")));
 		cprint_frag.append (new CCodeExpressionStatement (cclear));
 
-		if (codegen.current_try != null) {
+		if (current_try != null) {
 			// surrounding try found
 			// TODO might be the wrong one when using nested try statements
 
 			var cerror_block = new CCodeBlock ();
-			foreach (CatchClause clause in codegen.current_try.get_catch_clauses ()) {
+			foreach (CatchClause clause in current_try.get_catch_clauses ()) {
 				// go to catch clause if error domain matches
 				var cgoto_stmt = new CCodeGotoStatement (clause.clabel_name);
 
-				if (clause.error_type.equals (codegen.gerror_type)) {
+				if (clause.error_type.equals (gerror_type)) {
 					// general catch clause
 					cerror_block.add_statement (cgoto_stmt);
 				} else {
@@ -87,7 +87,7 @@
 			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("inner_error"), new CCodeConstant ("NULL"));
 
 			cfrag.append (new CCodeIfStatement (ccond, cerror_block));
-		} else if (codegen.current_method != null && codegen.current_method.get_error_types ().size > 0) {
+		} else if (current_method != null && current_method.get_error_types ().size > 0) {
 			// current method can fail, propagate error
 			// TODO ensure one of the error domains matches
 
@@ -100,13 +100,13 @@
 
 			// free local variables
 			var free_frag = new CCodeFragment ();
-			codegen.append_local_free (codegen.current_symbol, free_frag, false);
+			append_local_free (current_symbol, free_frag, false);
 			cerror_block.add_statement (free_frag);
 
-			if (codegen.current_return_type is VoidType) {
+			if (current_return_type is VoidType) {
 				cerror_block.add_statement (new CCodeReturnStatement ());
 			} else {
-				cerror_block.add_statement (new CCodeReturnStatement (codegen.default_value_for_type (codegen.current_return_type, false)));
+				cerror_block.add_statement (new CCodeReturnStatement (default_value_for_type (current_return_type, false)));
 			}
 
 			var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier ("inner_error"), new CCodeConstant ("NULL"));

Modified: trunk/gobject/valagirwriter.vala
==============================================================================
--- trunk/gobject/valagirwriter.vala	(original)
+++ trunk/gobject/valagirwriter.vala	Mon Nov  3 20:50:43 2008
@@ -395,7 +395,7 @@
 
 		DataType instance_type = null;
 		if (m.binding == MemberBinding.INSTANCE) {
-			instance_type = CCodeGenerator.get_data_type_for_symbol ((TypeSymbol) m.parent_symbol);
+			instance_type = CCodeBaseModule.get_data_type_for_symbol ((TypeSymbol) m.parent_symbol);
 		}
 
 		write_params (m.get_parameters (), instance_type);
@@ -423,7 +423,7 @@
 
 		write_params (m.get_parameters ());
 
-		write_return_type (CCodeGenerator.get_data_type_for_symbol ((TypeSymbol) m.parent_symbol));
+		write_return_type (CCodeBaseModule.get_data_type_for_symbol ((TypeSymbol) m.parent_symbol));
 
 		indent--;
 		write_indent ();

Modified: trunk/gobject/valagobjectmodule.vala
==============================================================================
--- trunk/gobject/valagobjectmodule.vala	(original)
+++ trunk/gobject/valagobjectmodule.vala	Mon Nov  3 20:50:43 2008
@@ -29,23 +29,23 @@
 	}
 
 	public override void visit_class (Class cl) {
-		var old_symbol = codegen.current_symbol;
-		var old_type_symbol = codegen.current_type_symbol;
-		var old_class = codegen.current_class;
-		var old_instance_struct = codegen.instance_struct;
-		var old_param_spec_struct = codegen.param_spec_struct;
-		var old_type_struct = codegen.type_struct;
-		var old_instance_priv_struct = codegen.instance_priv_struct;
-		var old_prop_enum = codegen.prop_enum;
-		var old_class_init_fragment = codegen.class_init_fragment;
-		var old_instance_init_fragment = codegen.instance_init_fragment;
-		var old_instance_finalize_fragment = codegen.instance_finalize_fragment;
-		codegen.current_symbol = cl;
-		codegen.current_type_symbol = cl;
-		codegen.current_class = cl;
+		var old_symbol = current_symbol;
+		var old_type_symbol = current_type_symbol;
+		var old_class = current_class;
+		var old_instance_struct = instance_struct;
+		var old_param_spec_struct = param_spec_struct;
+		var old_type_struct = type_struct;
+		var old_instance_priv_struct = instance_priv_struct;
+		var old_prop_enum = prop_enum;
+		var old_class_init_fragment = class_init_fragment;
+		var old_instance_init_fragment = instance_init_fragment;
+		var old_instance_finalize_fragment = instance_finalize_fragment;
+		current_symbol = cl;
+		current_type_symbol = cl;
+		current_class = cl;
 		
 		bool is_gtypeinstance = !cl.is_compact;
-		bool is_gobject = cl.is_subtype_of (codegen.gobject_type);
+		bool is_gobject = cl.is_subtype_of (gobject_type);
 		bool is_fundamental = is_gtypeinstance && cl.base_class == null;
 
 		if (cl.get_cname().len () < 3) {
@@ -55,24 +55,24 @@
 		}
 
 
-		codegen.instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
-		codegen.type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
-		codegen.instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
-		codegen.prop_enum = new CCodeEnum ();
-		codegen.prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null))));
-		codegen.class_init_fragment = new CCodeFragment ();
-		codegen.instance_init_fragment = new CCodeFragment ();
-		codegen.instance_finalize_fragment = new CCodeFragment ();
+		instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ()));
+		type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ()));
+		instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ()));
+		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 ();
+		instance_init_fragment = new CCodeFragment ();
+		instance_finalize_fragment = new CCodeFragment ();
 
 
 		CCodeFragment decl_frag;
 		CCodeFragment def_frag;
 		if (cl.access != SymbolAccessibility.PRIVATE) {
-			decl_frag = codegen.header_type_declaration;
-			def_frag = codegen.header_type_definition;
+			decl_frag = header_type_declaration;
+			def_frag = header_type_definition;
 		} else {
-			decl_frag = codegen.source_type_declaration;
-			def_frag = codegen.source_type_definition;
+			decl_frag = source_type_declaration;
+			def_frag = source_type_definition;
 		}
 
 		if (is_gtypeinstance) {
@@ -87,10 +87,10 @@
 			decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro));
 
 			macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_type_id ());
-			decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (codegen.get_type_check_function (cl)), macro));
+			decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (cl)), macro));
 
 			macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_type_id ());
-			decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (codegen.get_type_check_function (cl)), macro));
+			decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (get_type_check_function (cl)), macro));
 
 			macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ());
 			decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro));
@@ -99,64 +99,64 @@
 
 
 		if (cl.source_reference.file.cycle == null) {
-			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ())));
+			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ())));
 		}
 
 		if (cl.base_class != null) {
-			codegen.instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
+			instance_struct.add_field (cl.base_class.get_cname (), "parent_instance");
 		} else if (is_fundamental) {
-			codegen.instance_struct.add_field ("GTypeInstance", "parent_instance");
-			codegen.instance_struct.add_field ("volatile int", "ref_count");
+			instance_struct.add_field ("GTypeInstance", "parent_instance");
+			instance_struct.add_field ("volatile int", "ref_count");
 		}
 
 		if (cl.is_compact && cl.base_class == null && cl.get_fields ().size == 0) {
 			// add dummy member, C doesn't allow empty structs
-			codegen.instance_struct.add_field ("int", "dummy");
+			instance_struct.add_field ("int", "dummy");
 		}
 
 		if (is_gtypeinstance) {
 			if (cl.source_reference.file.cycle == null) {
-				decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
+				decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ()))));
 			}
-			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
+			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ()))));
 
-			codegen.instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
+			instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
 			if (is_fundamental) {
-				codegen.type_struct.add_field ("GTypeClass", "parent_class");
-				codegen.type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
+				type_struct.add_field ("GTypeClass", "parent_class");
+				type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ()));
 			} else {
-				codegen.type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
+				type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class");
 			}
 		}
 
 		if (cl.source_reference.comment != null) {
 			def_frag.append (new CCodeComment (cl.source_reference.comment));
 		}
-		def_frag.append (codegen.instance_struct);
+		def_frag.append (instance_struct);
 
 		if (is_gtypeinstance) {
-			def_frag.append (codegen.type_struct);
+			def_frag.append (type_struct);
 			/* only add the *Private struct if it is not empty, i.e. we actually have private data */
 			if (cl.has_private_fields || cl.get_type_parameters ().size > 0) {
-				codegen.source_type_member_declaration.append (codegen.instance_priv_struct);
+				source_type_member_declaration.append (instance_priv_struct);
 				var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ());
-				codegen.source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
+				source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro));
 			}
-			codegen.source_type_member_declaration.append (codegen.prop_enum);
+			source_type_member_declaration.append (prop_enum);
 		}
 
 		cl.accept_children (codegen);
 
 		if (is_gtypeinstance) {
 			if (is_fundamental) {
-				codegen.param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name));
-				codegen.param_spec_struct.add_field ("GParamSpec", "parent_instance");
-				def_frag.append (codegen.param_spec_struct);
+				param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name));
+				param_spec_struct.add_field ("GParamSpec", "parent_instance");
+				def_frag.append (param_spec_struct);
 
-				decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
+				decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name))));
 
 
-				codegen.gvaluecollector_h_needed = true;
+				gvaluecollector_h_needed = true;
 
 				add_type_value_table_init_function (cl);
 				add_type_value_table_free_function (cl);
@@ -169,7 +169,7 @@
 				add_g_value_set_function (cl);
 
 				var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1"));
-				codegen.instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
+				instance_init_fragment.append (new CCodeExpressionStatement (ref_count));
 			} else if (is_gobject) {
 				if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) {
 					add_get_property_function (cl);
@@ -192,20 +192,20 @@
 				add_finalize_function (cl);
 			}
 
-			var type_fun = new ClassRegisterFunction (cl, codegen);
-			type_fun.init_from_type (codegen.in_plugin);
+			var type_fun = new ClassRegisterFunction (cl, context);
+			type_fun.init_from_type (in_plugin);
 			if (cl.access != SymbolAccessibility.PRIVATE) {
-				codegen.header_type_member_declaration.append (type_fun.get_declaration ());
+				header_type_member_declaration.append (type_fun.get_declaration ());
 			} else {
-				codegen.source_type_member_declaration.append (type_fun.get_declaration ());
+				source_type_member_declaration.append (type_fun.get_declaration ());
 			}
-			codegen.source_type_member_definition.append (type_fun.get_definition ());
+			source_type_member_definition.append (type_fun.get_definition ());
 			
-			if (codegen.in_plugin) {
+			if (in_plugin) {
 				// FIXME resolve potential dependency issues, i.e. base types have to be registered before derived types
 				var register_call = new CCodeFunctionCall (new CCodeIdentifier ("%s_register_type".printf (cl.get_lower_case_cname (null))));
-				register_call.add_argument (new CCodeIdentifier (codegen.module_init_param_name));
-				codegen.module_init_fragment.append (new CCodeExpressionStatement (register_call));
+				register_call.add_argument (new CCodeIdentifier (module_init_param_name));
+				module_init_fragment.append (new CCodeExpressionStatement (register_call));
 			}
 
 			if (is_fundamental) {
@@ -220,11 +220,11 @@
 				unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer"));
 
 				if (cl.access != SymbolAccessibility.PRIVATE) {
-					codegen.header_type_member_declaration.append (ref_fun.copy ());
-					codegen.header_type_member_declaration.append (unref_fun.copy ());
+					header_type_member_declaration.append (ref_fun.copy ());
+					header_type_member_declaration.append (unref_fun.copy ());
 				} else {
-					codegen.source_type_member_declaration.append (ref_fun.copy ());
-					codegen.source_type_member_declaration.append (unref_fun.copy ());
+					source_type_member_declaration.append (ref_fun.copy ());
+					source_type_member_declaration.append (unref_fun.copy ());
 				}
 
 				var ref_block = new CCodeBlock ();
@@ -266,8 +266,8 @@
 				ref_fun.block = ref_block;
 				unref_fun.block = unref_block;
 
-				codegen.source_type_member_definition.append (ref_fun);
-				codegen.source_type_member_definition.append (unref_fun);
+				source_type_member_definition.append (ref_fun);
+				source_type_member_definition.append (unref_fun);
 			}
 		} else {
 			add_instance_init_function (cl);
@@ -280,14 +280,14 @@
 			function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*"));
 
 			if (cl.access != SymbolAccessibility.PRIVATE) {
-				codegen.header_type_member_declaration.append (function.copy ());
+				header_type_member_declaration.append (function.copy ());
 			} else {
-				codegen.source_type_member_declaration.append (function.copy ());
+				source_type_member_declaration.append (function.copy ());
 			}
 
 			var cblock = new CCodeBlock ();
 
-			cblock.add_statement (codegen.instance_finalize_fragment);
+			cblock.add_statement (instance_finalize_fragment);
 
 			if (cl.destructor != null) {
 				cblock.add_statement (cl.destructor.ccodenode);
@@ -300,18 +300,18 @@
 
 			function.block = cblock;
 
-			codegen.source_type_member_definition.append (function);
+			source_type_member_definition.append (function);
 		}
 
-		codegen.current_type_symbol = old_type_symbol;
-		codegen.current_class = old_class;
-		codegen.instance_struct = old_instance_struct;
-		codegen.type_struct = old_type_struct;
-		codegen.instance_priv_struct = old_instance_priv_struct;
-		codegen.prop_enum = old_prop_enum;
-		codegen.class_init_fragment = old_class_init_fragment;
-		codegen.instance_init_fragment = old_instance_init_fragment;
-		codegen.instance_finalize_fragment = old_instance_finalize_fragment;
+		current_type_symbol = old_type_symbol;
+		current_class = old_class;
+		instance_struct = old_instance_struct;
+		type_struct = old_type_struct;
+		instance_priv_struct = old_instance_priv_struct;
+		prop_enum = old_prop_enum;
+		class_init_fragment = old_class_init_fragment;
+		instance_init_fragment = old_instance_init_fragment;
+		instance_finalize_fragment = old_instance_finalize_fragment;
 	}
 
 	private void add_type_value_table_init_function (Class cl) {
@@ -323,7 +323,7 @@
 		function.block = init_block;
 
 		init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"),new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_type_value_table_free_function (Class cl) {
@@ -342,7 +342,7 @@
 		ifbody.add_statement ( new CCodeExpressionStatement(ccall) );
 
 		init_block.add_statement(new CCodeIfStatement (vpointer, ifbody));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_type_value_table_copy_function (Class cl) {
@@ -369,7 +369,7 @@
 		var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt);
 		init_block.add_statement (if_statement);
 
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_type_value_table_peek_pointer_function (Class cl) {
@@ -384,7 +384,7 @@
 		var ret = new CCodeReturnStatement ( vpointer );
 		init_block.add_statement (ret);
 
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_type_value_table_lcopy_value_function ( Class cl ) {
@@ -429,7 +429,7 @@
 		main_else_true.add_statement (new CCodeExpressionStatement( new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE)));
 
 		init_block.add_statement ( new CCodeReturnStatement ( null_ ));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_type_value_table_collect_value_function (Class cl) {
@@ -499,7 +499,7 @@
 		false_stmt.add_statement ( else_assigment );
 
 		init_block.add_statement ( new CCodeReturnStatement ( new CCodeConstant("NULL") ));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_g_param_spec_type_function (Class cl) {
@@ -516,9 +516,9 @@
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			codegen.source_type_member_declaration.append (function.copy ());
+			source_type_member_declaration.append (function.copy ());
 		} else {
-			codegen.header_type_member_declaration.append (function.copy ());		
+			header_type_member_declaration.append (function.copy ());		
 		}
 
 		var init_block = new CCodeBlock ();
@@ -551,7 +551,7 @@
 
 		init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "value_type"), new CCodeIdentifier ("object_type"), CCodeAssignmentOperator.SIMPLE )));
 		init_block.add_statement (new CCodeReturnStatement (ccall));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_g_value_set_function (Class cl) {
@@ -561,9 +561,9 @@
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			codegen.source_type_member_declaration.append (function.copy ());
+			source_type_member_declaration.append (function.copy ());
 		} else {
-			codegen.header_type_member_declaration.append (function.copy ());		
+			header_type_member_declaration.append (function.copy ());		
 		}
 
 		var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
@@ -628,7 +628,7 @@
 		ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ()));
 		ccall.add_argument (new CCodeIdentifier ("old"));
 		true_stmt.add_statement (new CCodeExpressionStatement (ccall));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_g_value_get_function (Class cl) {
@@ -637,9 +637,9 @@
 
 		if (cl.access == SymbolAccessibility.PRIVATE) {
 			function.modifiers = CCodeModifiers.STATIC;
-			codegen.source_type_member_declaration.append (function.copy ());
+			source_type_member_declaration.append (function.copy ());
 		} else {
-			codegen.header_type_member_declaration.append (function.copy ());		
+			header_type_member_declaration.append (function.copy ());		
 		}
 
 		var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer");
@@ -657,7 +657,7 @@
 		init_block.add_statement (new CCodeExpressionStatement (ccall));
 
 		init_block.add_statement (new CCodeReturnStatement ( vpointer ));
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private void add_class_init_function (Class cl) {
@@ -676,14 +676,14 @@
 		parent_var_decl.initializer = new CCodeConstant ("NULL");
 		parent_decl.add_declarator (parent_var_decl);
 		parent_decl.modifiers = CCodeModifiers.STATIC;
-		codegen.source_type_member_declaration.append (parent_decl);
+		source_type_member_declaration.append (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));
 		
 
-		if (!cl.is_compact && !cl.is_subtype_of (codegen.gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
+		if (!cl.is_compact && !cl.is_subtype_of (gobject_type) && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) {
 			// set finalize function
 			var fundamental_class = cl;
 			while (fundamental_class.base_class != null) {
@@ -704,7 +704,7 @@
 			init_block.add_statement (new CCodeExpressionStatement (ccall));
 		}
 
-		if (cl.is_subtype_of (codegen.gobject_type)) {
+		if (cl.is_subtype_of (gobject_type)) {
 			/* set property handlers */
 			ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS"));
 			ccall.add_argument (new CCodeIdentifier ("klass"));
@@ -762,7 +762,7 @@
 			}
 		}
 
-		if (cl.is_subtype_of (codegen.gobject_type)) {
+		if (cl.is_subtype_of (gobject_type)) {
 			/* create type, dup_func, and destroy_func properties for generic types */
 			foreach (TypeParameter type_param in cl.get_type_parameters ()) {
 				string func_name, enum_value;
@@ -783,9 +783,9 @@
 				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));
-				codegen.prop_enum.add_value (new CCodeEnumValue (enum_value));
+				prop_enum.add_value (new CCodeEnumValue (enum_value));
 
-				codegen.instance_priv_struct.add_field ("GType", func_name);
+				instance_priv_struct.add_field ("GType", func_name);
 
 
 				func_name = "%s_dup_func".printf (type_param.name.down ());
@@ -801,9 +801,9 @@
 				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));
-				codegen.prop_enum.add_value (new CCodeEnumValue (enum_value));
+				prop_enum.add_value (new CCodeEnumValue (enum_value));
 
-				codegen.instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
+				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
 
 
 				func_name = "%s_destroy_func".printf (type_param.name.down ());
@@ -819,9 +819,9 @@
 				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));
-				codegen.prop_enum.add_value (new CCodeEnumValue (enum_value));
+				prop_enum.add_value (new CCodeEnumValue (enum_value));
 
-				codegen.instance_priv_struct.add_field ("GDestroyNotify", func_name);
+				instance_priv_struct.add_field ("GDestroyNotify", func_name);
 			}
 
 			/* initialize class fields */
@@ -876,20 +876,20 @@
 				string func_name;
 
 				func_name = "%s_type".printf (type_param.name.down ());
-				codegen.instance_priv_struct.add_field ("GType", func_name);
+				instance_priv_struct.add_field ("GType", func_name);
 
 				func_name = "%s_dup_func".printf (type_param.name.down ());
-				codegen.instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
+				instance_priv_struct.add_field ("GBoxedCopyFunc", func_name);
 
 				func_name = "%s_destroy_func".printf (type_param.name.down ());
-				codegen.instance_priv_struct.add_field ("GDestroyNotify", func_name);
+				instance_priv_struct.add_field ("GDestroyNotify", func_name);
 			}
 		}
 
 		init_block.add_statement (head.register_dbus_info (cl));
-		init_block.add_statement (codegen.class_init_fragment);
+		init_block.add_statement (class_init_fragment);
 
-		codegen.source_type_member_definition.append (class_init);
+		source_type_member_definition.append (class_init);
 	}
 	
 	private void add_interface_init_function (Class cl, Interface iface) {
@@ -909,7 +909,7 @@
 		parent_var_decl.initializer = new CCodeConstant ("NULL");
 		parent_decl.add_declarator (parent_var_decl);
 		parent_decl.modifiers = CCodeModifiers.STATIC;
-		codegen.source_type_member_declaration.append (parent_decl);
+		source_type_member_declaration.append (parent_decl);
 		ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent"));
 		ccall.add_argument (new CCodeIdentifier ("iface"));
 		var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall);
@@ -1021,7 +1021,7 @@
 			}
 		}
 
-		codegen.source_type_member_definition.append (iface_init);
+		source_type_member_definition.append (iface_init);
 	}
 	
 	private void add_instance_init_function (Class cl) {
@@ -1032,7 +1032,7 @@
 		if (cl.is_compact) {
 			// Add declaration, since the instance_init function is explicitly called
 			// by the creation methods
-			codegen.source_type_member_declaration.append (instance_init.copy ());
+			source_type_member_declaration.append (instance_init.copy ());
 		}
 
 		var init_block = new CCodeBlock ();
@@ -1044,9 +1044,9 @@
 			init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall)));
 		}
 		
-		init_block.add_statement (codegen.instance_init_fragment);
+		init_block.add_statement (instance_init_fragment);
 
-		codegen.source_type_member_definition.append (instance_init);
+		source_type_member_definition.append (instance_init);
 	}
 	
 	private void add_finalize_function (Class cl) {
@@ -1060,7 +1060,7 @@
 
 		function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*"));
 
-		codegen.source_type_member_declaration.append (function.copy ());
+		source_type_member_declaration.append (function.copy ());
 
 
 		var cblock = new CCodeBlock ();
@@ -1076,7 +1076,7 @@
 			cblock.add_statement (cl.destructor.ccodenode);
 		}
 
-		cblock.add_statement (codegen.instance_finalize_fragment);
+		cblock.add_statement (instance_finalize_fragment);
 
 		// chain up to finalize function of the base class
 		if (cl.base_class != null) {
@@ -1090,7 +1090,7 @@
 
 		function.block = cblock;
 
-		codegen.source_type_member_definition.append (function);
+		source_type_member_definition.append (function);
 	}
 
 	private bool class_has_readable_properties (Class cl) {
@@ -1143,11 +1143,11 @@
 			if (prop.base_property != null) {
 				var base_type = (Class) prop.base_property.parent_symbol;
 				prefix = base_type.get_lower_case_cname (null);
-				cself = codegen.transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
+				cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
 			} else if (prop.base_interface_property != null) {
 				var base_type = (Interface) prop.base_interface_property.parent_symbol;
 				prefix = base_type.get_lower_case_cname (null);
-				cself = codegen.transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
+				cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
 			}
 
 			cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())));
@@ -1168,7 +1168,7 @@
 
 		get_prop.block = block;
 		
-		codegen.source_type_member_definition.append (get_prop);
+		source_type_member_definition.append (get_prop);
 	}
 	
 	private void add_set_property_function (Class cl) {
@@ -1203,11 +1203,11 @@
 			if (prop.base_property != null) {
 				var base_type = (Class) prop.base_property.parent_symbol;
 				prefix = base_type.get_lower_case_cname (null);
-				cself = codegen.transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
+				cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
 			} else if (prop.base_interface_property != null) {
 				var base_type = (Interface) prop.base_interface_property.parent_symbol;
 				prefix = base_type.get_lower_case_cname (null);
-				cself = codegen.transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
+				cself = transform_expression (cself, new ObjectType (cl), new ObjectType (base_type));
 			}
 
 			cswitch.add_statement (new CCodeCaseStatement (new CCodeIdentifier (prop.get_upper_case_cname ())));
@@ -1266,7 +1266,7 @@
 
 		set_prop.block = block;
 		
-		codegen.source_type_member_definition.append (set_prop);
+		source_type_member_definition.append (set_prop);
 	}
 
 	private CCodeStatement get_invalid_property_id_warn_statement () {
@@ -1293,7 +1293,7 @@
 				cspec.call = new CCodeIdentifier ( param_spec_name );
 				cspec.add_argument (new CCodeIdentifier (prop.property_type.data_type.get_type_id ()));
 			}
-		} else if (prop.property_type.data_type == codegen.string_type.data_type) {
+		} else if (prop.property_type.data_type == string_type.data_type) {
 			cspec.call = new CCodeIdentifier ("g_param_spec_string");
 			cspec.add_argument (new CCodeConstant ("NULL"));
 		} else if (prop.property_type.data_type is Enum) {

Modified: trunk/gobject/valagsignalmodule.vala
==============================================================================
--- trunk/gobject/valagsignalmodule.vala	(original)
+++ trunk/gobject/valagsignalmodule.vala	Mon Nov  3 20:50:43 2008
@@ -37,7 +37,7 @@
 			if (dbus) {
 				return ("BOXED");
 			} else {
-				if (((ArrayType) t).element_type.data_type == codegen.string_type.data_type) {
+				if (((ArrayType) t).element_type.data_type == string_type.data_type) {
 					return ("BOXED_INT");
 				} else {
 					return ("POINTER_INT");
@@ -65,7 +65,7 @@
 		string ret;
 
 		if (prefix == null) {
-			if (codegen.predefined_marshal_set.contains (signature)) {
+			if (predefined_marshal_set.contains (signature)) {
 				prefix = "g_cclosure_marshal";
 			} else {
 				prefix = "g_cclosure_user_marshal";
@@ -90,7 +90,7 @@
 			return "gpointer";
 		} else if (t is VoidType) {
 			return "void";
-		} else if (t.data_type == codegen.string_type.data_type) {
+		} else if (t.data_type == string_type.data_type) {
 			return "const char*";
 		} else if (t.data_type is Class || t.data_type is Interface) {
 			return "gpointer";
@@ -145,7 +145,7 @@
 		// parent_symbol may be null for late bound signals
 		if (sig.parent_symbol != null) {
 			var dt = sig.parent_symbol as TypeSymbol;
-			if (!dt.is_subtype_of (codegen.gobject_type)) {
+			if (!dt.is_subtype_of (gobject_type)) {
 				sig.error = true;
 				Report.error (sig.source_reference, "Only classes and interfaces deriving from GLib.Object support signals. `%s' does not derive from GLib.Object.".printf (dt.get_full_name ()));
 				return;
@@ -163,7 +163,7 @@
 		
 		/* check whether a signal with the same signature already exists for this source file (or predefined) */
 		signature = get_marshaller_signature (params, return_type, dbus);
-		if (codegen.predefined_marshal_set.contains (signature) || codegen.user_marshal_set.contains (signature)) {
+		if (predefined_marshal_set.contains (signature) || user_marshal_set.contains (signature)) {
 			return;
 		}
 		
@@ -177,7 +177,7 @@
 		signal_marshaller.add_parameter (new CCodeFormalParameter ("invocation_hint", "gpointer"));
 		signal_marshaller.add_parameter (new CCodeFormalParameter ("marshal_data", "gpointer"));
 		
-		codegen.source_signal_marshaller_declaration.append (signal_marshaller.copy ());
+		source_signal_marshaller_declaration.append (signal_marshaller.copy ());
 		
 		var marshaller_body = new CCodeBlock ();
 		
@@ -254,7 +254,7 @@
 				if (dbus) {
 					get_value_function = "g_value_get_boxed";
 				} else {
-					if (((ArrayType) p.parameter_type).element_type.data_type == codegen.string_type.data_type) {
+					if (((ArrayType) p.parameter_type).element_type.data_type == string_type.data_type) {
 						get_value_function = "g_value_get_boxed";
 					} else {
 						get_value_function = "g_value_get_pointer";
@@ -290,7 +290,7 @@
 				if (dbus) {
 					set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_boxed"));
 				} else {
-					if (((ArrayType) return_type).element_type.data_type == codegen.string_type.data_type) {
+					if (((ArrayType) return_type).element_type.data_type == string_type.data_type) {
 						set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_boxed"));
 					} else {
 						set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
@@ -300,7 +300,7 @@
 				set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
 			} else if (return_type is ErrorType) {
 				set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_set_pointer"));
-			} else if (return_type.data_type == codegen.string_type.data_type) {
+			} else if (return_type.data_type == string_type.data_type) {
 				set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_string"));
 			} else if (return_type.data_type is Class || return_type.data_type is Interface) {
 				set_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_take_object"));
@@ -319,8 +319,8 @@
 		
 		signal_marshaller.block = marshaller_body;
 		
-		codegen.source_signal_marshaller_definition.append (signal_marshaller);
-		codegen.user_marshal_set.add (signature);
+		source_signal_marshaller_definition.append (signal_marshaller);
+		user_marshal_set.add (signature);
 	}
 
 	public override CCodeFunctionCall get_signal_creation (Signal sig, TypeSymbol type) {	
@@ -359,7 +359,7 @@
 		csignew.add_argument (new CCodeConstant ("%d".printf (params_len)));
 		foreach (FormalParameter param in params) {
 			if (param.parameter_type.is_array ()) {
-				if (((ArrayType) param.parameter_type).element_type.data_type == codegen.string_type.data_type) {
+				if (((ArrayType) param.parameter_type).element_type.data_type == string_type.data_type) {
 					csignew.add_argument (new CCodeConstant ("G_TYPE_STRV"));
 				} else {
 					csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));

Modified: trunk/gobject/valagtypemodule.vala
==============================================================================
--- trunk/gobject/valagtypemodule.vala	(original)
+++ trunk/gobject/valagtypemodule.vala	Mon Nov  3 20:50:43 2008
@@ -29,8 +29,8 @@
 	}
 
 	public override void visit_interface (Interface iface) {
-		codegen.current_symbol = iface;
-		codegen.current_type_symbol = iface;
+		current_symbol = iface;
+		current_type_symbol = iface;
 
 		if (iface.get_cname().len () < 3) {
 			iface.error = true;
@@ -41,14 +41,14 @@
 		CCodeFragment decl_frag;
 		CCodeFragment def_frag;
 		if (iface.access != SymbolAccessibility.PRIVATE) {
-			decl_frag = codegen.header_type_declaration;
-			def_frag = codegen.header_type_definition;
+			decl_frag = header_type_declaration;
+			def_frag = header_type_definition;
 		} else {
-			decl_frag = codegen.source_type_declaration;
-			def_frag = codegen.source_type_definition;
+			decl_frag = source_type_declaration;
+			def_frag = source_type_definition;
 		}
 
-		codegen.type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
+		type_struct = new CCodeStruct ("_%s".printf (iface.get_type_cname ()));
 		
 		decl_frag.append (new CCodeNewline ());
 		var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
@@ -58,7 +58,7 @@
 		decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (iface.get_upper_case_cname (null)), macro));
 
 		macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_type_id ());
-		decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (codegen.get_type_check_function (iface)), macro));
+		decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (get_type_check_function (iface)), macro));
 
 		macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %s))".printf (iface.get_type_id (), iface.get_type_cname ());
 		decl_frag.append (new CCodeMacroReplacement ("%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), macro));
@@ -67,30 +67,30 @@
 
 		if (iface.source_reference.file.cycle == null) {
 			decl_frag.append (new CCodeTypeDefinition ("struct _%s".printf (iface.get_cname ()), new CCodeVariableDeclarator (iface.get_cname ())));
-			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (codegen.type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
+			decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator (iface.get_type_cname ())));
 		}
 		
-		codegen.type_struct.add_field ("GTypeInterface", "parent_iface");
+		type_struct.add_field ("GTypeInterface", "parent_iface");
 
 		if (iface.source_reference.comment != null) {
 			def_frag.append (new CCodeComment (iface.source_reference.comment));
 		}
-		def_frag.append (codegen.type_struct);
+		def_frag.append (type_struct);
 
 		iface.accept_children (codegen);
 
 		add_interface_base_init_function (iface);
 
-		var type_fun = new InterfaceRegisterFunction (iface, codegen);
+		var type_fun = new InterfaceRegisterFunction (iface, context);
 		type_fun.init_from_type ();
 		if (iface.access != SymbolAccessibility.PRIVATE) {
-			codegen.header_type_member_declaration.append (type_fun.get_declaration ());
+			header_type_member_declaration.append (type_fun.get_declaration ());
 		} else {
-			codegen.source_type_member_declaration.append (type_fun.get_declaration ());
+			source_type_member_declaration.append (type_fun.get_declaration ());
 		}
-		codegen.source_type_member_definition.append (type_fun.get_definition ());
+		source_type_member_definition.append (type_fun.get_definition ());
 
-		codegen.current_type_symbol = null;
+		current_type_symbol = null;
 	}
 
 	private void add_interface_base_init_function (Interface iface) {
@@ -102,7 +102,7 @@
 		
 		/* make sure not to run the initialization code twice */
 		base_init.block = new CCodeBlock ();
-		var decl = new CCodeDeclaration (codegen.bool_type.get_cname ());
+		var decl = new CCodeDeclaration (bool_type.get_cname ());
 		decl.modifiers |= CCodeModifiers.STATIC;
 		decl.add_declarator (new CCodeVariableDeclarator.with_initializer ("initialized", new CCodeConstant ("FALSE")));
 		base_init.block.add_statement (decl);
@@ -110,7 +110,7 @@
 		base_init.block.add_statement (cif);
 		init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("initialized"), new CCodeConstant ("TRUE"))));
 
-		if (iface.is_subtype_of (codegen.gobject_type)) {
+		if (iface.is_subtype_of (gobject_type)) {
 			/* create properties */
 			var props = iface.get_properties ();
 			foreach (Property prop in props) {
@@ -140,6 +140,6 @@
 
 		init_block.add_statement (head.register_dbus_info (iface));
 
-		codegen.source_type_member_definition.append (base_init);
+		source_type_member_definition.append (base_init);
 	}
 }

Modified: trunk/gobject/valainterfaceregisterfunction.vala
==============================================================================
--- trunk/gobject/valainterfaceregisterfunction.vala	(original)
+++ trunk/gobject/valainterfaceregisterfunction.vala	Mon Nov  3 20:50:43 2008
@@ -32,9 +32,9 @@
 	 */
 	public weak Interface interface_reference { get; set; }
 	
-	public InterfaceRegisterFunction (Interface iface, CCodeGenerator codegen) {
+	public InterfaceRegisterFunction (Interface iface, CodeContext context) {
 		interface_reference = iface;
-		this.codegen = codegen;
+		this.context = context;
 	}
 	
 	public override TypeSymbol get_type_declaration () {

Modified: trunk/gobject/valatyperegisterfunction.vala
==============================================================================
--- trunk/gobject/valatyperegisterfunction.vala	(original)
+++ trunk/gobject/valatyperegisterfunction.vala	Mon Nov  3 20:50:43 2008
@@ -30,13 +30,13 @@
 
 	private CCodeFragment definition_fragment = new CCodeFragment ();
 
-	public CCodeGenerator codegen { get; set; }
+	public CodeContext context { get; set; }
 
 	/**
 	 * Constructs the C function from the specified type.
 	 */
 	public void init_from_type (bool plugin = false) {
-		bool use_thread_safe = codegen.context.require_glib_version (2, 14);
+		bool use_thread_safe = context.require_glib_version (2, 14);
 
 		bool fundamental = false;
 		Class cl = get_type_declaration () as Class;



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