vala r2151 - in trunk: . gobject vala



Author: juergbi
Date: Mon Dec 15 08:19:39 2008
New Revision: 2151
URL: http://svn.gnome.org/viewvc/vala?rev=2151&view=rev

Log:
2008-12-15  JÃrg Billeter  <j bitron ch>

	* vala/valastruct.vala:
	* gobject/Makefile.am:
	* gobject/valaccodebasemodule.vala:
	* gobject/valaccodestructmodule.vala:
	* gobject/valagtypemodule.vala:
	* gobject/valastructregisterfunction.vala:
	* gobject/valatyperegisterfunction.vala:

	Register structs as boxed types, generate dup, copy, and free
	functions, fixes bug 548864


Added:
   trunk/gobject/valastructregisterfunction.vala
Modified:
   trunk/ChangeLog
   trunk/gobject/Makefile.am
   trunk/gobject/valaccodebasemodule.vala
   trunk/gobject/valaccodestructmodule.vala
   trunk/gobject/valagtypemodule.vala
   trunk/gobject/valatyperegisterfunction.vala
   trunk/vala/valastruct.vala

Modified: trunk/gobject/Makefile.am
==============================================================================
--- trunk/gobject/Makefile.am	(original)
+++ trunk/gobject/Makefile.am	Mon Dec 15 08:19:39 2008
@@ -35,6 +35,7 @@
 	valagtypemodule.vala \
 	valagasyncmodule.vala \
 	valainterfaceregisterfunction.vala \
+	valastructregisterfunction.vala \
 	valatyperegisterfunction.vala \
 	$(NULL)
 

Modified: trunk/gobject/valaccodebasemodule.vala
==============================================================================
--- trunk/gobject/valaccodebasemodule.vala	(original)
+++ trunk/gobject/valaccodebasemodule.vala	Mon Dec 15 08:19:39 2008
@@ -1532,9 +1532,10 @@
 				// 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 = type.data_type.get_dup_function ();
+				if (dup_function == null && type.nullable) {
 					dup_function = generate_struct_dup_wrapper ((ValueType) type);
-				} else {
+				} else if (dup_function == null) {
 					dup_function = "";
 				}
 			} else {
@@ -1941,10 +1942,9 @@
 		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);
+		cfrag.append (stmt.ccodenode);
 		
