support classes without base class
authorJuerg Billeter <j@bitron.ch>
Thu, 30 Aug 2007 13:45:05 +0000 (13:45 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Thu, 30 Aug 2007 13:45:05 +0000 (13:45 +0000)
2007-08-30  Juerg Billeter  <j@bitron.ch>

* 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
gobject/valacodegenerator.vala
gobject/valacodegeneratorclass.vala
gobject/valacodegeneratormethod.vala
vala/valaclass.vala
vala/valasemanticanalyzer.vala
vapi/glib-2.0.vala

index f799eba..9f3feaa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2007-08-30  Jürg Billeter  <j@bitron.ch>
 
+       * 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  <j@bitron.ch>
+
        * vala/valasymbolresolver.vala, vala/valasemanticanalyzer.vala,
          gobject/valacodegenerator.vala, gobject/valacodegeneratorclass.vala:
          don't implicitly derive from GLib.Object in preparation for a more
index fe8086a..54d6ef2 100644 (file)
@@ -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));
index f911a04..3ddd5fa 100644 (file)
@@ -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;
index f841544..317a1ab 100644 (file)
@@ -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);
        }
        
index cf4f35e..71c1782 100644 (file)
@@ -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;
                }
index 82b4cf6..cadc9ea 100644 (file)
@@ -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) {
index 6769755..e8ff280 100644 (file)
@@ -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 ();