Commit 3696a4b1 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

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

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

svn path=/trunk/; revision=2151
parent 78be2505
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
2008-12-15 Jürg Billeter <j@bitron.ch>
* gobject/valaccodebasemodule.vala:
......
......@@ -35,6 +35,7 @@ libvala_la_VALASOURCES = \
valagtypemodule.vala \
valagasyncmodule.vala \
valainterfaceregisterfunction.vala \
valastructregisterfunction.vala \
valatyperegisterfunction.vala \
$(NULL)
......
......@@ -1532,9 +1532,10 @@ public class Vala.CCodeBaseModule : CCodeModule {
// 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 @@ public class Vala.CCodeBaseModule : CCodeModule {
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 @@ public class Vala.CCodeBaseModule : CCodeModule {
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))
......
......@@ -62,11 +62,93 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
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 @@ public class Vala.CCodeStructModule : CCodeBaseModule {
}
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;
......
......@@ -142,4 +142,28 @@ public class Vala.GTypeModule : GErrorModule {
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 ());
}
}
/* 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 ();
}
}
......@@ -92,11 +92,11 @@ public abstract class Vala.TypeRegisterFunction {
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 @@ public abstract class Vala.TypeRegisterFunction {
}
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 @@ public abstract class Vala.TypeRegisterFunction {
*
* @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 ();
}
......
......@@ -373,16 +373,21 @@ public class Vala.Struct : TypeSymbol {
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 @@ public class Vala.Struct : TypeSymbol {
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";
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment