From: Jürg Billeter Date: Wed, 8 Apr 2009 20:18:03 +0000 (+0200) Subject: Move common code from GObjectModule to GTypeModule X-Git-Tag: 0.7.1~55 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f523e45f52792d1dd88c7fe4754b50cdebbc1bf;p=thirdparty%2Fvala.git Move common code from GObjectModule to GTypeModule --- diff --git a/gobject/valagobjectmodule.vala b/gobject/valagobjectmodule.vala index 38511ca9f..b48ffa5be 100644 --- a/gobject/valagobjectmodule.vala +++ b/gobject/valagobjectmodule.vala @@ -32,1491 +32,134 @@ internal class Vala.GObjectModule : GTypeModule { base (codegen, next); } - public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map cparam_map, Map? carg_map) { - if (!(param.parameter_type is ObjectType)) { - base.generate_parameter (param, decl_space, cparam_map, carg_map); - return; - } - - generate_type_declaration (param.parameter_type, decl_space); - - string ctypename = param.parameter_type.get_cname (); - - if (param.direction != ParameterDirection.IN) { - ctypename += "*"; - } - - param.ccodenode = new CCodeFormalParameter (param.name, ctypename); - - cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode); - if (carg_map != null) { - carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name)); - } - } + public override void visit_class (Class cl) { + base.visit_class (cl); - public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) { - if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) { + if (!cl.is_subtype_of (gobject_type)) { return; } - if (cl.base_class != null) { - // base class declaration - // necessary for ref and unref function declarations - generate_class_declaration (cl.base_class, decl_space); + if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { + add_get_property_function (cl); } - - bool is_gtypeinstance = !cl.is_compact; - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - - if (is_gtypeinstance) { - decl_space.add_type_declaration (new CCodeNewline ()); - var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); - decl_space.add_type_declaration (new CCodeMacroReplacement (cl.get_type_id (), macro)); - - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ()); - decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro)); - - macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ()); - decl_space.add_type_declaration (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_space.add_type_declaration (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_space.add_type_declaration (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_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro)); - decl_space.add_type_declaration (new CCodeNewline ()); - } - - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ()))); - - if (is_fundamental) { - var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer"); - var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void"); - if (cl.access == SymbolAccessibility.PRIVATE) { - ref_fun.modifiers = CCodeModifiers.STATIC; - unref_fun.modifiers = CCodeModifiers.STATIC; - } - - ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); - unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); - - decl_space.add_type_member_declaration (ref_fun.copy ()); - decl_space.add_type_member_declaration (unref_fun.copy ()); - - // GParamSpec and GValue functions - var function_name = cl.get_lower_case_cname ("param_spec_"); - - var function = new CCodeFunction (function_name, "GParamSpec*"); - function.add_parameter (new CCodeFormalParameter ("name", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("object_type", "GType")); - function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags")); - - cl.set_param_spec_function (function_name); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - decl_space.add_type_member_declaration (function); - - function = new CCodeFunction (cl.get_set_value_function (), "void"); - function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); - function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - decl_space.add_type_member_declaration (function); - - function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); - function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - decl_space.add_type_member_declaration (function); - } - - if (is_gtypeinstance) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ())))); - - var type_fun = new ClassRegisterFunction (cl, context); - type_fun.init_from_type (in_plugin); - decl_space.add_type_member_declaration (type_fun.get_declaration ()); + if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) { + add_set_property_function (cl); } } - public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) { - if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) { + public override void generate_class_init (Class cl, CCodeBlock init_block) { + if (!cl.is_subtype_of (gobject_type)) { return; } - if (cl.base_class != null) { - // base class declaration - generate_class_struct_declaration (cl.base_class, decl_space); - } - foreach (DataType base_type in cl.get_base_types ()) { - var iface = base_type.data_type as Interface; - if (iface != null) { - generate_interface_declaration (iface, decl_space); - } - } - - generate_class_declaration (cl, decl_space); - - bool is_gtypeinstance = !cl.is_compact; - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - - var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); - var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); - - if (cl.base_class != null) { - instance_struct.add_field (cl.base_class.get_cname (), "parent_instance"); - } else if (is_fundamental) { - 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 - instance_struct.add_field ("int", "dummy"); - } - - if (is_gtypeinstance) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ())))); - - instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); - if (is_fundamental) { - type_struct.add_field ("GTypeClass", "parent_class"); - } else { - type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class"); - } - - if (is_fundamental) { - type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ())); - } - } - - foreach (Method m in cl.get_methods ()) { - generate_virtual_method_declaration (m, decl_space, type_struct); - } - - foreach (Property prop in cl.get_properties ()) { - if (!prop.is_abstract && !prop.is_virtual) { - continue; - } - generate_type_declaration (prop.property_type, decl_space); - - var t = (ObjectTypeSymbol) prop.parent_symbol; - - bool returns_real_struct = prop.property_type.is_real_struct_type (); - - var this_type = new ObjectType (t); - var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ()); - CCodeFormalParameter cvalueparam; - if (returns_real_struct) { - cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*"); - } else { - cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ()); - } - - if (prop.get_accessor != null) { - var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name)); - vdeclarator.add_parameter (cselfparam); - string creturn_type; - if (returns_real_struct) { - vdeclarator.add_parameter (cvalueparam); - creturn_type = "void"; - } else { - creturn_type = prop.property_type.get_cname (); - } - var vdecl = new CCodeDeclaration (creturn_type); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - if (prop.set_accessor != null) { - var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name)); - vdeclarator.add_parameter (cselfparam); - vdeclarator.add_parameter (cvalueparam); - var vdecl = new CCodeDeclaration ("void"); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - } - - foreach (Field f in cl.get_fields ()) { - string field_ctype = f.field_type.get_cname (); - if (f.is_volatile) { - field_ctype = "volatile " + field_ctype; - } - - if (f.binding == MemberBinding.INSTANCE && f.access != SymbolAccessibility.PRIVATE) { - generate_type_declaration (f.field_type, decl_space); - - instance_struct.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; - var len_type = int_type.copy (); - - for (int dim = 1; dim <= array_type.rank; dim++) { - instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim)); - } - - if (array_type.rank == 1 && f.is_internal_symbol ()) { - instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name)); - } - } 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 - instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name)); - } - } - } else if (f.binding == MemberBinding.CLASS && f.access != SymbolAccessibility.PRIVATE) { - type_struct.add_field (field_ctype, f.get_cname ()); - } - } - - if (cl.source_reference.comment != null) { - decl_space.add_type_definition (new CCodeComment (cl.source_reference.comment)); - } - decl_space.add_type_definition (instance_struct); - - if (is_gtypeinstance) { - decl_space.add_type_definition (type_struct); - } - } - - public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) { - if (!m.is_abstract && !m.is_virtual) { - return; - } - - // add vfunc field to the type struct - var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name); - var cparam_map = new HashMap (direct_hash, direct_equal); - - generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator); - - var vdecl = new CCodeDeclaration (m.return_type.get_cname ()); - vdecl.add_declarator (vdeclarator); - type_struct.add_declaration (vdecl); - } - - void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) { - if (decl_space.add_symbol_declaration (cl, cl.get_cname () + "Private")) { - return; - } - - bool is_gtypeinstance = !cl.is_compact; - - var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); - var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ())); - - if (is_gtypeinstance) { - /* create type, dup_func, and destroy_func fields for generic types */ - foreach (TypeParameter type_param in cl.get_type_parameters ()) { - string func_name; - - func_name = "%s_type".printf (type_param.name.down ()); - instance_priv_struct.add_field ("GType", func_name); - - func_name = "%s_dup_func".printf (type_param.name.down ()); - instance_priv_struct.add_field ("GBoxedCopyFunc", func_name); - - func_name = "%s_destroy_func".printf (type_param.name.down ()); - instance_priv_struct.add_field ("GDestroyNotify", func_name); - } - } - - foreach (Field f in cl.get_fields ()) { - string field_ctype = f.field_type.get_cname (); - if (f.is_volatile) { - field_ctype = "volatile " + field_ctype; - } - - if (f.binding == MemberBinding.INSTANCE && f.access == SymbolAccessibility.PRIVATE) { - generate_type_declaration (f.field_type, decl_space); - - instance_priv_struct.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; - var len_type = int_type.copy (); - - for (int dim = 1; dim <= array_type.rank; dim++) { - instance_priv_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim)); - } - - if (array_type.rank == 1 && f.is_internal_symbol ()) { - instance_priv_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name)); - } - } 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 - instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name)); - } - } - - if (f.get_lock_used ()) { - // add field for mutex - instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f)); - } - } else if (f.binding == MemberBinding.CLASS && f.access == SymbolAccessibility.PRIVATE) { - type_priv_struct.add_field (field_ctype, f.get_cname ()); - } - } - - if (is_gtypeinstance) { - if (cl.has_class_private_fields) { - decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ())))); - var cdecl = new CCodeDeclaration ("GQuark"); - cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0"))); - cdecl.modifiers = CCodeModifiers.STATIC; - decl_space.add_type_declaration (cdecl); - } - - /* 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) { - decl_space.add_type_definition (instance_priv_struct); - var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ()); - decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); - } - - if (cl.has_class_private_fields) { - decl_space.add_type_member_declaration (type_priv_struct); - - var macro = "((%sClassPrivate *) g_type_get_qdata (type, _vala_%s_class_private_quark))".printf (cl.get_cname(), cl.get_lower_case_cname ()); - decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(type)".printf (cl.get_upper_case_cname (null)), macro)); - } - decl_space.add_type_member_declaration (prop_enum); - } else { - var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); - - decl_space.add_type_member_declaration (function); - } - } - - public override void visit_class (Class cl) { - var old_symbol = current_symbol; - var old_type_symbol = current_type_symbol; - var old_class = current_class; - var old_param_spec_struct = param_spec_struct; - var old_prop_enum = prop_enum; - var old_class_init_fragment = class_init_fragment; - var old_base_init_fragment = base_init_fragment; - var old_class_finalize_fragment = class_finalize_fragment; - var old_base_finalize_fragment = base_finalize_fragment; - var old_instance_init_fragment = instance_init_fragment; - var old_instance_finalize_fragment = instance_finalize_fragment; - current_symbol = cl; - current_type_symbol = cl; - current_class = cl; - - bool is_gtypeinstance = !cl.is_compact; - bool is_gobject = cl.is_subtype_of (gobject_type); - bool is_fundamental = is_gtypeinstance && cl.base_class == null; - - if (cl.get_cname().len () < 3) { - cl.error = true; - Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ())); - return; - } - - prop_enum = new CCodeEnum (); - prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)))); - class_init_fragment = new CCodeFragment (); - base_init_fragment = new CCodeFragment (); - class_finalize_fragment = new CCodeFragment (); - base_finalize_fragment = new CCodeFragment (); - instance_init_fragment = new CCodeFragment (); - instance_finalize_fragment = new CCodeFragment (); - - - generate_class_struct_declaration (cl, source_declarations); - generate_class_private_declaration (cl, source_declarations); - - if (!cl.is_internal_symbol ()) { - generate_class_struct_declaration (cl, header_declarations); - } - generate_class_struct_declaration (cl, internal_header_declarations); - - cl.accept_children (codegen); - - if (is_gtypeinstance) { - if (is_fundamental) { - param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)); - param_spec_struct.add_field ("GParamSpec", "parent_instance"); - source_declarations.add_type_definition (param_spec_struct); - - source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)))); - - - gvaluecollector_h_needed = true; - - add_type_value_table_init_function (cl); - add_type_value_table_free_function (cl); - add_type_value_table_copy_function (cl); - add_type_value_table_peek_pointer_function (cl); - add_type_value_table_collect_value_function (cl); - add_type_value_table_lcopy_value_function (cl); - add_g_param_spec_type_function (cl); - add_g_value_get_function (cl); - add_g_value_set_function (cl); - - var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); - instance_init_fragment.append (new CCodeExpressionStatement (ref_count)); - } else if (is_gobject) { - if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { - add_get_property_function (cl); - } - if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) { - add_set_property_function (cl); - } - } - - - if (cl.class_constructor != null || cl.has_class_private_fields) { - add_base_init_function (cl); - } - add_class_init_function (cl); - - if (cl.class_destructor != null || cl.has_class_private_fields) { - add_base_finalize_function (cl); - } - - if (cl.static_destructor != null) { - add_class_finalize_function (cl); - } - - foreach (DataType base_type in cl.get_base_types ()) { - if (base_type.data_type is Interface) { - add_interface_init_function (cl, (Interface) base_type.data_type); - } - } - - add_instance_init_function (cl); - - if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) { - add_finalize_function (cl); - } - - var type_fun = new ClassRegisterFunction (cl, context); - type_fun.init_from_type (in_plugin); - source_type_member_definition.append (type_fun.get_definition ()); - - 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 (module_init_param_name)); - module_init_fragment.append (new CCodeExpressionStatement (register_call)); - } - - if (is_fundamental) { - var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer"); - var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void"); - if (cl.access == SymbolAccessibility.PRIVATE) { - ref_fun.modifiers = CCodeModifiers.STATIC; - unref_fun.modifiers = CCodeModifiers.STATIC; - } - - ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); - unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); - - var ref_block = new CCodeBlock (); - var unref_block = new CCodeBlock (); - - var cdecl = new CCodeDeclaration (cl.get_cname () + "*"); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance"))); - ref_block.add_statement (cdecl); - unref_block.add_statement (cdecl); - - var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); - ref_block.add_statement (new CCodeExpressionStatement (ccall)); - - ref_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("instance"))); - - var destroy_block = new CCodeBlock (); - var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); - get_class.add_argument (new CCodeIdentifier ("self")); - - // finalize class - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); - ccast.add_argument (new CCodeIdentifier ("self")); - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); - ccall.add_argument (new CCodeIdentifier ("self")); - destroy_block.add_statement (new CCodeExpressionStatement (ccall)); - - // free type instance - var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance")); - free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *")); - destroy_block.add_statement (new CCodeExpressionStatement (free)); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test")); - ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); - unref_block.add_statement (new CCodeIfStatement (ccall, destroy_block)); - - ref_fun.block = ref_block; - unref_fun.block = unref_block; - - source_type_member_definition.append (ref_fun); - source_type_member_definition.append (unref_fun); - } - } else { - add_instance_init_function (cl); - - var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); - - var cblock = new CCodeBlock (); - - cblock.add_statement (instance_finalize_fragment); - - if (cl.destructor != null) { - cblock.add_statement (cl.destructor.ccodenode); - } - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); - ccall.add_argument (new CCodeIdentifier ("self")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); - - function.block = cblock; - - source_type_member_definition.append (function); - } - - current_symbol = old_symbol; - current_type_symbol = old_type_symbol; - current_class = old_class; - param_spec_struct = old_param_spec_struct; - prop_enum = old_prop_enum; - class_init_fragment = old_class_init_fragment; - base_init_fragment = old_base_init_fragment; - class_finalize_fragment = old_class_finalize_fragment; - base_finalize_fragment = old_base_finalize_fragment; - instance_init_fragment = old_instance_init_fragment; - instance_finalize_fragment = old_instance_finalize_fragment; - } - - private void add_type_value_table_init_function (Class cl) { - var function = new CCodeFunction ("%s_init".printf (cl.get_lower_case_cname ("value_")), "void"); - function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - 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))); - source_type_member_definition.append (function); - } - - private void add_type_value_table_free_function (Class cl) { - var function = new CCodeFunction ("%s_free_value".printf (cl.get_lower_case_cname ("value_")), "void"); - function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - function.block = init_block; - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "unref")); - ccall.add_argument ( vpointer ); - - var ifbody = new CCodeBlock (); - ifbody.add_statement ( new CCodeExpressionStatement(ccall) ); - - init_block.add_statement(new CCodeIfStatement (vpointer, ifbody)); - source_type_member_definition.append (function); - } - - private void add_type_value_table_copy_function (Class cl) { - var function = new CCodeFunction ("%s_copy_value".printf (cl.get_lower_case_cname ("value_")), "void"); - function.add_parameter (new CCodeFormalParameter ("src_value", "const GValue*")); - function.add_parameter (new CCodeFormalParameter ("dest_value", "GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - function.block = init_block; - - var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer"); - var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"),"v_pointer"); - - var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "ref")); - ref_ccall.add_argument ( src_vpointer ); - - var true_stmt = new CCodeBlock (); - true_stmt.add_statement(new CCodeExpressionStatement(new CCodeAssignment (dest_vpointer, ref_ccall, CCodeAssignmentOperator.SIMPLE))); - - var false_stmt = new CCodeBlock (); - false_stmt.add_statement (new CCodeExpressionStatement( new CCodeAssignment (dest_vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); - - var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt); - init_block.add_statement (if_statement); - - source_type_member_definition.append (function); - } - - private void add_type_value_table_peek_pointer_function (Class cl) { - var function = new CCodeFunction ("%s_peek_pointer".printf (cl.get_lower_case_cname ("value_")), "gpointer"); - function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); - function.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - function.block = init_block; - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - var ret = new CCodeReturnStatement ( vpointer ); - init_block.add_statement (ret); - - source_type_member_definition.append (function); - } - - private void add_type_value_table_lcopy_value_function ( Class cl ) { - var function = new CCodeFunction ("%s_lcopy_value".printf (cl.get_lower_case_cname ("value_")), "gchar*"); - function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); - function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); - function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); - function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); - function.modifiers = CCodeModifiers.STATIC; - - var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); - var object_p_ptr = new CCodeIdentifier ("*object_p"); - var null_ = new CCodeConstant ("NULL"); - - var init_block = new CCodeBlock (); - - var ctypedecl = new CCodeDeclaration (cl.get_cname () + "**"); - ctypedecl.add_declarator (new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"),"v_pointer"))); - init_block.add_statement (ctypedecl); - - var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); - value_type_name_fct.add_argument (new CCodeConstant ("value")); - - var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p")); - function.block = init_block; - var assert_true = new CCodeBlock (); - var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf")); - assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\"")); - assert_printf.add_argument (value_type_name_fct); - assert_true.add_statement (new CCodeReturnStatement (assert_printf)); - var if_assert = new CCodeIfStatement (assert_condition, assert_true); - init_block.add_statement (if_assert); - - var main_else_true = new CCodeBlock (); - var main_else_if_true = new CCodeBlock (); - var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS")); - var main_else_if = new CCodeIfStatement (main_else_if_condition, main_else_if_true, main_else_true); - - var main_true = new CCodeBlock (); - var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer); - var if_main = new CCodeIfStatement (main_condition, main_true, main_else_if); - init_block.add_statement (if_main); - - var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function())); - ref_fct.add_argument (vpointer); - - main_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, null_, CCodeAssignmentOperator.SIMPLE))); - main_else_if_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, vpointer, CCodeAssignmentOperator.SIMPLE))); - main_else_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE))); - - init_block.add_statement (new CCodeReturnStatement (null_)); - source_type_member_definition.append (function); - } - - private void add_type_value_table_collect_value_function (Class cl) { - var function = new CCodeFunction ("%s_collect_value".printf (cl.get_lower_case_cname ("value_")), "gchar*"); - function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); - function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); - function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); - function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); - function.modifiers = CCodeModifiers.STATIC; - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - - var init_block = new CCodeBlock (); - function.block = init_block; - - var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer"); - - var true_stmt = new CCodeBlock (); - var false_stmt = new CCodeBlock (); - var if_statement = new CCodeIfStatement (collect_vpointer, true_stmt, false_stmt); - init_block.add_statement (if_statement); - - var obj_identifier = new CCodeIdentifier ("object"); - - var ctypedecl = new CCodeDeclaration (cl.get_cname () + "*"); - ctypedecl.add_declarator (new CCodeVariableDeclarator ("object", collect_vpointer)); - true_stmt.add_statement (ctypedecl); - - var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class"); - var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL")); - var sub_true_stmt = new CCodeBlock (); - var sub_false_stmt = new CCodeBlock (); - - var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); - var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - type_check.add_argument (new CCodeIdentifier ("object")); - reg_call.add_argument (type_check); - - var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); - type_name_fct.add_argument (type_check); - - var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - stored_type.add_argument (new CCodeIdentifier ("value")); - reg_call.add_argument (stored_type); - - var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); - value_type_name_fct.add_argument (new CCodeConstant ("value")); - - var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\"")); - true_return.add_argument (value_type_name_fct); - true_return.add_argument (new CCodeConstant ("\"'\"")); - true_return.add_argument (new CCodeConstant ("NULL")); - sub_true_stmt.add_statement (new CCodeReturnStatement (true_return)); - - var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); - false_return.add_argument (new CCodeConstant ("\"invalid object type `\"")); - false_return.add_argument (type_name_fct); - false_return.add_argument (new CCodeConstant ("\"' for value type `\"")); - false_return.add_argument (value_type_name_fct); - false_return.add_argument (new CCodeConstant ("\"'\"")); - false_return.add_argument (new CCodeConstant ("NULL")); - sub_false_stmt.add_statement (new CCodeReturnStatement (false_return)); - - var sub_else_if_statement = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call), sub_false_stmt ); - sub_else_if_statement.else_if = true; - var sub_if_statement = new CCodeIfStatement (sub_condition, sub_true_stmt, sub_else_if_statement); - true_stmt.add_statement (sub_if_statement); - - var ref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ())); - ref_call.add_argument (new CCodeIdentifier ("object")); - - var true_assignment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, ref_call, CCodeAssignmentOperator.SIMPLE)); - true_stmt.add_statement (true_assignment); - - var else_assigment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)); - false_stmt.add_statement (else_assigment); - - init_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); - source_type_member_definition.append (function); - } - - private void add_g_param_spec_type_function (Class cl) { - var function_name = cl.get_lower_case_cname ("param_spec_"); - - var function = new CCodeFunction (function_name, "GParamSpec*"); - function.add_parameter (new CCodeFormalParameter ("name", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*")); - function.add_parameter (new CCodeFormalParameter ("object_type", "GType")); - function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags")); - - cl.set_param_spec_function ( function_name ); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - var init_block = new CCodeBlock (); - function.block = init_block; - - var ctypedecl = new CCodeDeclaration ("%sParamSpec%s*".printf (cl.parent_symbol.get_cprefix (), cl.name)); - ctypedecl.add_declarator ( new CCodeVariableDeclarator ("spec")); - init_block.add_statement (ctypedecl); - - var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a")); - subccall.add_argument (new CCodeIdentifier ("object_type")); - subccall.add_argument (new CCodeIdentifier ( cl.get_type_id() )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); - ccall.add_argument (subccall); - ccall.add_argument (new CCodeIdentifier ("NULL")); - init_block.add_statement (new CCodeExpressionStatement (ccall)); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal")); - ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" )); - ccall.add_argument (new CCodeIdentifier ("name")); - ccall.add_argument (new CCodeIdentifier ("nick")); - ccall.add_argument (new CCodeIdentifier ("blurb")); - ccall.add_argument (new CCodeIdentifier ("flags")); - - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("spec"), ccall, CCodeAssignmentOperator.SIMPLE ))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC")); - ccall.add_argument (new CCodeIdentifier ("spec")); - - 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)); - source_type_member_definition.append (function); - } - - private void add_g_value_set_function (Class cl) { - var function = new CCodeFunction (cl.get_set_value_function (), "void"); - function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); - function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - - var init_block = new CCodeBlock (); - function.block = init_block; - - var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*"); - ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old")); - init_block.add_statement (ctypedecl); - - var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - init_block.add_statement (new CCodeExpressionStatement (ccall)); - - init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE))); - - var true_stmt = new CCodeBlock (); - var false_stmt = new CCodeBlock (); - var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt); - init_block.add_statement (if_statement); - - - ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecheck); - true_stmt.add_statement (new CCodeExpressionStatement (ccall)); - - var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); - ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); - - var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); - ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); - - var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); - ccall_typecompatible.add_argument (ccall_typefrominstance); - ccall_typecompatible.add_argument (ccall_gvaluetype); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); - ccall.add_argument (ccall_typecompatible); - true_stmt.add_statement (new CCodeExpressionStatement (ccall)); - - true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ())); - ccall.add_argument (vpointer); - true_stmt.add_statement (new CCodeExpressionStatement (ccall)); - - false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); - - true_stmt = new CCodeBlock (); - if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt); - init_block.add_statement (if_statement); - - ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ())); - ccall.add_argument (new CCodeIdentifier ("old")); - true_stmt.add_statement (new CCodeExpressionStatement (ccall)); - source_type_member_definition.append (function); - } - - private void add_g_value_get_function (Class cl) { - var function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); - function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); - - if (cl.access == SymbolAccessibility.PRIVATE) { - function.modifiers = CCodeModifiers.STATIC; - } - - var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); - - var init_block = new CCodeBlock (); - function.block = init_block; - - var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); - ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); - ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); - ccall.add_argument (ccall_typecheck); - ccall.add_argument (new CCodeIdentifier ( "NULL" )); - init_block.add_statement (new CCodeExpressionStatement (ccall)); - - init_block.add_statement (new CCodeReturnStatement ( vpointer )); - source_type_member_definition.append (function); - } - - private void add_base_init_function (Class cl) { - 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; - - var init_block = new CCodeBlock (); - base_init.block = init_block; - - if (cl.has_class_private_fields) { - var block = new CCodeBlock (); - var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); - block.add_statement (cdecl); - cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("parent_priv", new CCodeConstant ("NULL"))); - block.add_statement (cdecl); - cdecl = new CCodeDeclaration ("GType"); - cdecl.add_declarator (new CCodeVariableDeclarator ("parent_type")); - block.add_statement (cdecl); - - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_parent")); - var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); - ccall2.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (ccall2); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall))); - - var iftrue = new CCodeBlock (); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeIdentifier ("parent_type")); - iftrue.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_priv"), ccall))); - block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue)); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); - ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf(cl.get_cname()))); - - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); - - source_declarations.add_include ("string.h"); - - iftrue = new CCodeBlock (); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); - ccall.add_argument (new CCodeIdentifier ("priv")); - ccall.add_argument (new CCodeIdentifier ("parent_priv")); - ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname()))); - iftrue.add_statement (new CCodeExpressionStatement (ccall)); - - block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue)); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); - ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); - ccall2.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (ccall2); - ccall.add_argument (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()))); - ccall.add_argument (new CCodeIdentifier ("priv")); - block.add_statement (new CCodeExpressionStatement (ccall)); - - init_block.add_statement (block); - - block = new CCodeBlock (); - cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); - block.add_statement (cdecl); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); - ccall2.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (ccall2); - block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); - ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ()))); - ccall.add_argument (new CCodeIdentifier ("priv")); - block.add_statement (new CCodeExpressionStatement (ccall)); - base_finalize_fragment.append (block); - } - - init_block.add_statement (base_init_fragment); - - source_type_member_definition.append (base_init); - } - - private void add_class_init_function (Class cl) { - var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void"); - class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); - class_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - class_init.block = init_block; - - CCodeFunctionCall ccall; - - /* save pointer to parent class */ - var parent_decl = new CCodeDeclaration ("gpointer"); - var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (cl.get_lower_case_cname (null))); - parent_var_decl.initializer = new CCodeConstant ("NULL"); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - source_declarations.add_type_member_declaration (parent_decl); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); + /* set property handlers */ + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); 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 (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) { - fundamental_class = fundamental_class.base_class; - } - - ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeIdentifier ("klass")); - var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize")); - init_block.add_statement (new CCodeExpressionStatement (finalize_assignment)); - } - - /* add struct for private fields */ - if (cl.has_private_fields || cl.get_type_parameters ().size > 0) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private")); - ccall.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ()))); - init_block.add_statement (new CCodeExpressionStatement (ccall)); + if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null)))))); } - - if (cl.is_subtype_of (gobject_type)) { - /* set property handlers */ - ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccall.add_argument (new CCodeIdentifier ("klass")); - if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "get_property"), new CCodeIdentifier ("%s_get_property".printf (cl.get_lower_case_cname (null)))))); - } - if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) { - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null)))))); - } - - /* set constructor */ - if (cl.constructor != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null)))))); - } - - /* set finalize function */ - if (cl.get_fields ().size > 0 || cl.destructor != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); - ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null)))))); - } + if (class_has_writable_properties (cl) || cl.get_type_parameters ().size > 0) { + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "set_property"), new CCodeIdentifier ("%s_set_property".printf (cl.get_lower_case_cname (null)))))); } - - /* connect overridden methods */ - foreach (Method m in cl.get_methods ()) { - if (m.base_method == null) { - continue; - } - var base_type = m.base_method.parent_symbol; - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); + + /* set constructor */ + if (cl.constructor != null) { + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccast.add_argument (new CCodeIdentifier ("klass")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ())))); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "constructor"), new CCodeIdentifier ("%s_constructor".printf (cl.get_lower_case_cname (null)))))); } - /* connect overridden properties */ - foreach (Property prop in cl.get_properties ()) { - if (prop.base_property == null) { - continue; - } - var base_type = prop.base_property.parent_symbol; - - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); + /* set finalize function */ + if (cl.get_fields ().size > 0 || cl.destructor != null) { + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT_CLASS")); ccast.add_argument (new CCodeIdentifier ("klass")); - - if (prop.get_accessor != null) { - string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } - if (prop.set_accessor != null) { - string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } - } - - /* initialize class fields */ - var fields = cl.get_fields (); - foreach (Field field in fields) { - if (field.binding != MemberBinding.CLASS || field.initializer == null) { - continue; - } - - CCodeExpression left; - - if (field.access == SymbolAccessibility.PRIVATE) { - ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ()))); - var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); - ccall2.add_argument (new CCodeIdentifier ("klass")); - ccall.add_argument (ccall2); - left = new CCodeMemberAccess (ccall, field.get_cname (), true); - } else { - left = new CCodeMemberAccess (new CCodeIdentifier ("klass"), field.get_cname (), true); - } - CCodeExpression right = (CCodeExpression) field.initializer.ccodenode; - CCodeAssignment assign = new CCodeAssignment (left, right); - init_block.add_statement (new CCodeExpressionStatement (assign)); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "finalize"), new CCodeIdentifier ("%s_finalize".printf (cl.get_lower_case_cname (null)))))); } - 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; - CCodeConstant func_name_constant; - CCodeFunctionCall cinst, cspec; - - func_name = "%s_type".printf (type_param.name.down ()); - func_name_constant = new CCodeConstant ("\"%s-type\"".printf (type_param.name.down ())); - enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_gtype")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"type\"")); - cspec.add_argument (new CCodeConstant ("\"type\"")); - cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - - - func_name = "%s_dup_func".printf (type_param.name.down ()); - func_name_constant = new CCodeConstant ("\"%s-dup-func\"".printf (type_param.name.down ())); - enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"dup func\"")); - cspec.add_argument (new CCodeConstant ("\"dup func\"")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - - - func_name = "%s_destroy_func".printf (type_param.name.down ()); - func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ())); - enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); - cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (enum_value)); - cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); - cspec.add_argument (func_name_constant); - cspec.add_argument (new CCodeConstant ("\"destroy func\"")); - cspec.add_argument (new CCodeConstant ("\"destroy func\"")); - cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); - cinst.add_argument (cspec); - init_block.add_statement (new CCodeExpressionStatement (cinst)); - prop_enum.add_value (new CCodeEnumValue (enum_value)); - } + /* 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; + CCodeConstant func_name_constant; + CCodeFunctionCall cinst, cspec; - /* create properties */ - var props = cl.get_properties (); - foreach (Property prop in props) { - if (prop.access == SymbolAccessibility.PRIVATE) { - // don't register private properties - continue; - } - - var st = prop.property_type.data_type as Struct; - if (st != null && !st.has_type_id) { - continue; - } - - if (prop.overrides || prop.base_interface_property != null) { - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); - cinst.add_argument (prop.get_canonical_cconstant ()); - - init_block.add_statement (new CCodeExpressionStatement (cinst)); - } else { - var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); - cinst.add_argument (ccall); - cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); - cinst.add_argument (head.get_param_spec (prop)); - - init_block.add_statement (new CCodeExpressionStatement (cinst)); - } - } - } + func_name = "%s_type".printf (type_param.name.down ()); + func_name_constant = new CCodeConstant ("\"%s-type\"".printf (type_param.name.down ())); + enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); + cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (enum_value)); + cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_gtype")); + cspec.add_argument (func_name_constant); + cspec.add_argument (new CCodeConstant ("\"type\"")); + cspec.add_argument (new CCodeConstant ("\"type\"")); + cspec.add_argument (new CCodeIdentifier ("G_TYPE_NONE")); + cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); + cinst.add_argument (cspec); + init_block.add_statement (new CCodeExpressionStatement (cinst)); + prop_enum.add_value (new CCodeEnumValue (enum_value)); - if (!cl.is_compact) { - /* create signals */ - foreach (Signal sig in cl.get_signals ()) { - init_block.add_statement (new CCodeExpressionStatement (head.get_signal_creation (sig, cl))); - } - } - init_block.add_statement (head.register_dbus_info (cl)); - init_block.add_statement (class_init_fragment); + func_name = "%s_dup_func".printf (type_param.name.down ()); + func_name_constant = new CCodeConstant ("\"%s-dup-func\"".printf (type_param.name.down ())); + enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); + cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (enum_value)); + cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); + cspec.add_argument (func_name_constant); + cspec.add_argument (new CCodeConstant ("\"dup func\"")); + cspec.add_argument (new CCodeConstant ("\"dup func\"")); + cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); + cinst.add_argument (cspec); + init_block.add_statement (new CCodeExpressionStatement (cinst)); + prop_enum.add_value (new CCodeEnumValue (enum_value)); - source_type_member_definition.append (class_init); - } - - private void add_interface_init_function (Class cl, Interface iface) { - var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void"); - iface_init.add_parameter (new CCodeFormalParameter ("iface", "%s *".printf (iface.get_type_cname ()))); - iface_init.modifiers = CCodeModifiers.STATIC; - - var init_block = new CCodeBlock (); - iface_init.block = init_block; - - CCodeFunctionCall ccall; - - /* save pointer to parent vtable */ - string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)); - var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*"); - var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var); - parent_var_decl.initializer = new CCodeConstant ("NULL"); - parent_decl.add_declarator (parent_var_decl); - parent_decl.modifiers = CCodeModifiers.STATIC; - source_declarations.add_type_member_declaration (parent_decl); - ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent")); - ccall.add_argument (new CCodeIdentifier ("iface")); - var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall); - init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); - - foreach (Method m in cl.get_methods ()) { - if (m.base_interface_method == null) { - continue; - } - var base_type = m.base_interface_method.parent_symbol; - if (base_type != iface) { + func_name = "%s_destroy_func".printf (type_param.name.down ()); + func_name_constant = new CCodeConstant ("\"%s-destroy-func\"".printf (type_param.name.down ())); + enum_value = "%s_%s".printf (cl.get_lower_case_cname (null), func_name).up (); + cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (enum_value)); + cspec = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_pointer")); + cspec.add_argument (func_name_constant); + cspec.add_argument (new CCodeConstant ("\"destroy func\"")); + cspec.add_argument (new CCodeConstant ("\"destroy func\"")); + cspec.add_argument (new CCodeConstant ("G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY")); + cinst.add_argument (cspec); + init_block.add_statement (new CCodeExpressionStatement (cinst)); + prop_enum.add_value (new CCodeEnumValue (enum_value)); + } + + /* create properties */ + var props = cl.get_properties (); + foreach (Property prop in props) { + if (prop.access == SymbolAccessibility.PRIVATE) { + // don't register private properties continue; } - - var ciface = new CCodeIdentifier ("iface"); - string cname = m.get_real_cname (); - if (m.is_abstract || m.is_virtual) { - // FIXME results in C compiler warning - cname = m.get_cname (); - } - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.vfunc_name), new CCodeIdentifier (cname)))); - } - - // connect inherited implementations - foreach (Method m in iface.get_methods ()) { - if (m.is_abstract) { - Method cl_method = null; - var base_class = cl; - while (base_class != null && cl_method == null) { - cl_method = base_class.scope.lookup (m.name) as Method; - base_class = base_class.base_class; - } - if (base_class != null && cl_method.parent_symbol != cl) { - // method inherited from base class - - var base_method = cl_method; - if (cl_method.base_method != null) { - base_method = cl_method.base_method; - } else if (cl_method.base_interface_method != null) { - base_method = cl_method.base_interface_method; - } - - var ciface = new CCodeIdentifier ("iface"); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (base_method.get_cname ())))); - } - } - } - foreach (Property prop in cl.get_properties ()) { - if (prop.base_interface_property == null) { + var st = prop.property_type.data_type as Struct; + if (st != null && !st.has_type_id) { continue; } - var base_type = prop.base_interface_property.parent_symbol; - if (base_type != iface) { - continue; - } + if (prop.overrides || prop.base_interface_property != null) { + var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_override_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); + cinst.add_argument (prop.get_canonical_cconstant ()); - var ciface = new CCodeIdentifier ("iface"); - - if (prop.get_accessor != null) { - string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name); - if (prop.is_abstract || prop.is_virtual) { - cname = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name); - } - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } - if (prop.set_accessor != null) { - string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name); - if (prop.is_abstract || prop.is_virtual) { - cname = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name); - } - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } - } - - foreach (Property prop in iface.get_properties ()) { - if (!prop.is_abstract) { - continue; - } - - Property cl_prop = null; - var base_class = cl; - while (base_class != null && cl_prop == null) { - cl_prop = base_class.scope.lookup (prop.name) as Property; - base_class = base_class.base_class; - } - if (base_class != null && cl_prop.parent_symbol != cl) { - // property inherited from base class - - var base_property = cl_prop; - if (cl_prop.base_property != null) { - base_property = cl_prop.base_property; - } else if (cl_prop.base_interface_property != null) { - base_property = cl_prop.base_interface_property; - } - - var ciface = new CCodeIdentifier ("iface"); - - if (base_property.get_accessor != null) { - string cname = base_property.get_accessor.get_cname (); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } - if (base_property.set_accessor != null) { - string cname = base_property.set_accessor.get_cname (); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); - } + init_block.add_statement (new CCodeExpressionStatement (cinst)); + } else { + var cinst = new CCodeFunctionCall (new CCodeIdentifier ("g_object_class_install_property")); + cinst.add_argument (ccall); + cinst.add_argument (new CCodeConstant (prop.get_upper_case_cname ())); + cinst.add_argument (head.get_param_spec (prop)); + + init_block.add_statement (new CCodeExpressionStatement (cinst)); } } - - source_type_member_definition.append (iface_init); - } - - private void add_instance_init_function (Class cl) { - var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void"); - instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ()))); - instance_init.modifiers = CCodeModifiers.STATIC; - - if (cl.is_compact) { - // Add declaration, since the instance_init function is explicitly called - // by the creation methods - source_declarations.add_type_member_declaration (instance_init.copy ()); - } - - var init_block = new CCodeBlock (); - instance_init.block = init_block; - - if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) { - var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); - ccall.add_argument (new CCodeIdentifier ("self")); - init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall))); - } - - init_block.add_statement (instance_init_fragment); - - source_type_member_definition.append (instance_init); - } - - private void add_class_finalize_function (Class cl) { - var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); - source_declarations.add_type_member_declaration (function.copy ()); - - var cblock = new CCodeBlock (); - - if (cl.class_destructor != null) { - cblock.add_statement (cl.class_destructor.ccodenode); - } - - cblock.add_statement (class_finalize_fragment); - - function.block = cblock; - source_type_member_definition.append (function); - } - - private void add_base_finalize_function (Class cl) { - var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); - source_declarations.add_type_member_declaration (function.copy ()); - - var cblock = new CCodeBlock (); - - if (cl.class_destructor != null) { - cblock.add_statement (cl.class_destructor.ccodenode); - } - - cblock.add_statement (base_finalize_fragment); - - function.block = cblock; - source_type_member_definition.append (function); - } - - private void add_finalize_function (Class cl) { - var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void"); - function.modifiers = CCodeModifiers.STATIC; - - var fundamental_class = cl; - while (fundamental_class.base_class != null) { - fundamental_class = fundamental_class.base_class; - } - - function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*")); - - source_declarations.add_type_member_declaration (function.copy ()); - - - var cblock = new CCodeBlock (); - - CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl); - - var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); - cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall)); - - cblock.add_statement (cdecl); - - if (cl.destructor != null) { - cblock.add_statement (cl.destructor.ccodenode); - } - - cblock.add_statement (instance_finalize_fragment); - - // chain up to finalize function of the base class - if (cl.base_class != null) { - var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ()))); - ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null)))); - ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); - ccall.add_argument (new CCodeIdentifier ("obj")); - cblock.add_statement (new CCodeExpressionStatement (ccall)); - } - - - function.block = cblock; - - source_type_member_definition.append (function); } private bool class_has_readable_properties (Class cl) { @@ -1614,6 +257,8 @@ internal class Vala.GObjectModule : GTypeModule { block.add_statement (cswitch); + source_declarations.add_type_member_declaration (get_prop.copy ()); + get_prop.block = block; source_type_member_definition.append (get_prop); @@ -1716,6 +361,8 @@ internal class Vala.GObjectModule : GTypeModule { cswitch.add_statement (new CCodeBreakStatement ()); } + source_declarations.add_type_member_declaration (set_prop.copy ()); + set_prop.block = block; source_type_member_definition.append (set_prop); @@ -1730,183 +377,6 @@ internal class Vala.GObjectModule : GTypeModule { return new CCodeExpressionStatement (cwarn); } - public override CCodeFunctionCall get_param_spec (Property prop) { - var cspec = new CCodeFunctionCall (); - cspec.add_argument (prop.get_canonical_cconstant ()); - cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick))); - cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb))); - - - if ((prop.property_type.data_type is Class && !(((Class) prop.property_type.data_type).is_compact)) || prop.property_type.data_type is Interface) { - string param_spec_name = prop.property_type.data_type.get_param_spec_function (); - if (param_spec_name == null) { - cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); - } else { - 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 == 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) { - var e = prop.property_type.data_type as Enum; - if (e.has_type_id) { - if (e.is_flags) { - cspec.call = new CCodeIdentifier ("g_param_spec_flags"); - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_enum"); - } - cspec.add_argument (new CCodeIdentifier (e.get_type_id ())); - } else { - if (e.is_flags) { - cspec.call = new CCodeIdentifier ("g_param_spec_uint"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT")); - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_int"); - cspec.add_argument (new CCodeConstant ("G_MININT")); - cspec.add_argument (new CCodeConstant ("G_MAXINT")); - } - } - - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ())); - } - } else if (prop.property_type.data_type is Struct) { - var st = (Struct) prop.property_type.data_type; - if (st.get_type_id () == "G_TYPE_INT") { - cspec.call = new CCodeIdentifier ("g_param_spec_int"); - cspec.add_argument (new CCodeConstant ("G_MININT")); - cspec.add_argument (new CCodeConstant ("G_MAXINT")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (st.get_type_id () == "G_TYPE_UINT") { - cspec.call = new CCodeIdentifier ("g_param_spec_uint"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0U")); - } - } else if (st.get_type_id () == "G_TYPE_INT64") { - cspec.call = new CCodeIdentifier ("g_param_spec_int64"); - cspec.add_argument (new CCodeConstant ("G_MININT64")); - cspec.add_argument (new CCodeConstant ("G_MAXINT64")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (st.get_type_id () == "G_TYPE_UINT64") { - cspec.call = new CCodeIdentifier ("g_param_spec_uint64"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT64")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0U")); - } - } else if (st.get_type_id () == "G_TYPE_LONG") { - cspec.call = new CCodeIdentifier ("g_param_spec_long"); - cspec.add_argument (new CCodeConstant ("G_MINLONG")); - cspec.add_argument (new CCodeConstant ("G_MAXLONG")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0L")); - } - } else if (st.get_type_id () == "G_TYPE_ULONG") { - cspec.call = new CCodeIdentifier ("g_param_spec_ulong"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXULONG")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0UL")); - } - } else if (st.get_type_id () == "G_TYPE_BOOLEAN") { - cspec.call = new CCodeIdentifier ("g_param_spec_boolean"); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("FALSE")); - } - } else if (st.get_type_id () == "G_TYPE_CHAR") { - cspec.call = new CCodeIdentifier ("g_param_spec_char"); - cspec.add_argument (new CCodeConstant ("G_MININT8")); - cspec.add_argument (new CCodeConstant ("G_MAXINT8")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - } else if (st.get_type_id () == "G_TYPE_UCHAR") { - cspec.call = new CCodeIdentifier ("g_param_spec_uchar"); - cspec.add_argument (new CCodeConstant ("0")); - cspec.add_argument (new CCodeConstant ("G_MAXUINT8")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0")); - } - }else if (st.get_type_id () == "G_TYPE_FLOAT") { - cspec.call = new CCodeIdentifier ("g_param_spec_float"); - cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT")); - cspec.add_argument (new CCodeConstant ("G_MAXFLOAT")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0.0F")); - } - } else if (st.get_type_id () == "G_TYPE_DOUBLE") { - cspec.call = new CCodeIdentifier ("g_param_spec_double"); - cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE")); - cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE")); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("0.0")); - } - } else if (st.get_type_id () == "G_TYPE_GTYPE") { - cspec.call = new CCodeIdentifier ("g_param_spec_gtype"); - if (prop.default_expression != null) { - cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); - } else { - cspec.add_argument (new CCodeConstant ("G_TYPE_NONE")); - } - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_boxed"); - cspec.add_argument (new CCodeIdentifier (st.get_type_id ())); - } - } else { - cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); - } - - var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB"; - if (prop.get_accessor != null) { - pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE"); - } - if (prop.set_accessor != null) { - pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE"); - if (prop.set_accessor.construction) { - if (prop.set_accessor.writable) { - pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT"); - } else { - pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY"); - } - } - } - cspec.add_argument (new CCodeConstant (pflags)); - - return cspec; - } - public override CCodeExpression get_construct_property_assignment (CCodeConstant canonical_cconstant, DataType property_type, CCodeExpression value) { // this property is used as a construction parameter var cpointer = new CCodeIdentifier ("__params_it"); diff --git a/gobject/valagtypemodule.vala b/gobject/valagtypemodule.vala index 5b0aad5bb..5f748da30 100644 --- a/gobject/valagtypemodule.vala +++ b/gobject/valagtypemodule.vala @@ -29,6 +29,1554 @@ internal class Vala.GTypeModule : GErrorModule { base (codegen, next); } + public override void generate_parameter (FormalParameter param, CCodeDeclarationSpace decl_space, Map cparam_map, Map? carg_map) { + if (!(param.parameter_type is ObjectType)) { + base.generate_parameter (param, decl_space, cparam_map, carg_map); + return; + } + + generate_type_declaration (param.parameter_type, decl_space); + + string ctypename = param.parameter_type.get_cname (); + + if (param.direction != ParameterDirection.IN) { + ctypename += "*"; + } + + param.ccodenode = new CCodeFormalParameter (param.name, ctypename); + + cparam_map.set (get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode); + if (carg_map != null) { + carg_map.set (get_param_pos (param.cparameter_position), new CCodeIdentifier (param.name)); + } + } + + public override void generate_class_declaration (Class cl, CCodeDeclarationSpace decl_space) { + if (decl_space.add_symbol_declaration (cl, cl.get_cname ())) { + return; + } + + if (cl.base_class != null) { + // base class declaration + // necessary for ref and unref function declarations + generate_class_declaration (cl.base_class, decl_space); + } + + bool is_gtypeinstance = !cl.is_compact; + bool is_fundamental = is_gtypeinstance && cl.base_class == null; + + if (is_gtypeinstance) { + decl_space.add_type_declaration (new CCodeNewline ()); + var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); + decl_space.add_type_declaration (new CCodeMacroReplacement (cl.get_type_id (), macro)); + + macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_type_id (), cl.get_cname ()); + decl_space.add_type_declaration (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro)); + + macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_type_id (), cl.get_cname ()); + decl_space.add_type_declaration (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_space.add_type_declaration (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_space.add_type_declaration (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_space.add_type_declaration (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro)); + decl_space.add_type_declaration (new CCodeNewline ()); + } + + decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%s".printf (cl.get_cname ()), new CCodeVariableDeclarator (cl.get_cname ()))); + + if (is_fundamental) { + var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer"); + var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void"); + if (cl.access == SymbolAccessibility.PRIVATE) { + ref_fun.modifiers = CCodeModifiers.STATIC; + unref_fun.modifiers = CCodeModifiers.STATIC; + } + + ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); + unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); + + decl_space.add_type_member_declaration (ref_fun.copy ()); + decl_space.add_type_member_declaration (unref_fun.copy ()); + + // GParamSpec and GValue functions + var function_name = cl.get_lower_case_cname ("param_spec_"); + + var function = new CCodeFunction (function_name, "GParamSpec*"); + function.add_parameter (new CCodeFormalParameter ("name", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("object_type", "GType")); + function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags")); + + cl.set_param_spec_function (function_name); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + decl_space.add_type_member_declaration (function); + + function = new CCodeFunction (cl.get_set_value_function (), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + decl_space.add_type_member_declaration (function); + + function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + decl_space.add_type_member_declaration (function); + } + + if (is_gtypeinstance) { + decl_space.add_type_declaration (new CCodeTypeDefinition ("struct _%sClass".printf (cl.get_cname ()), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ())))); + + var type_fun = new ClassRegisterFunction (cl, context); + type_fun.init_from_type (in_plugin); + decl_space.add_type_member_declaration (type_fun.get_declaration ()); + } + } + + public override void generate_class_struct_declaration (Class cl, CCodeDeclarationSpace decl_space) { + if (decl_space.add_symbol_declaration (cl, "struct _" + cl.get_cname ())) { + return; + } + + if (cl.base_class != null) { + // base class declaration + generate_class_struct_declaration (cl.base_class, decl_space); + } + foreach (DataType base_type in cl.get_base_types ()) { + var iface = base_type.data_type as Interface; + if (iface != null) { + generate_interface_declaration (iface, decl_space); + } + } + + generate_class_declaration (cl, decl_space); + + bool is_gtypeinstance = !cl.is_compact; + bool is_fundamental = is_gtypeinstance && cl.base_class == null; + + var instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); + var type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); + + if (cl.base_class != null) { + instance_struct.add_field (cl.base_class.get_cname (), "parent_instance"); + } else if (is_fundamental) { + 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 + instance_struct.add_field ("int", "dummy"); + } + + if (is_gtypeinstance) { + decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %sPrivate".printf (instance_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ())))); + + instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); + if (is_fundamental) { + type_struct.add_field ("GTypeClass", "parent_class"); + } else { + type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class"); + } + + if (is_fundamental) { + type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ())); + } + } + + foreach (Method m in cl.get_methods ()) { + generate_virtual_method_declaration (m, decl_space, type_struct); + } + + foreach (Property prop in cl.get_properties ()) { + if (!prop.is_abstract && !prop.is_virtual) { + continue; + } + generate_type_declaration (prop.property_type, decl_space); + + var t = (ObjectTypeSymbol) prop.parent_symbol; + + bool returns_real_struct = prop.property_type.is_real_struct_type (); + + var this_type = new ObjectType (t); + var cselfparam = new CCodeFormalParameter ("self", this_type.get_cname ()); + CCodeFormalParameter cvalueparam; + if (returns_real_struct) { + cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname () + "*"); + } else { + cvalueparam = new CCodeFormalParameter ("value", prop.property_type.get_cname ()); + } + + if (prop.get_accessor != null) { + var vdeclarator = new CCodeFunctionDeclarator ("get_%s".printf (prop.name)); + vdeclarator.add_parameter (cselfparam); + string creturn_type; + if (returns_real_struct) { + vdeclarator.add_parameter (cvalueparam); + creturn_type = "void"; + } else { + creturn_type = prop.property_type.get_cname (); + } + var vdecl = new CCodeDeclaration (creturn_type); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + } + if (prop.set_accessor != null) { + var vdeclarator = new CCodeFunctionDeclarator ("set_%s".printf (prop.name)); + vdeclarator.add_parameter (cselfparam); + vdeclarator.add_parameter (cvalueparam); + var vdecl = new CCodeDeclaration ("void"); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + } + } + + foreach (Field f in cl.get_fields ()) { + string field_ctype = f.field_type.get_cname (); + if (f.is_volatile) { + field_ctype = "volatile " + field_ctype; + } + + if (f.binding == MemberBinding.INSTANCE && f.access != SymbolAccessibility.PRIVATE) { + generate_type_declaration (f.field_type, decl_space); + + instance_struct.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; + var len_type = int_type.copy (); + + for (int dim = 1; dim <= array_type.rank; dim++) { + instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim)); + } + + if (array_type.rank == 1 && f.is_internal_symbol ()) { + instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name)); + } + } 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 + instance_struct.add_field ("gpointer", get_delegate_target_cname (f.name)); + } + } + } else if (f.binding == MemberBinding.CLASS && f.access != SymbolAccessibility.PRIVATE) { + type_struct.add_field (field_ctype, f.get_cname ()); + } + } + + if (cl.source_reference.comment != null) { + decl_space.add_type_definition (new CCodeComment (cl.source_reference.comment)); + } + decl_space.add_type_definition (instance_struct); + + if (is_gtypeinstance) { + decl_space.add_type_definition (type_struct); + } + } + + public virtual void generate_virtual_method_declaration (Method m, CCodeDeclarationSpace decl_space, CCodeStruct type_struct) { + if (!m.is_abstract && !m.is_virtual) { + return; + } + + // add vfunc field to the type struct + var vdeclarator = new CCodeFunctionDeclarator (m.vfunc_name); + var cparam_map = new HashMap (direct_hash, direct_equal); + + generate_cparameters (m, decl_space, cparam_map, new CCodeFunction ("fake"), vdeclarator); + + var vdecl = new CCodeDeclaration (m.return_type.get_cname ()); + vdecl.add_declarator (vdeclarator); + type_struct.add_declaration (vdecl); + } + + void generate_class_private_declaration (Class cl, CCodeDeclarationSpace decl_space) { + if (decl_space.add_symbol_declaration (cl, cl.get_cname () + "Private")) { + return; + } + + bool is_gtypeinstance = !cl.is_compact; + + var instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); + var type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ())); + + if (is_gtypeinstance) { + /* create type, dup_func, and destroy_func fields for generic types */ + foreach (TypeParameter type_param in cl.get_type_parameters ()) { + string func_name; + + func_name = "%s_type".printf (type_param.name.down ()); + instance_priv_struct.add_field ("GType", func_name); + + func_name = "%s_dup_func".printf (type_param.name.down ()); + instance_priv_struct.add_field ("GBoxedCopyFunc", func_name); + + func_name = "%s_destroy_func".printf (type_param.name.down ()); + instance_priv_struct.add_field ("GDestroyNotify", func_name); + } + } + + foreach (Field f in cl.get_fields ()) { + string field_ctype = f.field_type.get_cname (); + if (f.is_volatile) { + field_ctype = "volatile " + field_ctype; + } + + if (f.binding == MemberBinding.INSTANCE && f.access == SymbolAccessibility.PRIVATE) { + generate_type_declaration (f.field_type, decl_space); + + instance_priv_struct.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; + var len_type = int_type.copy (); + + for (int dim = 1; dim <= array_type.rank; dim++) { + instance_priv_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim)); + } + + if (array_type.rank == 1 && f.is_internal_symbol ()) { + instance_priv_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name)); + } + } 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 + instance_priv_struct.add_field ("gpointer", get_delegate_target_cname (f.name)); + } + } + + if (f.get_lock_used ()) { + // add field for mutex + instance_priv_struct.add_field (mutex_type.get_cname (), get_symbol_lock_name (f)); + } + } else if (f.binding == MemberBinding.CLASS && f.access == SymbolAccessibility.PRIVATE) { + type_priv_struct.add_field (field_ctype, f.get_cname ()); + } + } + + if (is_gtypeinstance) { + if (cl.has_class_private_fields) { + decl_space.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ())))); + var cdecl = new CCodeDeclaration ("GQuark"); + cdecl.add_declarator (new CCodeVariableDeclarator ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()), new CCodeConstant ("0"))); + cdecl.modifiers = CCodeModifiers.STATIC; + decl_space.add_type_declaration (cdecl); + } + + /* 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) { + decl_space.add_type_definition (instance_priv_struct); + var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ()); + decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); + } + + if (cl.has_class_private_fields) { + decl_space.add_type_member_declaration (type_priv_struct); + + var macro = "((%sClassPrivate *) g_type_get_qdata (type, _vala_%s_class_private_quark))".printf (cl.get_cname(), cl.get_lower_case_cname ()); + decl_space.add_type_member_declaration (new CCodeMacroReplacement ("%s_GET_CLASS_PRIVATE(type)".printf (cl.get_upper_case_cname (null)), macro)); + } + decl_space.add_type_member_declaration (prop_enum); + } else { + var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); + + decl_space.add_type_member_declaration (function); + } + } + + public override void visit_class (Class cl) { + var old_symbol = current_symbol; + var old_type_symbol = current_type_symbol; + var old_class = current_class; + var old_param_spec_struct = param_spec_struct; + var old_prop_enum = prop_enum; + var old_class_init_fragment = class_init_fragment; + var old_base_init_fragment = base_init_fragment; + var old_class_finalize_fragment = class_finalize_fragment; + var old_base_finalize_fragment = base_finalize_fragment; + var old_instance_init_fragment = instance_init_fragment; + var old_instance_finalize_fragment = instance_finalize_fragment; + current_symbol = cl; + current_type_symbol = cl; + current_class = cl; + + bool is_gtypeinstance = !cl.is_compact; + bool is_fundamental = is_gtypeinstance && cl.base_class == null; + + if (cl.get_cname().len () < 3) { + cl.error = true; + Report.error (cl.source_reference, "Class name `%s' is too short".printf (cl.get_cname ())); + return; + } + + prop_enum = new CCodeEnum (); + prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)))); + class_init_fragment = new CCodeFragment (); + base_init_fragment = new CCodeFragment (); + class_finalize_fragment = new CCodeFragment (); + base_finalize_fragment = new CCodeFragment (); + instance_init_fragment = new CCodeFragment (); + instance_finalize_fragment = new CCodeFragment (); + + + generate_class_struct_declaration (cl, source_declarations); + generate_class_private_declaration (cl, source_declarations); + + if (!cl.is_internal_symbol ()) { + generate_class_struct_declaration (cl, header_declarations); + } + generate_class_struct_declaration (cl, internal_header_declarations); + + cl.accept_children (codegen); + + if (is_gtypeinstance) { + if (is_fundamental) { + param_spec_struct = new CCodeStruct ( "_%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)); + param_spec_struct.add_field ("GParamSpec", "parent_instance"); + source_declarations.add_type_definition (param_spec_struct); + + source_declarations.add_type_declaration (new CCodeTypeDefinition ("struct %s".printf (param_spec_struct.name), new CCodeVariableDeclarator ( "%sParamSpec%s".printf(cl.parent_symbol.get_cprefix (), cl.name)))); + + + gvaluecollector_h_needed = true; + + add_type_value_table_init_function (cl); + add_type_value_table_free_function (cl); + add_type_value_table_copy_function (cl); + add_type_value_table_peek_pointer_function (cl); + add_type_value_table_collect_value_function (cl); + add_type_value_table_lcopy_value_function (cl); + add_g_param_spec_type_function (cl); + add_g_value_get_function (cl); + add_g_value_set_function (cl); + + var ref_count = new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"), new CCodeConstant ("1")); + instance_init_fragment.append (new CCodeExpressionStatement (ref_count)); + } + + + if (cl.class_constructor != null || cl.has_class_private_fields) { + add_base_init_function (cl); + } + add_class_init_function (cl); + + if (cl.class_destructor != null || cl.has_class_private_fields) { + add_base_finalize_function (cl); + } + + if (cl.static_destructor != null) { + add_class_finalize_function (cl); + } + + foreach (DataType base_type in cl.get_base_types ()) { + if (base_type.data_type is Interface) { + add_interface_init_function (cl, (Interface) base_type.data_type); + } + } + + add_instance_init_function (cl); + + if (!cl.is_compact && (cl.get_fields ().size > 0 || cl.destructor != null || cl.is_fundamental ())) { + add_finalize_function (cl); + } + + var type_fun = new ClassRegisterFunction (cl, context); + type_fun.init_from_type (in_plugin); + source_type_member_definition.append (type_fun.get_definition ()); + + 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 (module_init_param_name)); + module_init_fragment.append (new CCodeExpressionStatement (register_call)); + } + + if (is_fundamental) { + var ref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "ref", "gpointer"); + var unref_fun = new CCodeFunction (cl.get_lower_case_cprefix () + "unref", "void"); + if (cl.access == SymbolAccessibility.PRIVATE) { + ref_fun.modifiers = CCodeModifiers.STATIC; + unref_fun.modifiers = CCodeModifiers.STATIC; + } + + ref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); + unref_fun.add_parameter (new CCodeFormalParameter ("instance", "gpointer")); + + var ref_block = new CCodeBlock (); + var unref_block = new CCodeBlock (); + + var cdecl = new CCodeDeclaration (cl.get_cname () + "*"); + cdecl.add_declarator (new CCodeVariableDeclarator ("self", new CCodeIdentifier ("instance"))); + ref_block.add_statement (cdecl); + unref_block.add_statement (cdecl); + + var ref_count = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "ref_count"); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_inc")); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); + ref_block.add_statement (new CCodeExpressionStatement (ccall)); + + ref_block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("instance"))); + + var destroy_block = new CCodeBlock (); + var get_class = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); + get_class.add_argument (new CCodeIdentifier ("self")); + + // finalize class + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS".printf (cl.get_upper_case_cname (null)))); + ccast.add_argument (new CCodeIdentifier ("self")); + ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); + ccall.add_argument (new CCodeIdentifier ("self")); + destroy_block.add_statement (new CCodeExpressionStatement (ccall)); + + // free type instance + var free = new CCodeFunctionCall (new CCodeIdentifier ("g_type_free_instance")); + free.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GTypeInstance *")); + destroy_block.add_statement (new CCodeExpressionStatement (free)); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_atomic_int_dec_and_test")); + ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, ref_count)); + unref_block.add_statement (new CCodeIfStatement (ccall, destroy_block)); + + ref_fun.block = ref_block; + unref_fun.block = unref_block; + + source_type_member_definition.append (ref_fun); + source_type_member_definition.append (unref_fun); + } + } else { + add_instance_init_function (cl); + + var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); + + var cblock = new CCodeBlock (); + + cblock.add_statement (instance_finalize_fragment); + + if (cl.destructor != null) { + cblock.add_statement (cl.destructor.ccodenode); + } + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); + ccall.add_argument (new CCodeIdentifier ("self")); + cblock.add_statement (new CCodeExpressionStatement (ccall)); + + function.block = cblock; + + source_type_member_definition.append (function); + } + + current_symbol = old_symbol; + current_type_symbol = old_type_symbol; + current_class = old_class; + param_spec_struct = old_param_spec_struct; + prop_enum = old_prop_enum; + class_init_fragment = old_class_init_fragment; + base_init_fragment = old_base_init_fragment; + class_finalize_fragment = old_class_finalize_fragment; + base_finalize_fragment = old_base_finalize_fragment; + instance_init_fragment = old_instance_init_fragment; + instance_finalize_fragment = old_instance_finalize_fragment; + } + + private void add_type_value_table_init_function (Class cl) { + var function = new CCodeFunction ("%s_init".printf (cl.get_lower_case_cname ("value_")), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + 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))); + source_type_member_definition.append (function); + } + + private void add_type_value_table_free_function (Class cl) { + var function = new CCodeFunction ("%s_free_value".printf (cl.get_lower_case_cname ("value_")), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "unref")); + ccall.add_argument ( vpointer ); + + var ifbody = new CCodeBlock (); + ifbody.add_statement ( new CCodeExpressionStatement(ccall) ); + + init_block.add_statement(new CCodeIfStatement (vpointer, ifbody)); + source_type_member_definition.append (function); + } + + private void add_type_value_table_copy_function (Class cl) { + var function = new CCodeFunction ("%s_copy_value".printf (cl.get_lower_case_cname ("value_")), "void"); + function.add_parameter (new CCodeFormalParameter ("src_value", "const GValue*")); + function.add_parameter (new CCodeFormalParameter ("dest_value", "GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var dest_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest_value"), "data[0]"),"v_pointer"); + var src_vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("src_value"), "data[0]"),"v_pointer"); + + var ref_ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_lower_case_cprefix () + "ref")); + ref_ccall.add_argument ( src_vpointer ); + + var true_stmt = new CCodeBlock (); + true_stmt.add_statement(new CCodeExpressionStatement(new CCodeAssignment (dest_vpointer, ref_ccall, CCodeAssignmentOperator.SIMPLE))); + + var false_stmt = new CCodeBlock (); + false_stmt.add_statement (new CCodeExpressionStatement( new CCodeAssignment (dest_vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + + var if_statement = new CCodeIfStatement (src_vpointer, true_stmt, false_stmt); + init_block.add_statement (if_statement); + + source_type_member_definition.append (function); + } + + private void add_type_value_table_peek_pointer_function (Class cl) { + var function = new CCodeFunction ("%s_peek_pointer".printf (cl.get_lower_case_cname ("value_")), "gpointer"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + function.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + function.block = init_block; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + var ret = new CCodeReturnStatement ( vpointer ); + init_block.add_statement (ret); + + source_type_member_definition.append (function); + } + + private void add_type_value_table_lcopy_value_function ( Class cl ) { + var function = new CCodeFunction ("%s_lcopy_value".printf (cl.get_lower_case_cname ("value_")), "gchar*"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); + function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); + function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); + function.modifiers = CCodeModifiers.STATIC; + + var vpointer = new CCodeMemberAccess (new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"), "v_pointer"); + var object_p_ptr = new CCodeIdentifier ("*object_p"); + var null_ = new CCodeConstant ("NULL"); + + var init_block = new CCodeBlock (); + + var ctypedecl = new CCodeDeclaration (cl.get_cname () + "**"); + ctypedecl.add_declarator (new CCodeVariableDeclarator ("object_p", new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"),"v_pointer"))); + init_block.add_statement (ctypedecl); + + var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); + value_type_name_fct.add_argument (new CCodeConstant ("value")); + + var assert_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new CCodeIdentifier ("object_p")); + function.block = init_block; + var assert_true = new CCodeBlock (); + var assert_printf = new CCodeFunctionCall (new CCodeIdentifier ("g_strdup_printf")); + assert_printf.add_argument (new CCodeConstant ("\"value location for `%s' passed as NULL\"")); + assert_printf.add_argument (value_type_name_fct); + assert_true.add_statement (new CCodeReturnStatement (assert_printf)); + var if_assert = new CCodeIfStatement (assert_condition, assert_true); + init_block.add_statement (if_assert); + + var main_else_true = new CCodeBlock (); + var main_else_if_true = new CCodeBlock (); + var main_else_if_condition = new CCodeBinaryExpression (CCodeBinaryOperator.AND, new CCodeIdentifier ("collect_flags"), new CCodeIdentifier ("G_VALUE_NOCOPY_CONTENTS")); + var main_else_if = new CCodeIfStatement (main_else_if_condition, main_else_if_true, main_else_true); + + var main_true = new CCodeBlock (); + var main_condition = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, vpointer); + var if_main = new CCodeIfStatement (main_condition, main_true, main_else_if); + init_block.add_statement (if_main); + + var ref_fct = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function())); + ref_fct.add_argument (vpointer); + + main_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, null_, CCodeAssignmentOperator.SIMPLE))); + main_else_if_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, vpointer, CCodeAssignmentOperator.SIMPLE))); + main_else_true.add_statement (new CCodeExpressionStatement (new CCodeAssignment (object_p_ptr, ref_fct, CCodeAssignmentOperator.SIMPLE))); + + init_block.add_statement (new CCodeReturnStatement (null_)); + source_type_member_definition.append (function); + } + + private void add_type_value_table_collect_value_function (Class cl) { + var function = new CCodeFunction ("%s_collect_value".printf (cl.get_lower_case_cname ("value_")), "gchar*"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("n_collect_values", "guint")); + function.add_parameter (new CCodeFormalParameter ("collect_values", "GTypeCValue*")); + function.add_parameter (new CCodeFormalParameter ("collect_flags", "guint")); + function.modifiers = CCodeModifiers.STATIC; + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var collect_vpointer = new CCodeMemberAccess (new CCodeIdentifier ("collect_values[0]"), "v_pointer"); + + var true_stmt = new CCodeBlock (); + var false_stmt = new CCodeBlock (); + var if_statement = new CCodeIfStatement (collect_vpointer, true_stmt, false_stmt); + init_block.add_statement (if_statement); + + var obj_identifier = new CCodeIdentifier ("object"); + + var ctypedecl = new CCodeDeclaration (cl.get_cname () + "*"); + ctypedecl.add_declarator (new CCodeVariableDeclarator ("object", collect_vpointer)); + true_stmt.add_statement (ctypedecl); + + var l_expression = new CCodeMemberAccess (new CCodeMemberAccess.pointer (obj_identifier, "parent_instance"), "g_class"); + var sub_condition = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, l_expression, new CCodeConstant ("NULL")); + var sub_true_stmt = new CCodeBlock (); + var sub_false_stmt = new CCodeBlock (); + + var reg_call = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); + var type_check = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); + type_check.add_argument (new CCodeIdentifier ("object")); + reg_call.add_argument (type_check); + + var type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("g_type_name")); + type_name_fct.add_argument (type_check); + + var stored_type = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + stored_type.add_argument (new CCodeIdentifier ("value")); + reg_call.add_argument (stored_type); + + var value_type_name_fct = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE_NAME")); + value_type_name_fct.add_argument (new CCodeConstant ("value")); + + var true_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); + true_return.add_argument (new CCodeConstant ("\"invalid unclassed object pointer for value type `\"")); + true_return.add_argument (value_type_name_fct); + true_return.add_argument (new CCodeConstant ("\"'\"")); + true_return.add_argument (new CCodeConstant ("NULL")); + sub_true_stmt.add_statement (new CCodeReturnStatement (true_return)); + + var false_return = new CCodeFunctionCall (new CCodeIdentifier ("g_strconcat")); + false_return.add_argument (new CCodeConstant ("\"invalid object type `\"")); + false_return.add_argument (type_name_fct); + false_return.add_argument (new CCodeConstant ("\"' for value type `\"")); + false_return.add_argument (value_type_name_fct); + false_return.add_argument (new CCodeConstant ("\"'\"")); + false_return.add_argument (new CCodeConstant ("NULL")); + sub_false_stmt.add_statement (new CCodeReturnStatement (false_return)); + + var sub_else_if_statement = new CCodeIfStatement (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, reg_call), sub_false_stmt ); + sub_else_if_statement.else_if = true; + var sub_if_statement = new CCodeIfStatement (sub_condition, sub_true_stmt, sub_else_if_statement); + true_stmt.add_statement (sub_if_statement); + + var ref_call = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ())); + ref_call.add_argument (new CCodeIdentifier ("object")); + + var true_assignment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, ref_call, CCodeAssignmentOperator.SIMPLE)); + true_stmt.add_statement (true_assignment); + + var else_assigment = new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE)); + false_stmt.add_statement (else_assigment); + + init_block.add_statement (new CCodeReturnStatement (new CCodeConstant ("NULL"))); + source_type_member_definition.append (function); + } + + private void add_g_param_spec_type_function (Class cl) { + var function_name = cl.get_lower_case_cname ("param_spec_"); + + var function = new CCodeFunction (function_name, "GParamSpec*"); + function.add_parameter (new CCodeFormalParameter ("name", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("nick", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("blurb", "const gchar*")); + function.add_parameter (new CCodeFormalParameter ("object_type", "GType")); + function.add_parameter (new CCodeFormalParameter ("flags", "GParamFlags")); + + cl.set_param_spec_function ( function_name ); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ctypedecl = new CCodeDeclaration ("%sParamSpec%s*".printf (cl.parent_symbol.get_cprefix (), cl.name)); + ctypedecl.add_declarator ( new CCodeVariableDeclarator ("spec")); + init_block.add_statement (ctypedecl); + + var subccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_is_a")); + subccall.add_argument (new CCodeIdentifier ("object_type")); + subccall.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); + ccall.add_argument (subccall); + ccall.add_argument (new CCodeIdentifier ("NULL")); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_param_spec_internal")); + ccall.add_argument (new CCodeIdentifier ( "G_TYPE_PARAM_OBJECT" )); + ccall.add_argument (new CCodeIdentifier ("name")); + ccall.add_argument (new CCodeIdentifier ("nick")); + ccall.add_argument (new CCodeIdentifier ("blurb")); + ccall.add_argument (new CCodeIdentifier ("flags")); + + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("spec"), ccall, CCodeAssignmentOperator.SIMPLE ))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("G_PARAM_SPEC")); + ccall.add_argument (new CCodeIdentifier ("spec")); + + 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)); + source_type_member_definition.append (function); + } + + private void add_g_value_set_function (Class cl) { + var function = new CCodeFunction (cl.get_set_value_function (), "void"); + function.add_parameter (new CCodeFormalParameter ("value", "GValue*")); + function.add_parameter (new CCodeFormalParameter ("v_object", "gpointer")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ctypedecl = new CCodeDeclaration (cl.get_cname()+"*"); + ctypedecl.add_declarator ( new CCodeVariableDeclarator ("old")); + init_block.add_statement (ctypedecl); + + var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement(new CCodeExpressionStatement (new CCodeAssignment (new CCodeConstant ("old"), vpointer, CCodeAssignmentOperator.SIMPLE))); + + var true_stmt = new CCodeBlock (); + var false_stmt = new CCodeBlock (); + var if_statement = new CCodeIfStatement (new CCodeIdentifier ("v_object"), true_stmt, false_stmt); + init_block.add_statement (if_statement); + + + ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_INSTANCE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "v_object" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecheck); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + var ccall_typefrominstance = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_INSTANCE")); + ccall_typefrominstance.add_argument (new CCodeIdentifier ( "v_object" )); + + var ccall_gvaluetype = new CCodeFunctionCall (new CCodeIdentifier ("G_VALUE_TYPE")); + ccall_gvaluetype.add_argument (new CCodeIdentifier ( "value" )); + + var ccall_typecompatible = new CCodeFunctionCall (new CCodeIdentifier ("g_value_type_compatible")); + ccall_typecompatible.add_argument (ccall_typefrominstance); + ccall_typecompatible.add_argument (ccall_gvaluetype); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_if_fail")); + ccall.add_argument (ccall_typecompatible); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + true_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("v_object"), CCodeAssignmentOperator.SIMPLE))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_ref_function ())); + ccall.add_argument (vpointer); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + + false_stmt.add_statement(new CCodeExpressionStatement (new CCodeAssignment (vpointer, new CCodeConstant ("NULL"), CCodeAssignmentOperator.SIMPLE))); + + true_stmt = new CCodeBlock (); + if_statement = new CCodeIfStatement (new CCodeIdentifier ("old"), true_stmt); + init_block.add_statement (if_statement); + + ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_unref_function ())); + ccall.add_argument (new CCodeIdentifier ("old")); + true_stmt.add_statement (new CCodeExpressionStatement (ccall)); + source_type_member_definition.append (function); + } + + private void add_g_value_get_function (Class cl) { + var function = new CCodeFunction (cl.get_get_value_function (), "gpointer"); + function.add_parameter (new CCodeFormalParameter ("value", "const GValue*")); + + if (cl.access == SymbolAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + var vpointer = new CCodeMemberAccess(new CCodeMemberAccess.pointer (new CCodeIdentifier ("value"), "data[0]"),"v_pointer"); + + var init_block = new CCodeBlock (); + function.block = init_block; + + var ccall_typecheck = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_CHECK_VALUE_TYPE")); + ccall_typecheck.add_argument (new CCodeIdentifier ( "value" )); + ccall_typecheck.add_argument (new CCodeIdentifier ( cl.get_type_id() )); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_return_val_if_fail")); + ccall.add_argument (ccall_typecheck); + ccall.add_argument (new CCodeIdentifier ( "NULL" )); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement (new CCodeReturnStatement ( vpointer )); + source_type_member_definition.append (function); + } + + private void add_base_init_function (Class cl) { + 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; + + var init_block = new CCodeBlock (); + base_init.block = init_block; + + if (cl.has_class_private_fields) { + var block = new CCodeBlock (); + var cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); + block.add_statement (cdecl); + cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator ("parent_priv", new CCodeConstant ("NULL"))); + block.add_statement (cdecl); + cdecl = new CCodeDeclaration ("GType"); + cdecl.add_declarator (new CCodeVariableDeclarator ("parent_type")); + block.add_statement (cdecl); + + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_parent")); + var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); + ccall2.add_argument (new CCodeIdentifier ("klass")); + ccall.add_argument (ccall2); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_type"), ccall))); + + var iftrue = new CCodeBlock (); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); + ccall.add_argument (new CCodeIdentifier ("parent_type")); + iftrue.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("parent_priv"), ccall))); + block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_type"), iftrue)); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); + ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf(cl.get_cname()))); + + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); + + source_declarations.add_include ("string.h"); + + iftrue = new CCodeBlock (); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); + ccall.add_argument (new CCodeIdentifier ("priv")); + ccall.add_argument (new CCodeIdentifier ("parent_priv")); + ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname()))); + iftrue.add_statement (new CCodeExpressionStatement (ccall)); + + block.add_statement (new CCodeIfStatement (new CCodeIdentifier ("parent_priv"), iftrue)); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_set_qdata")); + ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); + ccall2.add_argument (new CCodeIdentifier ("klass")); + ccall.add_argument (ccall2); + ccall.add_argument (new CCodeIdentifier ("_vala_%s_class_private_quark".printf (cl.get_lower_case_cname ()))); + ccall.add_argument (new CCodeIdentifier ("priv")); + block.add_statement (new CCodeExpressionStatement (ccall)); + + init_block.add_statement (block); + + block = new CCodeBlock (); + cdecl = new CCodeDeclaration ("%sClassPrivate *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator ("priv")); + block.add_statement (cdecl); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname (null)))); + ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); + ccall2.add_argument (new CCodeIdentifier ("klass")); + ccall.add_argument (ccall2); + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeIdentifier ("priv"), ccall))); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ()))); + ccall.add_argument (new CCodeIdentifier ("priv")); + block.add_statement (new CCodeExpressionStatement (ccall)); + base_finalize_fragment.append (block); + } + + init_block.add_statement (base_init_fragment); + + source_type_member_definition.append (base_init); + } + + public virtual void generate_class_init (Class cl, CCodeBlock init_block) { + } + + private void add_class_init_function (Class cl) { + var class_init = new CCodeFunction ("%s_class_init".printf (cl.get_lower_case_cname (null)), "void"); + class_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); + class_init.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + class_init.block = init_block; + + CCodeFunctionCall ccall; + + /* save pointer to parent class */ + var parent_decl = new CCodeDeclaration ("gpointer"); + var parent_var_decl = new CCodeVariableDeclarator ("%s_parent_class".printf (cl.get_lower_case_cname (null))); + parent_var_decl.initializer = new CCodeConstant ("NULL"); + parent_decl.add_declarator (parent_var_decl); + parent_decl.modifiers = CCodeModifiers.STATIC; + source_declarations.add_type_member_declaration (parent_decl); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_peek_parent")); + ccall.add_argument (new CCodeIdentifier ("klass")); + var parent_assignment = new CCodeAssignment (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null))), ccall); + init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); + + + 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) { + fundamental_class = fundamental_class.base_class; + } + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname (null)))); + ccall.add_argument (new CCodeIdentifier ("klass")); + var finalize_assignment = new CCodeAssignment (new CCodeMemberAccess.pointer (ccall, "finalize"), new CCodeIdentifier (cl.get_lower_case_cprefix () + "finalize")); + init_block.add_statement (new CCodeExpressionStatement (finalize_assignment)); + } + + /* add struct for private fields */ + if (cl.has_private_fields || cl.get_type_parameters ().size > 0) { + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_class_add_private")); + ccall.add_argument (new CCodeIdentifier ("klass")); + ccall.add_argument (new CCodeConstant ("sizeof (%sPrivate)".printf (cl.get_cname ()))); + init_block.add_statement (new CCodeExpressionStatement (ccall)); + } + + /* connect overridden methods */ + foreach (Method m in cl.get_methods ()) { + if (m.base_method == null) { + continue; + } + var base_type = m.base_method.parent_symbol; + + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); + ccast.add_argument (new CCodeIdentifier ("klass")); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ())))); + } + + /* connect overridden properties */ + foreach (Property prop in cl.get_properties ()) { + if (prop.base_property == null) { + continue; + } + var base_type = prop.base_property.parent_symbol; + + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null)))); + ccast.add_argument (new CCodeIdentifier ("klass")); + + if (prop.get_accessor != null) { + string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + if (prop.set_accessor != null) { + string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + } + + /* initialize class fields */ + var fields = cl.get_fields (); + foreach (Field field in fields) { + if (field.binding != MemberBinding.CLASS || field.initializer == null) { + continue; + } + + CCodeExpression left; + + if (field.access == SymbolAccessibility.PRIVATE) { + ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_CLASS_PRIVATE".printf (cl.get_upper_case_cname ()))); + var ccall2 = new CCodeFunctionCall (new CCodeIdentifier ("G_TYPE_FROM_CLASS")); + ccall2.add_argument (new CCodeIdentifier ("klass")); + ccall.add_argument (ccall2); + left = new CCodeMemberAccess (ccall, field.get_cname (), true); + } else { + left = new CCodeMemberAccess (new CCodeIdentifier ("klass"), field.get_cname (), true); + } + CCodeExpression right = (CCodeExpression) field.initializer.ccodenode; + CCodeAssignment assign = new CCodeAssignment (left, right); + init_block.add_statement (new CCodeExpressionStatement (assign)); + } + + generate_class_init (cl, init_block); + + if (!cl.is_compact) { + /* create signals */ + foreach (Signal sig in cl.get_signals ()) { + init_block.add_statement (new CCodeExpressionStatement (head.get_signal_creation (sig, cl))); + } + } + + init_block.add_statement (head.register_dbus_info (cl)); + init_block.add_statement (class_init_fragment); + + source_type_member_definition.append (class_init); + } + + private void add_interface_init_function (Class cl, Interface iface) { + var iface_init = new CCodeFunction ("%s_%s_interface_init".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)), "void"); + iface_init.add_parameter (new CCodeFormalParameter ("iface", "%s *".printf (iface.get_type_cname ()))); + iface_init.modifiers = CCodeModifiers.STATIC; + + var init_block = new CCodeBlock (); + iface_init.block = init_block; + + CCodeFunctionCall ccall; + + /* save pointer to parent vtable */ + string parent_iface_var = "%s_%s_parent_iface".printf (cl.get_lower_case_cname (null), iface.get_lower_case_cname (null)); + var parent_decl = new CCodeDeclaration (iface.get_type_cname () + "*"); + var parent_var_decl = new CCodeVariableDeclarator (parent_iface_var); + parent_var_decl.initializer = new CCodeConstant ("NULL"); + parent_decl.add_declarator (parent_var_decl); + parent_decl.modifiers = CCodeModifiers.STATIC; + source_declarations.add_type_member_declaration (parent_decl); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_type_interface_peek_parent")); + ccall.add_argument (new CCodeIdentifier ("iface")); + var parent_assignment = new CCodeAssignment (new CCodeIdentifier (parent_iface_var), ccall); + init_block.add_statement (new CCodeExpressionStatement (parent_assignment)); + + foreach (Method m in cl.get_methods ()) { + if (m.base_interface_method == null) { + continue; + } + + var base_type = m.base_interface_method.parent_symbol; + if (base_type != iface) { + continue; + } + + var ciface = new CCodeIdentifier ("iface"); + string cname = m.get_real_cname (); + if (m.is_abstract || m.is_virtual) { + // FIXME results in C compiler warning + cname = m.get_cname (); + } + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.base_interface_method.vfunc_name), new CCodeIdentifier (cname)))); + } + + // connect inherited implementations + foreach (Method m in iface.get_methods ()) { + if (m.is_abstract) { + Method cl_method = null; + var base_class = cl; + while (base_class != null && cl_method == null) { + cl_method = base_class.scope.lookup (m.name) as Method; + base_class = base_class.base_class; + } + if (base_class != null && cl_method.parent_symbol != cl) { + // method inherited from base class + + var base_method = cl_method; + if (cl_method.base_method != null) { + base_method = cl_method.base_method; + } else if (cl_method.base_interface_method != null) { + base_method = cl_method.base_interface_method; + } + + var ciface = new CCodeIdentifier ("iface"); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, m.vfunc_name), new CCodeIdentifier (base_method.get_cname ())))); + } + } + } + + foreach (Property prop in cl.get_properties ()) { + if (prop.base_interface_property == null) { + continue; + } + + var base_type = prop.base_interface_property.parent_symbol; + if (base_type != iface) { + continue; + } + + var ciface = new CCodeIdentifier ("iface"); + + if (prop.get_accessor != null) { + string cname = "%s_real_get_%s".printf (cl.get_lower_case_cname (null), prop.name); + if (prop.is_abstract || prop.is_virtual) { + cname = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name); + } + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + if (prop.set_accessor != null) { + string cname = "%s_real_set_%s".printf (cl.get_lower_case_cname (null), prop.name); + if (prop.is_abstract || prop.is_virtual) { + cname = "%s_set_%s".printf (cl.get_lower_case_cname (null), prop.name); + } + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + } + + foreach (Property prop in iface.get_properties ()) { + if (!prop.is_abstract) { + continue; + } + + Property cl_prop = null; + var base_class = cl; + while (base_class != null && cl_prop == null) { + cl_prop = base_class.scope.lookup (prop.name) as Property; + base_class = base_class.base_class; + } + if (base_class != null && cl_prop.parent_symbol != cl) { + // property inherited from base class + + var base_property = cl_prop; + if (cl_prop.base_property != null) { + base_property = cl_prop.base_property; + } else if (cl_prop.base_interface_property != null) { + base_property = cl_prop.base_interface_property; + } + + var ciface = new CCodeIdentifier ("iface"); + + if (base_property.get_accessor != null) { + string cname = base_property.get_accessor.get_cname (); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "get_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + if (base_property.set_accessor != null) { + string cname = base_property.set_accessor.get_cname (); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ciface, "set_%s".printf (prop.name)), new CCodeIdentifier (cname)))); + } + } + } + + source_type_member_definition.append (iface_init); + } + + private void add_instance_init_function (Class cl) { + var instance_init = new CCodeFunction ("%s_instance_init".printf (cl.get_lower_case_cname (null)), "void"); + instance_init.add_parameter (new CCodeFormalParameter ("self", "%s *".printf (cl.get_cname ()))); + instance_init.modifiers = CCodeModifiers.STATIC; + + if (cl.is_compact) { + // Add declaration, since the instance_init function is explicitly called + // by the creation methods + source_declarations.add_type_member_declaration (instance_init.copy ()); + } + + var init_block = new CCodeBlock (); + instance_init.block = init_block; + + if (!cl.is_compact && (cl.has_private_fields || cl.get_type_parameters ().size > 0)) { + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("%s_GET_PRIVATE".printf (cl.get_upper_case_cname (null)))); + ccall.add_argument (new CCodeIdentifier ("self")); + init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), ccall))); + } + + init_block.add_statement (instance_init_fragment); + + source_type_member_definition.append (instance_init); + } + + private void add_class_finalize_function (Class cl) { + var function = new CCodeFunction ("%s_class_finalize".printf (cl.get_lower_case_cname (null)), "void"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); + source_declarations.add_type_member_declaration (function.copy ()); + + var cblock = new CCodeBlock (); + + if (cl.class_destructor != null) { + cblock.add_statement (cl.class_destructor.ccodenode); + } + + cblock.add_statement (class_finalize_fragment); + + function.block = cblock; + source_type_member_definition.append (function); + } + + private void add_base_finalize_function (Class cl) { + var function = new CCodeFunction ("%s_base_finalize".printf (cl.get_lower_case_cname (null)), "void"); + function.modifiers = CCodeModifiers.STATIC; + + function.add_parameter (new CCodeFormalParameter ("klass", cl.get_cname () + "Class *")); + source_declarations.add_type_member_declaration (function.copy ()); + + var cblock = new CCodeBlock (); + + if (cl.class_destructor != null) { + cblock.add_statement (cl.class_destructor.ccodenode); + } + + cblock.add_statement (base_finalize_fragment); + + function.block = cblock; + source_type_member_definition.append (function); + } + + private void add_finalize_function (Class cl) { + var function = new CCodeFunction ("%s_finalize".printf (cl.get_lower_case_cname (null)), "void"); + function.modifiers = CCodeModifiers.STATIC; + + var fundamental_class = cl; + while (fundamental_class.base_class != null) { + fundamental_class = fundamental_class.base_class; + } + + function.add_parameter (new CCodeFormalParameter ("obj", fundamental_class.get_cname () + "*")); + + source_declarations.add_type_member_declaration (function.copy ()); + + + var cblock = new CCodeBlock (); + + CCodeFunctionCall ccall = new InstanceCast (new CCodeIdentifier ("obj"), cl); + + var cdecl = new CCodeDeclaration ("%s *".printf (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator ("self", ccall)); + + cblock.add_statement (cdecl); + + if (cl.destructor != null) { + cblock.add_statement (cl.destructor.ccodenode); + } + + cblock.add_statement (instance_finalize_fragment); + + // chain up to finalize function of the base class + if (cl.base_class != null) { + var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (fundamental_class.get_upper_case_cname ()))); + ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (cl.get_lower_case_cname (null)))); + ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (ccast, "finalize")); + ccall.add_argument (new CCodeIdentifier ("obj")); + cblock.add_statement (new CCodeExpressionStatement (ccall)); + } + + + function.block = cblock; + + source_type_member_definition.append (function); + } + + public override CCodeFunctionCall get_param_spec (Property prop) { + var cspec = new CCodeFunctionCall (); + cspec.add_argument (prop.get_canonical_cconstant ()); + cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.nick))); + cspec.add_argument (new CCodeConstant ("\"%s\"".printf (prop.blurb))); + + + if ((prop.property_type.data_type is Class && !(((Class) prop.property_type.data_type).is_compact)) || prop.property_type.data_type is Interface) { + string param_spec_name = prop.property_type.data_type.get_param_spec_function (); + if (param_spec_name == null) { + cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); + } else { + 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 == 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) { + var e = prop.property_type.data_type as Enum; + if (e.has_type_id) { + if (e.is_flags) { + cspec.call = new CCodeIdentifier ("g_param_spec_flags"); + } else { + cspec.call = new CCodeIdentifier ("g_param_spec_enum"); + } + cspec.add_argument (new CCodeIdentifier (e.get_type_id ())); + } else { + if (e.is_flags) { + cspec.call = new CCodeIdentifier ("g_param_spec_uint"); + cspec.add_argument (new CCodeConstant ("0")); + cspec.add_argument (new CCodeConstant ("G_MAXUINT")); + } else { + cspec.call = new CCodeIdentifier ("g_param_spec_int"); + cspec.add_argument (new CCodeConstant ("G_MININT")); + cspec.add_argument (new CCodeConstant ("G_MAXINT")); + } + } + + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant (prop.property_type.data_type.get_default_value ())); + } + } else if (prop.property_type.data_type is Struct) { + var st = (Struct) prop.property_type.data_type; + if (st.get_type_id () == "G_TYPE_INT") { + cspec.call = new CCodeIdentifier ("g_param_spec_int"); + cspec.add_argument (new CCodeConstant ("G_MININT")); + cspec.add_argument (new CCodeConstant ("G_MAXINT")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0")); + } + } else if (st.get_type_id () == "G_TYPE_UINT") { + cspec.call = new CCodeIdentifier ("g_param_spec_uint"); + cspec.add_argument (new CCodeConstant ("0")); + cspec.add_argument (new CCodeConstant ("G_MAXUINT")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0U")); + } + } else if (st.get_type_id () == "G_TYPE_INT64") { + cspec.call = new CCodeIdentifier ("g_param_spec_int64"); + cspec.add_argument (new CCodeConstant ("G_MININT64")); + cspec.add_argument (new CCodeConstant ("G_MAXINT64")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0")); + } + } else if (st.get_type_id () == "G_TYPE_UINT64") { + cspec.call = new CCodeIdentifier ("g_param_spec_uint64"); + cspec.add_argument (new CCodeConstant ("0")); + cspec.add_argument (new CCodeConstant ("G_MAXUINT64")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0U")); + } + } else if (st.get_type_id () == "G_TYPE_LONG") { + cspec.call = new CCodeIdentifier ("g_param_spec_long"); + cspec.add_argument (new CCodeConstant ("G_MINLONG")); + cspec.add_argument (new CCodeConstant ("G_MAXLONG")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0L")); + } + } else if (st.get_type_id () == "G_TYPE_ULONG") { + cspec.call = new CCodeIdentifier ("g_param_spec_ulong"); + cspec.add_argument (new CCodeConstant ("0")); + cspec.add_argument (new CCodeConstant ("G_MAXULONG")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0UL")); + } + } else if (st.get_type_id () == "G_TYPE_BOOLEAN") { + cspec.call = new CCodeIdentifier ("g_param_spec_boolean"); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("FALSE")); + } + } else if (st.get_type_id () == "G_TYPE_CHAR") { + cspec.call = new CCodeIdentifier ("g_param_spec_char"); + cspec.add_argument (new CCodeConstant ("G_MININT8")); + cspec.add_argument (new CCodeConstant ("G_MAXINT8")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0")); + } + } else if (st.get_type_id () == "G_TYPE_UCHAR") { + cspec.call = new CCodeIdentifier ("g_param_spec_uchar"); + cspec.add_argument (new CCodeConstant ("0")); + cspec.add_argument (new CCodeConstant ("G_MAXUINT8")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0")); + } + }else if (st.get_type_id () == "G_TYPE_FLOAT") { + cspec.call = new CCodeIdentifier ("g_param_spec_float"); + cspec.add_argument (new CCodeConstant ("-G_MAXFLOAT")); + cspec.add_argument (new CCodeConstant ("G_MAXFLOAT")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0.0F")); + } + } else if (st.get_type_id () == "G_TYPE_DOUBLE") { + cspec.call = new CCodeIdentifier ("g_param_spec_double"); + cspec.add_argument (new CCodeConstant ("-G_MAXDOUBLE")); + cspec.add_argument (new CCodeConstant ("G_MAXDOUBLE")); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("0.0")); + } + } else if (st.get_type_id () == "G_TYPE_GTYPE") { + cspec.call = new CCodeIdentifier ("g_param_spec_gtype"); + if (prop.default_expression != null) { + cspec.add_argument ((CCodeExpression) prop.default_expression.ccodenode); + } else { + cspec.add_argument (new CCodeConstant ("G_TYPE_NONE")); + } + } else { + cspec.call = new CCodeIdentifier ("g_param_spec_boxed"); + cspec.add_argument (new CCodeIdentifier (st.get_type_id ())); + } + } else { + cspec.call = new CCodeIdentifier ("g_param_spec_pointer"); + } + + var pflags = "G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB"; + if (prop.get_accessor != null) { + pflags = "%s%s".printf (pflags, " | G_PARAM_READABLE"); + } + if (prop.set_accessor != null) { + pflags = "%s%s".printf (pflags, " | G_PARAM_WRITABLE"); + if (prop.set_accessor.construction) { + if (prop.set_accessor.writable) { + pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT"); + } else { + pflags = "%s%s".printf (pflags, " | G_PARAM_CONSTRUCT_ONLY"); + } + } + } + cspec.add_argument (new CCodeConstant (pflags)); + + return cspec; + } + public override void generate_interface_declaration (Interface iface, CCodeDeclarationSpace decl_space) { if (decl_space.add_symbol_declaration (iface, iface.get_cname ())) { return;