[vala/wip/cpp] c++: Add basic support for using C++ libraries



commit e7eb521a0c19c2183a8678d4f5e13f7f740a9bf0
Author: Luca Bruno <lucabru src gnome org>
Date:   Sat Mar 31 22:56:00 2012 +0200

    c++: Add basic support for using C++ libraries

 ccode/Makefile.am                        |    2 +
 ccode/valacppdeletestatement.vala        |   47 ++++++++++++++++++
 ccode/valacppobjectcreation.vala         |   38 ++++++++++++++
 codegen/Makefile.am                      |    1 +
 codegen/valaccodeattribute.vala          |   78 +++++++++++++++++++++++++++--
 codegen/valaccodebasemodule.vala         |   61 +++++++++++++++++++----
 codegen/valaccodememberaccessmodule.vala |   22 +++++----
 codegen/valaccodemethodcallmodule.vala   |   17 +++++--
 codegen/valacppmodule.vala               |   56 +++++++++++++++++++++
 codegen/valagerrormodule.vala            |    2 +-
 vala/valasymbol.vala                     |    4 +-
 11 files changed, 294 insertions(+), 34 deletions(-)
---
diff --git a/ccode/Makefile.am b/ccode/Makefile.am
index c63dd06..fbf81df 100644
--- a/ccode/Makefile.am
+++ b/ccode/Makefile.am
@@ -64,6 +64,8 @@ libvalaccode_la_VALASOURCES = \
 	valaccodewhilestatement.vala \
 	valaccodewriter.vala \
 	valaccodeelementaccess.vala \
+	valacppdeletestatement.vala \
+	valacppobjectcreation.vala \
 	$(NULL)
 
 libvalaccode_la_SOURCES = \
diff --git a/ccode/valacppdeletestatement.vala b/ccode/valacppdeletestatement.vala
new file mode 100644
index 0000000..ba62964
--- /dev/null
+++ b/ccode/valacppdeletestatement.vala
@@ -0,0 +1,47 @@
+/* valacppdeletestatement.vala
+ *
+ * Copyright (C) 2012  Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Luca Bruno <lucabru src gnome org>
+ */
+
+using GLib;
+
+/**
+ * Represents a delete statement in the C++ code.
+ */
+public class Vala.CppDeleteStatement : CCodeStatement {
+	/**
+	 * The optional expression to return.
+	 */
+	public CCodeExpression delete_expression { get; set; }
+
+	public CppDeleteStatement (CCodeExpression expr) {
+		delete_expression = expr;
+	}
+
+	public override void write (CCodeWriter writer) {
+		writer.write_indent (line);
+		writer.write_string ("delete ");
+
+		delete_expression.write (writer);
+
+		writer.write_string (";");
+		writer.write_newline ();
+	}
+}
diff --git a/ccode/valacppobjectcreation.vala b/ccode/valacppobjectcreation.vala
new file mode 100644
index 0000000..47e33b8
--- /dev/null
+++ b/ccode/valacppobjectcreation.vala
@@ -0,0 +1,38 @@
+/* valacppobjectcreation.vala
+ *
+ * Copyright (C) 2012  Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Luca Bruno <lucabru src gnome org>
+ */
+
+using GLib;
+
+/**
+ * Represents a 'new' expression in the C++ code.
+ */
+public class Vala.CppObjectCreation : CCodeFunctionCall {
+	public CppObjectCreation (CCodeExpression? call = null) {
+		base (call);
+	}
+
+	public override void write (CCodeWriter writer) {
+		writer.write_string ("new ");
+
+		base.write (writer);
+	}
+}
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 2535a88..dbf558f 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -27,6 +27,7 @@ libvala_la_VALASOURCES = \
 	valaccodemethodmodule.vala \
 	valaccodestructmodule.vala \
 	valaclassregisterfunction.vala \
+	valacppmodule.vala \
 	valactype.vala \
 	valadovaarraymodule.vala \
 	valadovaassignmentmodule.vala \
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index f22598b..aadc446 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -468,6 +468,36 @@ public class Vala.CCodeAttribute : AttributeCache {
 		}
 	}
 
