From: Jürg Billeter Date: Tue, 16 Dec 2008 21:14:45 +0000 (+0000) Subject: Add support for private class fields, patch by Sebastian Dröge, fixes bug X-Git-Tag: VALA_0_5_3~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16bac3b7ea02525a81c81645e407ffb9d19c8212;p=thirdparty%2Fvala.git Add support for private class fields, patch by Sebastian Dröge, fixes bug 2008-12-16 Jürg Billeter * vala/valaclass.vala: * gobject/valaccodebasemodule.vala: * gobject/valaccodememberaccessmodule.vala: * gobject/valaclassregisterfunction.vala: * gobject/valagobjectmodule.vala: * gobject/valainterfaceregisterfunction.vala: * gobject/valatyperegisterfunction.vala: Add support for private class fields, patch by Sebastian Dröge, fixes bug 561469 svn path=/trunk/; revision=2187 --- diff --git a/ChangeLog b/ChangeLog index 079d561fd..2a75d9b62 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2008-12-16 Jürg Billeter + + * vala/valaclass.vala: + * gobject/valaccodebasemodule.vala: + * gobject/valaccodememberaccessmodule.vala: + * gobject/valaclassregisterfunction.vala: + * gobject/valagobjectmodule.vala: + * gobject/valainterfaceregisterfunction.vala: + * gobject/valatyperegisterfunction.vala: + + Add support for private class fields, patch by Sebastian Dröge, + fixes bug 561469 + 2008-12-16 Jürg Billeter * gobject/valaccodebasemodule.vala: diff --git a/gobject/valaccodebasemodule.vala b/gobject/valaccodebasemodule.vala index b94c76d7c..981b0f186 100644 --- a/gobject/valaccodebasemodule.vala +++ b/gobject/valaccodebasemodule.vala @@ -52,6 +52,8 @@ public class Vala.CCodeBaseModule : CCodeModule { public CCodeFragment source_signal_marshaller_declaration; public CCodeFragment source_type_member_definition; public CCodeFragment class_init_fragment; + public CCodeFragment base_init_fragment; + public CCodeFragment base_finalize_fragment; public CCodeFragment instance_init_fragment; public CCodeFragment instance_finalize_fragment; public CCodeFragment source_signal_marshaller_definition; @@ -61,6 +63,7 @@ public class Vala.CCodeBaseModule : CCodeModule { public CCodeStruct instance_struct; public CCodeStruct type_struct; public CCodeStruct instance_priv_struct; + public CCodeStruct type_priv_struct; public CCodeEnum prop_enum; public CCodeEnum cenum; public CCodeFunction function; @@ -837,7 +840,8 @@ public class Vala.CCodeBaseModule : CCodeModule { lhs = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), f.get_cname ()); } } else if (f.binding == MemberBinding.CLASS) { - st = type_struct; + st = type_priv_struct; + lhs = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv"), f.get_cname ()); } else { var cdecl = new CCodeDeclaration (field_ctype); var var_decl = new CCodeVariableDeclarator (f.get_cname ()); diff --git a/gobject/valaccodememberaccessmodule.vala b/gobject/valaccodememberaccessmodule.vala index 8a509f1c7..b6391b3da 100644 --- a/gobject/valaccodememberaccessmodule.vala +++ b/gobject/valaccodememberaccessmodule.vala @@ -129,7 +129,13 @@ public class Vala.CCodeMemberAccessModule : CCodeControlFlowModule { klass = k; } cast.add_argument (klass); - expr.ccodenode = new CCodeMemberAccess.pointer (cast, f.get_cname ()); + + if (f.access == SymbolAccessibility.PRIVATE) { + expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (cast, "priv"), f.get_cname ()); + } else { + expr.ccodenode = new CCodeMemberAccess.pointer (cast, f.get_cname ()); + } + } else { expr.ccodenode = new CCodeIdentifier (f.get_cname ()); } diff --git a/gobject/valaclassregisterfunction.vala b/gobject/valaclassregisterfunction.vala index 966aaa8f8..adc9a02b3 100644 --- a/gobject/valaclassregisterfunction.vala +++ b/gobject/valaclassregisterfunction.vala @@ -51,13 +51,21 @@ public class Vala.ClassRegisterFunction : TypeRegisterFunction { } public override string get_base_init_func_name () { - if (class_reference.class_constructor != null) { + if (class_reference.class_constructor != null || class_reference.has_class_private_fields) { return "%s_base_init".printf (class_reference.get_lower_case_cname (null)); } else { return "NULL"; } } + public override string get_base_finalize_func_name () { + if (class_reference.has_class_private_fields) { + return "%s_base_finalize".printf (class_reference.get_lower_case_cname (null)); + } else { + return "NULL"; + } + } + public override string get_class_init_func_name () { return "%s_class_init".printf (class_reference.get_lower_case_cname (null)); } diff --git a/gobject/valagobjectmodule.vala b/gobject/valagobjectmodule.vala index 8b8432b5f..f9efce04f 100644 --- a/gobject/valagobjectmodule.vala +++ b/gobject/valagobjectmodule.vala @@ -39,8 +39,11 @@ public class Vala.GObjectModule : GTypeModule { var old_param_spec_struct = param_spec_struct; var old_type_struct = type_struct; var old_instance_priv_struct = instance_priv_struct; + var old_type_priv_struct = type_priv_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_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; @@ -61,9 +64,12 @@ public class Vala.GObjectModule : GTypeModule { instance_struct = new CCodeStruct ("_%s".printf (cl.get_cname ())); type_struct = new CCodeStruct ("_%sClass".printf (cl.get_cname ())); instance_priv_struct = new CCodeStruct ("_%sPrivate".printf (cl.get_cname ())); + type_priv_struct = new CCodeStruct ("_%sClassPrivate".printf (cl.get_cname ())); prop_enum = new CCodeEnum (); prop_enum.add_value (new CCodeEnumValue ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)))); class_init_fragment = new CCodeFragment (); + base_init_fragment = new CCodeFragment (); + base_finalize_fragment = new CCodeFragment (); instance_init_fragment = new CCodeFragment (); instance_finalize_fragment = new CCodeFragment (); @@ -122,14 +128,23 @@ public class Vala.GObjectModule : GTypeModule { decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_struct.name), new CCodeVariableDeclarator ("%sClass".printf (cl.get_cname ())))); } decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_priv_struct.name), new CCodeVariableDeclarator ("%sPrivate".printf (cl.get_cname ())))); + if (cl.has_class_private_fields) { + decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (type_priv_struct.name), new CCodeVariableDeclarator ("%sClassPrivate".printf (cl.get_cname ())))); + } instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); if (is_fundamental) { type_struct.add_field ("GTypeClass", "parent_class"); - type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ())); } else { type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent_class"); } + if (cl.has_class_private_fields) { + type_struct.add_field ("%sClassPrivate *".printf (cl.get_cname ()), "priv"); + } + + if (is_fundamental) { + type_struct.add_field ("void", "(*finalize) (%s *self)".printf (cl.get_cname ())); + } } if (cl.source_reference.comment != null) { @@ -145,6 +160,10 @@ public class Vala.GObjectModule : GTypeModule { var macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_type_id (), cl.get_cname ()); source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); } + + if (cl.has_class_private_fields) { + source_type_member_declaration.append (type_priv_struct); + } source_type_member_declaration.append (prop_enum); } @@ -181,8 +200,17 @@ public class Vala.GObjectModule : GTypeModule { 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.has_class_private_fields) { + add_base_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); @@ -313,8 +341,11 @@ public class Vala.GObjectModule : GTypeModule { param_spec_struct = old_param_spec_struct; type_struct = old_type_struct; instance_priv_struct = old_instance_priv_struct; + type_priv_struct = old_type_priv_struct; prop_enum = old_prop_enum; class_init_fragment = old_class_init_fragment; + base_init_fragment = old_base_init_fragment; + base_finalize_fragment = old_base_finalize_fragment; instance_init_fragment = old_instance_init_fragment; instance_finalize_fragment = old_instance_finalize_fragment; } @@ -682,6 +713,53 @@ public class Vala.GObjectModule : GTypeModule { 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); + + var 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_include_directives.append (new CCodeIncludeDirective ("string.h")); + + var iftrue = new CCodeBlock (); + ccall = new CCodeFunctionCall (new CCodeIdentifier ("memcpy")); + ccall.add_argument (new CCodeIdentifier ("priv")); + ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv")); + ccall.add_argument (new CCodeIdentifier ("sizeof (%sClassPrivate)".printf(cl.get_cname()))); + iftrue.add_statement (new CCodeExpressionStatement (ccall)); + + block.add_statement (new CCodeIfStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv"), iftrue)); + + block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv"), new CCodeIdentifier ("priv")))); + + + init_block.add_statement (block); + + ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free")); + ccall.add_argument (new CCodeIdentifier ("%sClassPrivate".printf (cl.get_cname ()))); + ccall.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv")); + base_finalize_fragment.append (new CCodeExpressionStatement (ccall)); + base_finalize_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("klass"), "priv"), new CCodeIdentifier ("NULL")))); + } + + 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 ()))); @@ -790,9 +868,15 @@ public class Vala.GObjectModule : GTypeModule { if (field.binding != MemberBinding.CLASS || field.initializer == null) { continue; } - CCodeExpression left = new CCodeMemberAccess (new CCodeIdentifier ("klass"), - field.get_cname (), true); - CCodeExpression right = (CCodeExpression)field.initializer.ccodenode; + + CCodeExpression left; + + if (field.access == SymbolAccessibility.PRIVATE) { + left = new CCodeMemberAccess (new CCodeMemberAccess (new CCodeIdentifier ("klass"), "priv", true), 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)); } @@ -1072,7 +1156,22 @@ public class Vala.GObjectModule : GTypeModule { source_type_member_definition.append (instance_init); } - + + 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_type_member_declaration.append (function.copy ()); + + var cblock = new CCodeBlock (); + + 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; @@ -1602,25 +1701,16 @@ public class Vala.GObjectModule : GTypeModule { } else if (c.binding == MemberBinding.CLASS) { // class constructor - var base_init = new CCodeFunction ("%s_base_init".printf (cl.get_lower_case_cname (null)), "void"); - base_init.add_parameter (new CCodeFormalParameter ("klass", "%sClass *".printf (cl.get_cname ()))); - base_init.modifiers = CCodeModifiers.STATIC; - - source_type_member_declaration.append (base_init.copy ()); - - var block = (CCodeBlock) c.body.ccodenode; if (current_method_inner_error) { /* always separate error parameter and inner_error local variable * as error may be set to NULL but we're always interested in inner errors */ var cdecl = new CCodeDeclaration ("GError *"); cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("inner_error", new CCodeConstant ("NULL"))); - block.prepend_statement (cdecl); + base_init_fragment.append (cdecl); } - base_init.block = block; - - source_type_member_definition.append (base_init); + base_init_fragment.append (c.body.ccodenode); } else if (c.binding == MemberBinding.STATIC) { // static class constructor // add to class_init diff --git a/gobject/valainterfaceregisterfunction.vala b/gobject/valainterfaceregisterfunction.vala index 8e9ffb68c..306aa3d8c 100644 --- a/gobject/valainterfaceregisterfunction.vala +++ b/gobject/valainterfaceregisterfunction.vala @@ -48,11 +48,15 @@ public class Vala.InterfaceRegisterFunction : TypeRegisterFunction { public override string get_base_init_func_name () { return "%s_base_init".printf (interface_reference.get_lower_case_cname (null)); } + + public override string get_base_finalize_func_name () { + return "NULL"; + } public override string get_class_init_func_name () { return "NULL"; } - + public override string get_instance_struct_size () { return "0"; } diff --git a/gobject/valatyperegisterfunction.vala b/gobject/valatyperegisterfunction.vala index 652eda639..db813865c 100644 --- a/gobject/valatyperegisterfunction.vala +++ b/gobject/valatyperegisterfunction.vala @@ -1,6 +1,6 @@ /* valatyperegisterfunction.vala * - * Copyright (C) 2006-2007 Jürg Billeter + * Copyright (C) 2006-2008 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -108,7 +108,7 @@ public abstract class Vala.TypeRegisterFunction { if (get_type_declaration () is ObjectTypeSymbol) { var ctypedecl = new CCodeDeclaration ("const GTypeInfo"); ctypedecl.modifiers = CCodeModifiers.STATIC; - ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) NULL, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name)))); + ctypedecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("g_define_type_info", new CCodeConstant ("{ sizeof (%s), (GBaseInitFunc) %s, (GBaseFinalizeFunc) %s, (GClassInitFunc) %s, (GClassFinalizeFunc) NULL, NULL, %s, 0, (GInstanceInitFunc) %s, %s }".printf (get_type_struct_name (), get_base_init_func_name (), get_base_finalize_func_name (), get_class_init_func_name (), get_instance_struct_size (), get_instance_init_func_name (), type_value_table_decl_name)))); type_init.add_statement (ctypedecl); if (fundamental) { var ctypefundamentaldecl = new CCodeDeclaration ("const GTypeFundamentalInfo"); @@ -208,7 +208,6 @@ public abstract class Vala.TypeRegisterFunction { public virtual string get_type_struct_name () { assert_not_reached (); } - /** * Returns the name of the base_init function in C code. * @@ -218,6 +217,15 @@ public abstract class Vala.TypeRegisterFunction { assert_not_reached (); } + /** + * Returns the name of the base_finalize function in C code. + * + * @return C function name + */ + public virtual string get_base_finalize_func_name () { + assert_not_reached (); + } + /** * Returns the name of the class_init function in C code. * diff --git a/vala/valaclass.vala b/vala/valaclass.vala index 3bf09e6e4..87c7da499 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -81,6 +81,11 @@ public class Vala.Class : ObjectTypeSymbol { * Specifies whether this class has private fields. */ public bool has_private_fields { get; private set; } + + /** + * Specifies whether this class has class fields. + */ + public bool has_class_private_fields { get; private set; } private string cname; private string const_cname; @@ -247,6 +252,8 @@ public class Vala.Class : ObjectTypeSymbol { fields.add (f); if (f.access == SymbolAccessibility.PRIVATE && f.binding == MemberBinding.INSTANCE) { has_private_fields = true; + } else if (f.access == SymbolAccessibility.PRIVATE && f.binding == MemberBinding.CLASS) { + has_class_private_fields = true; } scope.add (f.name, f); }