-		((CodeNode) stmt).ccodenode = cfrag;
+		stmt.ccodenode = cfrag;
 	}
 
 	public void append_local_free (Symbol sym, CCodeFragment cfrag, bool stop_at_loop) {
@@ -2377,7 +2377,15 @@
 			ccomma.append_expression (copy_call);
 			ccomma.append_expression (ctemp);
 
-			return ccomma;
+			if (expression_type.data_type == gvalue_type) {
+				// g_value_init/copy must not be called for uninitialized values
+				var cisvalid = new CCodeFunctionCall (new CCodeIdentifier ("G_IS_VALUE"));
+				cisvalid.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr));
+
+				return new CCodeConditionalExpression (cisvalid, ccomma, cexpr);
+			} else {
+				return ccomma;
+			}
 		}
 
 		/* (temp = expr, temp == NULL ? NULL : ref (temp))

Modified: trunk/gobject/valaccodestructmodule.vala
==============================================================================
--- trunk/gobject/valaccodestructmodule.vala	(original)
+++ trunk/gobject/valaccodestructmodule.vala	Mon Dec 15 08:19:39 2008
@@ -62,11 +62,93 @@
 			add_struct_destroy_function (st);
 		}
 
+		add_struct_dup_function (st);
+		add_struct_free_function (st);
+
 		current_type_symbol = old_type_symbol;
 		instance_struct = old_instance_struct;
 		instance_finalize_fragment = old_instance_finalize_fragment;
 	}
 
+	void add_struct_dup_function (Struct st) {
+		var function = new CCodeFunction (st.get_dup_function (), st.get_cname () + "*");
+		if (st.access == SymbolAccessibility.PRIVATE) {
+			function.modifiers = CCodeModifiers.STATIC;
+		}
+
+		function.add_parameter (new CCodeFormalParameter ("self", "const " + st.get_cname () + "*"));
+
+		if (st.access != SymbolAccessibility.PRIVATE) {
+			header_type_member_declaration.append (function.copy ());
+		} else {
+			source_type_member_declaration.append (function.copy ());
+		}
+
+		var cblock = new CCodeBlock ();
+
+		var cdecl = new CCodeDeclaration (st.get_cname () + "*");
+		cdecl.add_declarator (new CCodeVariableDeclarator ("dup"));
+		cblock.add_statement (cdecl);
+
+		var creation_call = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
+		creation_call.add_argument (new CCodeConstant (st.get_cname ()));
+		creation_call.add_argument (new CCodeConstant ("1"));
+		cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("dup"), creation_call)));
+
+		if (st.is_disposable ()) {
+			var copy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_copy_function ()));
+			copy_call.add_argument (new CCodeIdentifier ("self"));
+			copy_call.add_argument (new CCodeIdentifier ("dup"));
+			cblock.add_statement (new CCodeExpressionStatement (copy_call));
+		} else {
+			var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+			sizeof_call.add_argument (new CCodeConstant (st.get_cname ()));
+
+			var copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+			copy_call.add_argument (new CCodeIdentifier ("dup"));
+			copy_call.add_argument (new CCodeIdentifier ("self"));
+			copy_call.add_argument (sizeof_call);
+			cblock.add_statement (new CCodeExpressionStatement (copy_call));
+		}
+
+		cblock.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("dup")));
+
+		function.block = cblock;
+
+		source_type_member_definition.append (function);
+	}
+
+	void add_struct_free_function (Struct st) {
+		var function = new CCodeFunction (st.get_free_function (), "void");
+		if (st.access == SymbolAccessibility.PRIVATE) {
+			function.modifiers = CCodeModifiers.STATIC;
+		}
+
+		function.add_parameter (new CCodeFormalParameter ("self", st.get_cname () + "*"));
+
+		if (st.access != SymbolAccessibility.PRIVATE) {
+			header_type_member_declaration.append (function.copy ());
+		} else {
+			source_type_member_declaration.append (function.copy ());
+		}
+
+		var cblock = new CCodeBlock ();
+
+		if (st.is_disposable ()) {
+			var destroy_call = new CCodeFunctionCall (new CCodeIdentifier (st.get_destroy_function ()));
+			destroy_call.add_argument (new CCodeIdentifier ("self"));
+			cblock.add_statement (new CCodeExpressionStatement (destroy_call));
+		}
+
+		var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
+		free_call.add_argument (new CCodeIdentifier ("self"));
+		cblock.add_statement (new CCodeExpressionStatement (free_call));
+
+		function.block = cblock;
+
+		source_type_member_definition.append (function);
+	}
+
 	void add_struct_copy_function (Struct st) {
 		var function = new CCodeFunction (st.get_copy_function (), "void");
 		if (st.access == SymbolAccessibility.PRIVATE) {
@@ -83,6 +165,22 @@
 		}
 
 		var cblock = new CCodeBlock ();
+		var cfrag = new CCodeFragment ();
+		cblock.add_statement (cfrag);
+
+		foreach (var f in st.get_fields ()) {
+			if (f.binding == MemberBinding.INSTANCE) {
+				CCodeExpression copy = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.name);
+				if (requires_copy (f.field_type))  {
+					copy = get_ref_cexpression (f.field_type, copy, null, f);
+				}
+				var dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), f.name);
+				cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (dest, copy)));
+			}
+		}
+
+		append_temp_decl (cfrag, temp_vars);
+		temp_vars.clear ();
 
 		function.block = cblock;
 

Modified: trunk/gobject/valagtypemodule.vala
==============================================================================
--- trunk/gobject/valagtypemodule.vala	(original)
+++ trunk/gobject/valagtypemodule.vala	Mon Dec 15 08:19:39 2008
@@ -142,4 +142,28 @@
 
 		source_type_member_definition.append (base_init);
 	}
+
+	public override void visit_struct (Struct st) {
+		base.visit_struct (st);
+
+		CCodeFragment decl_frag;
+		if (st.access != SymbolAccessibility.PRIVATE) {
+			decl_frag = header_type_declaration;
+		} else {
+			decl_frag = source_type_declaration;
+		}
+
+		decl_frag.append (new CCodeNewline ());
+		var macro = "(%s_get_type ())".printf (st.get_lower_case_cname (null));
+		decl_frag.append (new CCodeMacroReplacement (st.get_type_id (), macro));
+
+		var type_fun = new StructRegisterFunction (st, context);
+		type_fun.init_from_type (false);
+		if (st.access != SymbolAccessibility.PRIVATE) {
+			header_type_member_declaration.append (type_fun.get_declaration ());
+		} else {
+			source_type_member_declaration.append (type_fun.get_declaration ());
+		}
+		source_type_member_definition.append (type_fun.get_definition ());
+	}
 }

Added: trunk/gobject/valastructregisterfunction.vala
==============================================================================
--- (empty file)
+++ trunk/gobject/valastructregisterfunction.vala	Mon Dec 15 08:19:39 2008
@@ -0,0 +1,56 @@
+/* valastructregisterfunction.vala
+ *
+ * Copyright (C) 2008  JÃrg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	JÃrg Billeter <j bitron ch>
+ */
+
+using GLib;
+
+/**
+ * C function to register a class at runtime.
+ */
+public class Vala.StructRegisterFunction : TypeRegisterFunction {
+	/**
+	 * Specifies the struct to be registered.
+	 */
+	public weak Struct struct_reference { get; set; }
+
+	/**
+	 * Creates a new C function to register the specified class at runtime.
+	 *
+	 * @param cl a class
+	 * @return   newly created class register function
+	 */
+	public StructRegisterFunction (Struct st, CodeContext context) {
+		struct_reference = st;
+		this.context = context;
+	}
+	
+	public override TypeSymbol get_type_declaration () {
+		return struct_reference;
+	}
+
+	public override SymbolAccessibility get_accessibility () {
+		return struct_reference.access;
+	}
+
+	public override CCodeFragment get_type_interface_init_statements () {
+		return new CCodeFragment ();
+	}
+}