+	public bool cpp {
+		get {
+			if (_cpp == null) {
+				if (ccode != null && ccode.has_argument ("cpp")) {
+					_cpp = ccode.get_bool ("cpp");
+				} else if (sym.parent_symbol != null) {
+					_cpp = CCodeBaseModule.get_ccode_cpp (sym.parent_symbol);
+				} else {
+					_cpp = false;
+				}
+			}
+			return _cpp;
+		}
+	}
+
+	public bool camelcase {
+		get {
+			if (_camelcase == null) {
+				if (ccode != null && ccode.has_argument ("camelcase")) {
+					_camelcase = ccode.get_bool ("camelcase");
+				} else if (sym.parent_symbol != null) {
+					_camelcase = CCodeBaseModule.get_ccode_camelcase (sym.parent_symbol);
+				} else {
+					_camelcase = false;
+				}
+			}
+			return _camelcase;
+		}
+	}
+
 	public bool array_length { get; private set; }
 	public string? array_length_type { get; private set; }
 	public bool array_null_terminated { get; private set; }
@@ -511,6 +541,8 @@ public class Vala.CCodeAttribute : AttributeCache {
 	private string _finish_real_name;
 	private string _real_name;
 	private string _delegate_target_name;
+	private bool? _cpp;
+	private bool? _camelcase;
 
 	private static int dynamic_method_id;
 
@@ -558,6 +590,9 @@ public class Vala.CCodeAttribute : AttributeCache {
 					return sym.name;
 				}
 			} else if (sym is CreationMethod) {
+				if (cpp) {
+					return CCodeBaseModule.get_ccode_name (sym.parent_symbol);
+				}
 				var m = (CreationMethod) sym;
 				string infix;
 				if (m.parent_symbol is Struct) {
@@ -582,6 +617,18 @@ public class Vala.CCodeAttribute : AttributeCache {
 					return "_vala_main";
 				} else if (sym.name.has_prefix ("_")) {
 					return "_%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (sym.parent_symbol), sym.name.substring (1));
+				} else if (cpp) {
+					string cname;
+					if (!camelcase) {
+						cname = sym.name;
+					} else {
+						cname = Symbol.lower_case_to_camel_case (sym.name, false);
+					}
+					if (m.binding == MemberBinding.INSTANCE) {
+						return cname;
+					} else {
+						return "%s%s".printf (CCodeBaseModule.get_ccode_prefix (sym.parent_symbol), cname);
+					}
 				} else {
 					return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (sym.parent_symbol), sym.name);
 				}
@@ -589,10 +636,21 @@ public class Vala.CCodeAttribute : AttributeCache {
 				var acc = (PropertyAccessor) sym;
 				var t = (TypeSymbol) acc.prop.parent_symbol;
 
-				if (acc.readable) {
-					return "%sget_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (t), acc.prop.name);
+				string cname = acc.readable ? "get" : "set";
+				if (!camelcase) {
+					cname += "_%s".printf (acc.prop.name);
 				} else {
-					return "%sset_%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (t), acc.prop.name);
+					cname += "%s".printf (Symbol.lower_case_to_camel_case (acc.prop.name, true));
+				}
+
+				if (cpp) {
+					if (acc.prop.binding == MemberBinding.INSTANCE) {
+						return cname;
+					} else {
+						return "%s%s".printf (CCodeBaseModule.get_ccode_prefix (t), cname);
+					}
+				} else {
+					return "%s%s".printf (CCodeBaseModule.get_ccode_lower_case_prefix (t), cname);
 				}
 			} else if (sym is Signal) {
 				return Symbol.camel_case_to_lower_case (sym.name);
@@ -705,8 +763,12 @@ public class Vala.CCodeAttribute : AttributeCache {
 	}
 
 	private string get_default_prefix () {
-		if (sym is ObjectTypeSymbol) {
-			return name;
+		if (sym is ObjectTypeSymbol || sym is Struct) {
+			if (cpp) {
+				return "%s::".printf (name);
+			} else {
+				return name;
+			}
 		} else if (sym is Enum || sym is ErrorDomain) {
 			return "%s_".printf (CCodeBaseModule.get_ccode_upper_case_name (sym));
 		} else if (sym is Namespace) {
@@ -715,7 +777,11 @@ public class Vala.CCodeAttribute : AttributeCache {
 				if (sym.parent_symbol != null) {
 					parent_prefix = CCodeBaseModule.get_ccode_prefix (sym.parent_symbol);
 				}
-				return "%s%s".printf (parent_prefix, sym.name);
+				if (cpp) {
+					return "%s%s::".printf (parent_prefix, sym.name);
+				} else {
+					return "%s%s".printf (parent_prefix, sym.name);
+				}
 			} else {
 				return "";
 			}
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 866e8b9..c9b7e2a 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2154,7 +2154,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		var st = variable.variable_type.data_type as Struct;
 		var creation = expr as ObjectCreationExpression;
 		if (creation != null && st != null && (!st.is_simple_type () || get_ccode_name (st) == "va_list") && !variable.variable_type.nullable &&
-		    variable.variable_type.data_type != gvalue_type && creation.get_object_initializer ().size == 0) {
+		    variable.variable_type.data_type != gvalue_type && creation.get_object_initializer ().size == 0 && !get_ccode_cpp (st)) {
 			return true;
 		} else {
 			return false;
@@ -2191,7 +2191,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
 				// try to initialize uninitialized variables
 				// initialization not necessary for variables stored in closure
-				if (rhs == null || is_simple_struct_creation (local, local.initializer)) {
+				if (rhs == null || is_simple_struct_creation (local, local.initializer) || (local.variable_type.data_type != null && get_ccode_cpp (local.variable_type.data_type))) {
 					cvar.initializer = default_value_for_type (local.variable_type, true);
 					cvar.init0 = true;
 				}
@@ -2252,6 +2252,10 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 	public TargetValue create_temp_value (DataType type, bool init, CodeNode node_reference, bool? value_owned = null) {
 		var local = new LocalVariable (type.copy (), "_tmp%d_".printf (next_temp_var_id++), null, node_reference.source_reference);
 		local.no_init = !init;
+		if (type.data_type is Struct && get_ccode_cpp (type.data_type)) {
+			// C++ structs must be initialized to zero
+			local.no_init = false;
+		}
 		if (value_owned != null) {
 			local.variable_type.value_owned = value_owned;
 		}
@@ -2878,7 +2882,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		return element_destroy_func_expression;
 	}
 
-	public CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
+	public virtual CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
 		if (context.profile == Profile.GOBJECT && (type.data_type == glist_type || type.data_type == gslist_type || type.data_type == gnode_type || type.data_type == gqueue_type)) {
 			// create wrapper function to free list elements if necessary
 
@@ -4307,15 +4311,19 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
 			var cl = expr.type_reference.data_type as Class;
 
-			if (!get_ccode_has_new_function (m)) {
+			if (!get_ccode_has_new_function (m) && !get_ccode_cpp (m)) {
 				// use construct function directly
 				creation_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
 				creation_call.add_argument (new CCodeIdentifier (get_ccode_type_id (cl)));
 			} else {
-				creation_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
+				if (st == null && get_ccode_cpp (m)) {
+					creation_call = new CppObjectCreation (new CCodeIdentifier (get_ccode_name (m)));
+				} else {
+					creation_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
+				}
 			}
 
-			if ((st != null && !st.is_simple_type ()) && !(get_ccode_instance_pos (m) < 0)) {
+			if ((st != null && !st.is_simple_type ()) && !(get_ccode_instance_pos (m) < 0) && !get_ccode_cpp (st)) {
 				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
 			} else if (st != null && get_ccode_name (st) == "va_list") {
 				creation_call.add_argument (instance);
@@ -4445,7 +4453,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 				last_pos = min_pos;
 			}
 
-			if ((st != null && !st.is_simple_type ()) && get_ccode_instance_pos (m) < 0) {
+			if ((st != null && !st.is_simple_type ()) && get_ccode_instance_pos (m) < 0 && !get_ccode_cpp (st)) {
 				// instance parameter is at the end in a struct creation method
 				creation_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, instance));
 			}
@@ -4502,7 +4510,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 			ccode.add_expression (creation_expr);
 			set_cvalue (expr, instance);
 		} else if (instance != null) {
-			if (expr.type_reference.data_type is Struct) {
+			if (expr.type_reference.data_type is Struct && !get_ccode_cpp (expr.type_reference.data_type)) {
 				ccode.add_expression (creation_expr);
 			} else {
 				ccode.add_assignment (instance, creation_expr);
@@ -4538,6 +4546,11 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 	}
 
 	public CCodeExpression? handle_struct_argument (Parameter? param, Expression arg, CCodeExpression? cexpr) {
+		if (param != null && get_byref (param)) {
+			// no need for address of expression
+			return cexpr;
+		}
+
 		DataType type;
 		if (param != null) {
 			type = param.variable_type;
@@ -4579,6 +4592,15 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 
 	public override void visit_unary_expression (UnaryExpression expr) {
 		if (expr.operator == UnaryOperator.REF || expr.operator == UnaryOperator.OUT) {
+			if (expr.formal_target_type != null) {
+				var param = expr.formal_target_type.parent_node as Parameter;
+				if (param != null && get_byref (param)) {
+					// no need for address of expression
+					expr.target_value = expr.inner.target_value;
+					return;
+				}
+			}
+
 			var glib_value = (GLibValue) expr.inner.target_value;
 
 			var ref_value = new GLibValue (glib_value.value_type);
@@ -5597,9 +5619,14 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 				   (st != null || (array_type != null && array_type.fixed_length))) {
 			// 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;
+			if (st != null && get_ccode_cpp (st)) {
+				// c++ will call the default constructor if any
+				return null;
+			} else {
+				var clist = new CCodeInitializerList ();
+				clist.append (new CCodeConstant ("0"));
+				return clist;
+			}
 		} else if ((type.data_type != null && type.data_type.is_reference_type ())
 		           || type.nullable
 		           || type is PointerType || type is DelegateType
@@ -6008,6 +6035,18 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
 		return "";
 	}
 
+	public static bool get_ccode_cpp (Symbol sym) {
+		return get_ccode_attribute(sym).cpp;
+	}
+
+	public static bool get_ccode_camelcase (Symbol sym) {
+		return get_ccode_attribute(sym).camelcase;
+	}
+
+	public static bool get_byref (Symbol sym) {
+		return sym.get_attribute ("ByRef") != null;
+	}
+
 	public CCodeConstant get_signal_canonical_constant (Signal sig, string? detail = null) {
 		var str = new StringBuilder ("\"");
 
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 09b8ad7..ccd721f 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -203,16 +203,20 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 				var ccall = new CCodeFunctionCall (new CCodeIdentifier (getter_cname));
 
 				if (prop.binding == MemberBinding.INSTANCE) {
-					if (prop.parent_symbol is Struct && !((Struct) prop.parent_symbol).is_simple_type ()) {
-						// we need to pass struct instance by reference
-						var instance = expr.inner.target_value;
-						if (!get_lvalue (instance)) {
-							instance = store_temp_value (instance, expr);
+					if (!get_ccode_cpp (prop.get_accessor)) {
+						if (prop.parent_symbol is Struct && !((Struct) prop.parent_symbol).is_simple_type ()) {
+							// we need to pass struct instance by reference
+							var instance = expr.inner.target_value;
+							if (!get_lvalue (instance)) {
+								instance = store_temp_value (instance, expr);
+							}
+							pub_inst = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance));
 						}
-						pub_inst = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance));
-					}
 
-					ccall.add_argument (pub_inst);
+						ccall.add_argument (pub_inst);
+					} else {
+						ccall.call = new CCodeMemberAccess (pub_inst, get_ccode_name (prop.get_accessor), !(prop.parent_symbol is Struct));
+					}
 				}
 
 				var temp_value = create_temp_value (prop.get_accessor.value_type, false, expr);
@@ -221,7 +225,7 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
 
 				// Property access to real struct types is handled differently
 				// The value is returned by out parameter
-				if (prop.property_type.is_real_non_null_struct_type ()) {
+				if (prop.property_type.is_real_non_null_struct_type () && !get_byref (prop)) {
 					ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ctemp));
 					ccode.add_expression (ccall);
 				} else {
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index fa3f727..fc92098 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -193,7 +193,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 			instance = get_cvalue_ (instance_value);
 
 			var st = m.parent_symbol as Struct;
-			if (st != null && !st.is_simple_type ()) {
+			if (st != null && !st.is_simple_type () && !get_ccode_cpp (st)) {
 				// we need to pass struct instance by reference
 				if (!get_lvalue (instance_value)) {
 					instance_value = store_temp_value (instance_value, expr);
@@ -201,8 +201,12 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 				instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance_value));
 			}
 
-			in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
-			out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
+			if (get_ccode_cpp (m)) {
+				ccall.call = new CCodeMemberAccess (instance, get_ccode_name (m), st == null);
+			} else {
+				in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
+				out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
+			}
 		} else if (m != null && m.binding == MemberBinding.CLASS) {
 			var cl = (Class) m.parent_symbol;
 			var cast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_upper_case_name (cl, null) + "_CLASS"));
@@ -387,7 +391,10 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 						set_cvalue (arg, get_variable_cexpression (temp_var.name));
 						arg.target_value.value_type = arg.target_type;
 
-						cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg));
+						cexpr = get_cvalue (arg);
+						if (!get_byref (param)) {
+							cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
+						}
 
 						if (get_ccode_array_length (param) && param.variable_type is ArrayType) {
 							var array_type = (ArrayType) param.variable_type;
@@ -603,7 +610,7 @@ public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 		}
 
 		// structs are returned via out parameter
-		bool return_result_via_out_param = itype.get_return_type ().is_real_non_null_struct_type ();
+		bool return_result_via_out_param = itype.get_return_type ().is_real_non_null_struct_type () && (m == null || !get_byref (m));
 
 		// pass address for the return value of non-void signals without emitter functions
 		if (itype is SignalType && !(itype.get_return_type () is VoidType)) {
diff --git a/codegen/valacppmodule.vala b/codegen/valacppmodule.vala
new file mode 100644
index 0000000..ec0b824
--- /dev/null
+++ b/codegen/valacppmodule.vala
@@ -0,0 +1,56 @@
+/* valacppmodule.vala
+ *
+ * Copyright (C) 2012  Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Luca Bruno <lucabru src gnome org>
+ */
+
+
+public class Vala.CppModule : CCodeDelegateModule {
+	public string get_ccode_wrapper_name (Symbol sym) {
+		return get_ccode_name (sym).replace (":", "_");
+	}
+
+	public override CCodeExpression? get_destroy_func_expression (DataType type, bool is_chainup = false) {
+		var cl = type.data_type as Class;
+		if (cl == null || !get_ccode_cpp (cl)) {
+			return base.get_destroy_func_expression (type, is_chainup);
+		}
+
+		string destroy_func = "_vala_cpp_%s_free".printf (get_ccode_wrapper_name (cl));
+		if (!add_wrapper (destroy_func)) {
+			// wrapper already defined
+			return new CCodeIdentifier (destroy_func);
+		}
+
+		var function = new CCodeFunction (destroy_func, "void");
+		function.modifiers = CCodeModifiers.STATIC;
+		function.add_parameter (new CCodeParameter ("self", get_ccode_name (cl)+"*"));
+
+		push_function (function);
+
+		ccode.add_statement (new CppDeleteStatement (new CCodeIdentifier ("self")));
+
+		pop_function ();
+
+		cfile.add_function_declaration (function);
+		cfile.add_function (function);
+
+		return new CCodeIdentifier (destroy_func);
+	}
+}
diff --git a/codegen/valagerrormodule.vala b/codegen/valagerrormodule.vala
index 23d11a3..3047ad4 100644
--- a/codegen/valagerrormodule.vala
+++ b/codegen/valagerrormodule.vala
@@ -23,7 +23,7 @@
 
 using GLib;
 
-public class Vala.GErrorModule : CCodeDelegateModule {
+public class Vala.GErrorModule : CppModule {
 	private int current_try_id = 0;
 	private int next_try_id = 0;
 	private bool is_in_catch = false;
diff --git a/vala/valasymbol.vala b/vala/valasymbol.vala
index cc92116..ecb076c 100644
--- a/vala/valasymbol.vala
+++ b/vala/valasymbol.vala
@@ -316,12 +316,12 @@ public abstract class Vala.Symbol : CodeNode {
 	 * @param lower_case a string in lower case
 	 * @return           the specified string converted to camel case
 	 */
-	public static string lower_case_to_camel_case (string lower_case) {
+	public static string lower_case_to_camel_case (string lower_case, bool first_uppercase = true) {
 		var result_builder = new StringBuilder ("");
 
 		weak string i = lower_case;
 
-		bool last_underscore = true;
+		bool last_underscore = first_uppercase;
 		while (i.length > 0) {
 			unichar c = i.get_char ();
 			if (c == '_') {



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