From c390970c9b4ad29f44e9fe92d4440cc8cc0b9cf1 Mon Sep 17 00:00:00 2001 From: Juerg Billeter Date: Thu, 30 Aug 2007 13:45:05 +0000 Subject: [PATCH] support classes without base class 2007-08-30 Juerg Billeter * vala/valaclass.vala, vala/valasemanticanalyzer.vala, gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala, gobject/valacodegeneratormethod.vala, vapi/glib-2.0.vala: support classes without base class svn path=/trunk/; revision=537 --- ChangeLog | 7 +++ gobject/valacodegenerator.vala | 4 +- gobject/valacodegeneratorclass.vala | 82 +++++++++++++++++++++++++----------- gobject/valacodegeneratormethod.vala | 28 ++++++++++-- vala/valaclass.vala | 59 +++++++++++++------------- vala/valasemanticanalyzer.vala | 15 ------- vapi/glib-2.0.vala | 2 +- 7 files changed, 122 insertions(+), 75 deletions(-) diff --git a/ChangeLog b/ChangeLog index f799eba..9f3feaa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2007-08-30 Jürg Billeter + * vala/valaclass.vala, vala/valasemanticanalyzer.vala, + gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala, + gobject/valacodegeneratormethod.vala, vapi/glib-2.0.vala: support + classes without base class + +2007-08-30 Jürg Billeter + * vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala, gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala: don't implicitly derive from GLib.Object in preparation for a more diff --git a/gobject/valacodegenerator.vala b/gobject/valacodegenerator.vala index fe8086a..54d6ef2 100644 --- a/gobject/valacodegenerator.vala +++ b/gobject/valacodegenerator.vala @@ -1005,7 +1005,7 @@ public class Vala.CodeGenerator : CodeVisitor { var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cvar, new CCodeConstant ("NULL")); if (type.data_type == null) { - if (!(current_type_symbol is Class)) { + if (!(current_type_symbol is Class) || !current_class.is_subtype_of (gobject_type)) { return new CCodeConstant ("NULL"); } @@ -2375,7 +2375,7 @@ public class Vala.CodeGenerator : CodeVisitor { var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); - if (expr.type_reference.data_type is Class) { + if (expr.type_reference.data_type is Class && expr.type_reference.data_type.is_subtype_of (gobject_type)) { foreach (TypeReference type_arg in expr.type_reference.get_type_arguments ()) { if (type_arg.takes_ownership) { ccall.add_argument (get_dup_func_expression (type_arg)); diff --git a/gobject/valacodegeneratorclass.vala b/gobject/valacodegeneratorclass.vala index f911a04..3ddd5fa 100644 --- a/gobject/valacodegeneratorclass.vala +++ b/gobject/valacodegeneratorclass.vala @@ -38,6 +38,8 @@ public class Vala.CodeGenerator { current_symbol = cl; current_type_symbol = cl; current_class = cl; + + bool is_gobject = cl.is_subtype_of (gobject_type); if (cl.get_cname().len () < 3) { cl.error = true; @@ -67,35 +69,40 @@ public class Vala.CodeGenerator { decl_frag = source_type_member_declaration; def_frag = source_type_member_declaration; } - - decl_frag.append (new CCodeNewline ()); + var macro = "(%s_get_type ())".printf (cl.get_lower_case_cname (null)); - decl_frag.append (new CCodeMacroReplacement (cl.get_upper_case_cname ("TYPE_"), macro)); + if (is_gobject) { + decl_frag.append (new CCodeNewline ()); + decl_frag.append (new CCodeMacroReplacement (cl.get_upper_case_cname ("TYPE_"), macro)); - macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro)); + macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname (null)), macro)); - macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro)); + macro = "(G_TYPE_CHECK_CLASS_CAST ((klass), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname (null)), macro)); - macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname ("IS_")), macro)); + macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (cl.get_upper_case_cname ("TYPE_")); + decl_frag.append (new CCodeMacroReplacement ("%s(obj)".printf (cl.get_upper_case_cname ("IS_")), macro)); - macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_")); - decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), macro)); + macro = "(G_TYPE_CHECK_CLASS_TYPE ((klass), %s))".printf (cl.get_upper_case_cname ("TYPE_")); + decl_frag.append (new CCodeMacroReplacement ("%s_CLASS(klass)".printf (cl.get_upper_case_cname ("IS_")), macro)); - macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro)); - decl_frag.append (new CCodeNewline ()); + macro = "(G_TYPE_INSTANCE_GET_CLASS ((obj), %s, %sClass))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + decl_frag.append (new CCodeMacroReplacement ("%s_GET_CLASS(obj)".printf (cl.get_upper_case_cname (null)), macro)); + decl_frag.append (new CCodeNewline ()); + } if (cl.source_reference.file.cycle == null) { decl_frag.append (new CCodeTypeDefinition ("struct %s".printf (instance_struct.name), new CCodeVariableDeclarator (cl.get_cname ()))); - 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.is_subtype_of (gobject_type)) { + if (is_gobject) { + if (cl.source_reference.file.cycle == null) { + 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 ())))); + instance_struct.add_field (cl.base_class.get_cname (), "parent"); instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv"); type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent"); @@ -105,18 +112,21 @@ public class Vala.CodeGenerator { def_frag.append (new CCodeComment (cl.source_reference.comment)); } def_frag.append (instance_struct); - def_frag.append (type_struct); - /* 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) { - source_type_member_declaration.append (instance_priv_struct); - macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); - source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); + + if (is_gobject) { + def_frag.append (type_struct); + /* 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) { + source_type_member_declaration.append (instance_priv_struct); + macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ()); + source_type_member_declaration.append (new CCodeMacroReplacement ("%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), macro)); + } + source_type_member_declaration.append (prop_enum); } - source_type_member_declaration.append (prop_enum); cl.accept_children (this); - if (cl.is_subtype_of (gobject_type)) { + if (is_gobject) { if (class_has_readable_properties (cl) || cl.get_type_parameters ().size > 0) { add_get_property_function (cl); } @@ -151,6 +161,28 @@ public class Vala.CodeGenerator { register_call.add_argument (new CCodeIdentifier (module_init_param_name)); module_init_fragment.append (new CCodeExpressionStatement (register_call)); } + } else if (cl.default_construction_method != null) { + var function = new CCodeFunction (cl.get_lower_case_cprefix () + "free", "void"); + if (cl.access == MemberAccessibility.PRIVATE) { + function.modifiers = CCodeModifiers.STATIC; + } + + function.add_parameter (new CCodeFormalParameter ("self", cl.get_cname () + "*")); + + decl_frag.append (function.copy ()); + + var cblock = new CCodeBlock (); + + cblock.add_statement (instance_dispose_fragment); + + 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; + + def_frag.append (function); } current_type_symbol = old_type_symbol; diff --git a/gobject/valacodegeneratormethod.vala b/gobject/valacodegeneratormethod.vala index f841544..317a1ab 100644 --- a/gobject/valacodegeneratormethod.vala +++ b/gobject/valacodegeneratormethod.vala @@ -41,7 +41,7 @@ public class Vala.CodeGenerator { m.accept_children (this); if (m is CreationMethod) { - if (current_type_symbol is Class && m.body != null) { + if (current_type_symbol is Class && current_class.is_subtype_of (gobject_type) && m.body != null) { var cblock = new CCodeBlock (); foreach (CodeNode stmt in m.body.get_statements ()) { @@ -127,7 +127,7 @@ public class Vala.CodeGenerator { } } - if (m is CreationMethod && current_type_symbol is Class) { + if (m is CreationMethod && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) { // memory management for generic types foreach (TypeParameter type_param in current_class.get_type_parameters ()) { function.add_parameter (new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc")); @@ -258,7 +258,7 @@ public class Vala.CodeGenerator { source_type_member_definition.append (function); if (m is CreationMethod) { - if (current_type_symbol is Class) { + if (current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) { int n_params = ((CreationMethod) m).n_construction_params; if (n_params > 0) { @@ -292,6 +292,13 @@ public class Vala.CodeGenerator { cassign = new CCodeAssignment (cmember, new CCodeIdentifier (func_name)); function.block.add_statement (new CCodeExpressionStatement (cassign)); } + } else if (current_type_symbol is Class) { + var cl = (Class) m.parent_symbol; + var cdecl = new CCodeDeclaration (cl.get_cname () + "*"); + var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_new0")); + ccall.add_argument (new CCodeIdentifier (cl.get_cname ())); + cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("self", ccall)); + cinit.append (cdecl); } else { var st = (Struct) m.parent_symbol; var cdecl = new CCodeDeclaration (st.get_cname () + "*"); @@ -520,6 +527,21 @@ public class Vala.CodeGenerator { } public override void visit_creation_method (CreationMethod! m) { + if (m.body != null && current_type_symbol is Class && current_class.is_subtype_of (gobject_type)) { + int n_params = 0; + foreach (Statement stmt in m.body.get_statements ()) { + if (!(stmt is ExpressionStatement) || ((ExpressionStatement) stmt).assigned_property () == null) { + m.error = true; + Report.error (stmt.source_reference, "class creation methods only allow property assignment statements"); + return; + } + if (((ExpressionStatement) stmt).assigned_property ().set_accessor.construction) { + n_params++; + } + } + m.n_construction_params = n_params; + } + visit_method (m); } diff --git a/vala/valaclass.vala b/vala/valaclass.vala index cf4f35e..71c1782 100644 --- a/vala/valaclass.vala +++ b/vala/valaclass.vala @@ -397,32 +397,33 @@ public class Vala.Class : DataType { if (a.has_argument ("ctype")) { if (a.get_string ("ctype") != "gobject") { is_gobject = false; - if (a.has_argument ("ref_function")) { - set_ref_function (a.get_string ("ref_function")); - } - if (a.has_argument ("unref_function")) { - set_unref_function (a.get_string ("unref_function")); - } - if (a.has_argument ("copy_function")) { - set_dup_function (a.get_string ("copy_function")); - } - if (a.has_argument ("free_function")) { - set_free_function (a.get_string ("free_function")); - } - if (a.has_argument ("type_id")) { - type_id = a.get_string ("type_id"); - } - if (a.has_argument ("marshaller_type_name")) { - marshaller_type_name = a.get_string ("marshaller_type_name"); - } - if (a.has_argument ("get_value_function")) { - get_value_function = a.get_string ("get_value_function"); - } - if (a.has_argument ("set_value_function")) { - set_value_function = a.get_string ("set_value_function"); - } } } + if (a.has_argument ("ref_function")) { + set_ref_function (a.get_string ("ref_function")); + } + if (a.has_argument ("unref_function")) { + set_unref_function (a.get_string ("unref_function")); + } + if (a.has_argument ("copy_function")) { + set_dup_function (a.get_string ("copy_function")); + } + if (a.has_argument ("free_function")) { + set_free_function (a.get_string ("free_function")); + } + if (a.has_argument ("type_id")) { + type_id = a.get_string ("type_id"); + } + if (a.has_argument ("marshaller_type_name")) { + marshaller_type_name = a.get_string ("marshaller_type_name"); + } + if (a.has_argument ("get_value_function")) { + get_value_function = a.get_string ("get_value_function"); + } + if (a.has_argument ("set_value_function")) { + set_value_function = a.get_string ("set_value_function"); + } + if (a.has_argument ("cname")) { set_cname (a.get_string ("cname")); } @@ -499,12 +500,12 @@ public class Vala.Class : DataType { } public override bool is_reference_counting () { - return is_gobject || (ref_function != null && unref_function != null); + return get_ref_function () != null; } public override string get_ref_function () { - if (is_gobject) { - return "g_object_ref"; + if (ref_function == null && base_class != null) { + return base_class.get_ref_function (); } else { return ref_function; } @@ -515,8 +516,8 @@ public class Vala.Class : DataType { } public override string get_unref_function () { - if (is_gobject) { - return "g_object_unref"; + if (unref_function == null && base_class != null) { + return base_class.get_unref_function (); } else { return unref_function; } diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 82b4cf6..cadc9ea 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -466,21 +466,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Report.error (m.source_reference, "The creation method `%s' cannot be marked as override, virtual, or abstract".printf (m.get_full_name ())); return; } - - if (m.body != null && current_class != null) { - int n_params = 0; - foreach (Statement stmt in m.body.get_statements ()) { - if (!(stmt is ExpressionStatement) || ((ExpressionStatement) stmt).assigned_property () == null) { - m.error = true; - Report.error (stmt.source_reference, "class creation methods only allow property assignment statements"); - return; - } - if (((ExpressionStatement) stmt).assigned_property ().set_accessor.construction) { - n_params++; - } - } - m.n_construction_params = n_params; - } } public override void visit_formal_parameter (FormalParameter! p) { diff --git a/vapi/glib-2.0.vala b/vapi/glib-2.0.vala index 6769755..e8ff280 100644 --- a/vapi/glib-2.0.vala +++ b/vapi/glib-2.0.vala @@ -627,7 +627,7 @@ namespace GLib { public static delegate void ObjectGetPropertyFunc (Object object, uint property_id, Value value, ParamSpec pspec); public static delegate void ObjectSetPropertyFunc (Object object, uint property_id, Value value, ParamSpec pspec); - [CCode (cheader_filename = "glib-object.h")] + [CCode (ref_function = "g_object_ref", unref_function = "g_object_unref", cheader_filename = "glib-object.h")] public class Object { [CCode (cname = "G_TYPE_FROM_INSTANCE")] public Type get_type (); -- 2.7.4