Modified: trunk/gobject/valatyperegisterfunction.vala
==============================================================================
--- trunk/gobject/valatyperegisterfunction.vala	(original)
+++ trunk/gobject/valatyperegisterfunction.vala	Mon Dec 15 08:19:39 2008
@@ -92,11 +92,11 @@
 		string type_value_table_decl_name = null;
 		var type_init = new CCodeBlock ();
 
-		if ( fundamental ) {
+		if (fundamental) {
 			var cgtypetabledecl = new CCodeDeclaration ("const GTypeValueTable");
 			cgtypetabledecl.modifiers = CCodeModifiers.STATIC;
 
-			cgtypetabledecl.add_declarator ( new CCodeVariableDeclarator.with_initializer ( "g_define_type_value_table", new CCodeConstant ("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf ( get_gtype_value_table_init_function_name (), get_gtype_value_table_free_function_name (), get_gtype_value_table_copy_function_name (), get_gtype_value_table_peek_pointer_function_name (), get_gtype_value_table_collect_value_function_name (), get_gtype_value_table_lcopy_value_function_name () ))));
+			cgtypetabledecl.add_declarator (new CCodeVariableDeclarator.with_initializer ( "g_define_type_value_table", new CCodeConstant ("{ %s, %s, %s, %s, \"p\", %s, \"p\", %s }".printf (get_gtype_value_table_init_function_name (), get_gtype_value_table_free_function_name (), get_gtype_value_table_copy_function_name (), get_gtype_value_table_peek_pointer_function_name (), get_gtype_value_table_collect_value_function_name (), get_gtype_value_table_lcopy_value_function_name ()))));
 			type_value_table_decl_name = "&g_define_type_value_table";
 			type_init.add_statement ( cgtypetabledecl );
 		}
@@ -105,39 +105,47 @@
 		}
 
 
-		var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
-		ctypedecl.modifiers = CCodeModifiers.STATIC;
-		ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name))));
-		type_init.add_statement (ctypedecl);
-		if (fundamental) {
-			var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo");
-			ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC;
-			ctypefundamentaldecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_fundamental_info", new CCodeConstant ("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }")));
-			type_init.add_statement (ctypefundamentaldecl);
+		if (get_type_declaration () is ObjectTypeSymbol) {
+			var ctypedecl = new CCodeDeclaration ("const GTypeInfo");
+			ctypedecl.modifiers = CCodeModifiers.STATIC;
+			ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name))));
+			type_init.add_statement (ctypedecl);
+			if (fundamental) {
+				var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo");
+				ctypefundamentaldecl.modifiers = CCodeModifiers.STATIC;
+				ctypefundamentaldecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_fundamental_info", new CCodeConstant ("{ (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }")));
+				type_init.add_statement (ctypefundamentaldecl);
+			}
 		}
 
 		type_init.add_statement (get_type_interface_init_declaration ());
 
 		CCodeFunctionCall reg_call;
-		if (fundamental) {
+		if (get_type_declaration () is Struct) {
+			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_boxed_type_register_static"));
+		} else if (fundamental) {
 			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_fundamental"));
+			reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("g_type_fundamental_next")));
 		} else if (!plugin) {
 			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_register_static"));
+			reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
 		} else {
 			reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_type_module_register_type"));
 			reg_call.add_argument (new CCodeIdentifier ("module"));
-		}
-		if (fundamental) {
-			reg_call.add_argument (new CCodeFunctionCall (new CCodeIdentifier ("g_type_fundamental_next")));
-		} else {
 			reg_call.add_argument (new CCodeIdentifier (get_parent_type_name ()));
 		}
 		reg_call.add_argument (new CCodeConstant ("\"%s\"".printf (get_type_declaration ().get_cname ())));
-		reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
-		if (fundamental) {
-			reg_call.add_argument (new CCodeIdentifier ("&g_define_type_fundamental_info"));
+		if (get_type_declaration () is Struct) {
+			var st = (Struct) get_type_declaration ();
+			reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (st.get_dup_function ()), "GBoxedCopyFunc"));
+			reg_call.add_argument (new CCodeCastExpression (new CCodeIdentifier (st.get_free_function ()), "GBoxedFreeFunc"));
+		} else {
+			reg_call.add_argument (new CCodeIdentifier ("&g_define_type_info"));
+			if (fundamental) {
+				reg_call.add_argument (new CCodeIdentifier ("&g_define_type_fundamental_info"));
+			}
+			reg_call.add_argument (new CCodeConstant (get_type_flags ()));
 		}
-		reg_call.add_argument (new CCodeConstant (get_type_flags ()));
 
 		if (use_thread_safe && !plugin) {
 			var temp_decl = new CCodeDeclaration ("GType");
@@ -197,42 +205,54 @@
 	 *
 	 * @return C struct name
 	 */
-	public abstract string get_type_struct_name ();
+	public virtual string get_type_struct_name () {
+		assert_not_reached ();
+	}
 
 	/**
 	 * Returns the name of the base_init function in C code.
 	 *
 	 * @return C function name
 	 */
-	public abstract string get_base_init_func_name ();
+	public virtual string get_base_init_func_name () {
+		assert_not_reached ();
+	}
 
 	/**
 	 * Returns the name of the class_init function in C code.
 	 *
 	 * @return C function name
 	 */
-	public abstract string get_class_init_func_name ();
+	public virtual string get_class_init_func_name () {
+		assert_not_reached ();
+	}
 
 	/**
 	 * Returns the size of the instance struct in C code.
 	 *
 	 * @return C instance struct size
 	 */
-	public abstract string get_instance_struct_size ();
+	public virtual string get_instance_struct_size () {
+		assert_not_reached ();
+	}
 
 	/**
 	 * Returns the name of the instance_init function in C code.
 	 *
 	 * @return C function name
 	 */
-	public abstract string get_instance_init_func_name ();
+	public virtual string get_instance_init_func_name () {
+		assert_not_reached ();
+	}
 
 	/**
 	 * Returns the name of the parent type in C code.
 	 *
 	 * @return C function name
 	 */
-	public abstract string get_parent_type_name ();
+	public virtual string get_parent_type_name () {
+		assert_not_reached ();
+	}
 
 
 

Modified: trunk/vala/valastruct.vala
==============================================================================
--- trunk/vala/valastruct.vala	(original)
+++ trunk/vala/valastruct.vala	Mon Dec 15 08:19:39 2008
@@ -373,16 +373,21 @@
 
 	public override string? get_type_id () {
 		if (type_id == null) {
-			foreach (DataType type in base_types) {
-				var st = type.data_type as Struct;
-				if (st != null) {
-					return st.get_type_id ();;
+			// TODO use attribute check instead
+			if (external_package) {
+				foreach (DataType type in base_types) {
+					var st = type.data_type as Struct;
+					if (st != null) {
+						return st.get_type_id ();;
+					}
+				}
+				if (is_simple_type ()) {
+					Report.error (source_reference, "The type `%s` doesn't declare a type id".printf (get_full_name ()));
+				} else {
+					return "G_TYPE_POINTER";
 				}
-			}
-			if (is_simple_type ()) {
-				Report.error (source_reference, "The type `%s` doesn't declare a type id".printf (get_full_name ()));
 			} else {
-				return "G_TYPE_POINTER";
+				type_id = get_upper_case_cname ("TYPE_");
 			}
 		}
 		return type_id;
@@ -555,6 +560,24 @@
 		return false;
 	}
 
+	public override string? get_dup_function () {
+		// TODO use attribute check instead
+		if (external_package) {
+			return null;
+		} else {
+			return get_lower_case_cprefix () + "dup";
+		}
+	}
+	
+	public override string? get_free_function () {
+		// TODO use attribute check instead
+		if (external_package) {
+			return null;
+		} else {
+			return get_lower_case_cprefix () + "free";
+		}
+	}
+
 	public string get_default_copy_function () {
 		return get_lower_case_cprefix () + "copy";
 	}



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