rename base_types of interfaces to prerequisites to follow GObject
authorJürg Billeter <j@bitron.ch>
Sun, 4 Mar 2007 18:45:02 +0000 (18:45 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sun, 4 Mar 2007 18:45:02 +0000 (18:45 +0000)
2007-03-04  Jürg Billeter  <j@bitron.ch>

* vala/parser.y, vala/valainterface.vala,
  vala/valasemanticanalyzer.vala: rename base_types of interfaces to
  prerequisites to follow GObject terminology
* vala/valamethod.vala, vala/valasemanticanalyzer.vala,
  vala/valacodegenerator.vala: move interface usage part from
  base_method to base_interface_method property
* vala/valasemanticanalyzer.vala: don't require interface
  implementations to specify override
* vala/valacodegenerator.vala: support base access in interface
  implementations
* tests/test-017.vala: remove override in method declaration

svn path=/trunk/; revision=218

vala/ChangeLog
vala/tests/test-017.vala
vala/vala/parser.y
vala/vala/valacodegenerator.vala
vala/vala/valainterface.vala
vala/vala/valamethod.vala
vala/vala/valasemanticanalyzer.vala

index 1b9a08b..b78a766 100644 (file)
@@ -1,5 +1,19 @@
 2007-03-04  Jürg Billeter  <j@bitron.ch>
 
+       * vala/parser.y, vala/valainterface.vala,
+         vala/valasemanticanalyzer.vala: rename base_types of interfaces to
+         prerequisites to follow GObject terminology
+       * vala/valamethod.vala, vala/valasemanticanalyzer.vala,
+         vala/valacodegenerator.vala: move interface usage part from
+         base_method to base_interface_method property
+       * vala/valasemanticanalyzer.vala: don't require interface
+         implementations to specify override
+       * vala/valacodegenerator.vala: support base access in interface
+         implementations
+       * tests/test-017.vala: remove override in method declaration
+
+2007-03-04  Jürg Billeter  <j@bitron.ch>
+
        * vala/valasemanticanalyzer.vala: support lambda expressions in
          constructors
        * tests/test-029.vala: remove extra printf argument
index d8fca85..58ba607 100644 (file)
@@ -5,7 +5,7 @@ interface Maman.Ibaz {
 }
 
 class Maman.Baz : Ibaz {
-       public override void do_action () {
+       public void do_action () {
                stdout.printf (" 2");
        }
 
index 974286d..635fe32 100644 (file)
@@ -2672,7 +2672,7 @@ interface_declaration
                if ($8 != NULL) {
                        GList *l;
                        for (l = $8; l != NULL; l = l->next) {
-                               vala_interface_add_base_type (current_interface, l->data);
+                               vala_interface_add_prerequisite (current_interface, l->data);
                                g_object_unref (l->data);
                        }
                        g_list_free ($8);
index b01e3a6..d887e14 100644 (file)
@@ -484,14 +484,10 @@ public class Vala.CodeGenerator : CodeVisitor {
                /* connect overridden methods */
                var methods = cl.get_methods ();
                foreach (Method m in methods) {
-                       if (!m.is_virtual && !m.overrides) {
+                       if (m.base_method == null) {
                                continue;
                        }
-                       
                        var base_type = m.base_method.symbol.parent_symbol.node;
-                       if (base_type is Interface) {
-                               continue;
-                       }
                        
                        var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (((Class) base_type).get_upper_case_cname (null))));
                        ccast.add_argument (new CCodeIdentifier ("klass"));
@@ -618,13 +614,26 @@ public class Vala.CodeGenerator : CodeVisitor {
                
                ref 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_type_member_declaration.append (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));
+
                var methods = cl.get_methods ();
                foreach (Method m in methods) {
-                       if (!m.overrides) {
+                       if (m.base_interface_method == null) {
                                continue;
                        }
-                       
-                       var base_type = m.base_method.symbol.parent_symbol.node;
+
+                       var base_type = m.base_interface_method.symbol.parent_symbol.node;
                        if (base_type != iface) {
                                continue;
                        }
@@ -1150,16 +1159,20 @@ public class Vala.CodeGenerator : CodeVisitor {
                if (m.instance) {
                        var this_type = new TypeReference ();
                        this_type.data_type = find_parent_type (m);
-                       if (!m.overrides) {
+                       if (m.base_interface_method != null) {
+                               var base_type = new TypeReference ();
+                               base_type.data_type = (DataType) m.base_interface_method.symbol.parent_symbol.node;
+                               instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
+                       } else if (m.overrides) {
+                               var base_type = new TypeReference ();
+                               base_type.data_type = (DataType) m.base_method.symbol.parent_symbol.node;
+                               instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
+                       } else {
                                if (m.instance_by_reference) {
                                        instance_param = new CCodeFormalParameter ("*self", this_type.get_cname ());
                                } else {
                                        instance_param = new CCodeFormalParameter ("self", this_type.get_cname ());
                                }
-                       } else {
-                               var base_type = new TypeReference ();
-                               base_type.data_type = (DataType) m.base_method.symbol.parent_symbol.node;
-                               instance_param = new CCodeFormalParameter ("base", base_type.get_cname ());
                        }
                        if (!m.instance_last) {
                                function.add_parameter (instance_param);
@@ -1207,7 +1220,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                /* real function declaration and definition not needed
                 * for abstract methods */
                if (!m.is_abstract) {
-                       if (m.access != MemberAccessibility.PRIVATE && !(m.is_virtual || m.overrides)) {
+                       if (m.access != MemberAccessibility.PRIVATE && m.base_method == null && m.base_interface_method == null) {
                                /* public methods need function declaration in
                                 * header file except virtual/overridden methods */
                                header_type_member_declaration.append (function.copy ());
@@ -1228,7 +1241,7 @@ public class Vala.CodeGenerator : CodeVisitor {
 
                                if (m.symbol.parent_symbol.node is Class) {
                                        var cl = (Class) m.symbol.parent_symbol.node;
-                                       if (m.overrides) {
+                                       if (m.overrides || m.base_interface_method != null) {
                                                var ccall = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
                                                ccall.add_argument (new CCodeIdentifier ("base"));
                                                
@@ -2562,19 +2575,29 @@ public class Vala.CodeGenerator : CodeVisitor {
                if (expr.symbol_reference.node is Method) {
                        var m = (Method) expr.symbol_reference.node;
                        
-                       if (expr.inner is BaseAccess && (m.is_virtual || m.overrides)) {
-                               var base_class = (Class) m.base_method.symbol.parent_symbol.node;
-                               var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
-                               vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
-                               
-                               expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
-                               return;
+                       if (expr.inner is BaseAccess) {
+                               if (m.base_interface_method != null) {
+                                       var base_iface = (Interface) m.base_interface_method.symbol.parent_symbol.node;
+                                       string parent_iface_var = "%s_%s_parent_iface".printf (current_class.get_lower_case_cname (null), base_iface.get_lower_case_cname (null));
+
+                                       expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeIdentifier (parent_iface_var), m.name);
+                                       return;
+                               } else if (m.base_method != null) {
+                                       var base_class = (Class) m.base_method.symbol.parent_symbol.node;
+                                       var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
+                                       vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
+                                       
+                                       expr.ccodenode = new CCodeMemberAccess.pointer (vcast, m.name);
+                                       return;
+                               }
                        }
                        
-                       if (!m.overrides) {
-                               expr.ccodenode = new CCodeIdentifier (m.get_cname ());
-                       } else {
+                       if (m.base_interface_method != null) {
+                               expr.ccodenode = new CCodeIdentifier (m.base_interface_method.get_cname ());
+                       } else if (m.base_method != null) {
                                expr.ccodenode = new CCodeIdentifier (m.base_method.get_cname ());
+                       } else {
+                               expr.ccodenode = new CCodeIdentifier (m.get_cname ());
                        }
                } else if (expr.symbol_reference.node is ArrayLengthField) {
                        expr.ccodenode = get_array_length_cexpression (expr.inner, 1);
@@ -2889,7 +2912,9 @@ public class Vala.CodeGenerator : CodeVisitor {
                ref CCodeExpression instance;
                if (m != null && m.instance) {
                        var base_method = m;
-                       if (m.overrides) {
+                       if (m.base_interface_method != null) {
+                               base_method = m.base_interface_method;
+                       } else if (m.base_method != null) {
                                base_method = m.base_method;
                        }
 
@@ -2897,7 +2922,7 @@ public class Vala.CodeGenerator : CodeVisitor {
                        if (ma.inner == null) {
                                instance = new CCodeIdentifier ("self");
                                /* require casts for overriden and inherited methods */
-                               req_cast = m.overrides || (m.symbol.parent_symbol != current_type_symbol);
+                               req_cast = m.overrides || m.base_interface_method != null || (m.symbol.parent_symbol != current_type_symbol);
                        } else {
                                instance = (CCodeExpression) ma.inner.ccodenode;
                                /* reqiure casts if the type of the used instance is
index 10079a0..30dc579 100644 (file)
@@ -28,7 +28,7 @@ using GLib;
 public class Vala.Interface : DataType {
        private List<TypeParameter> type_parameters;
        
-       private List<TypeReference> base_types;
+       private List<TypeReference> prerequisites;
 
        private List<Method> methods;
        private List<Property> properties;
@@ -62,13 +62,13 @@ public class Vala.Interface : DataType {
        }
 
        /**
-        * Adds the specified interface to the list of prerequisites of this
-        * interface.
+        * Adds the specified interface or class to the list of prerequisites of
+        * this interface.
         *
-        * @param type an interface reference
+        * @param type an interface or class reference
         */
-       public void add_base_type (TypeReference! type) {
-               base_types.append (type);
+       public void add_prerequisite (TypeReference! type) {
+               prerequisites.append (type);
        }
 
        /**
@@ -76,8 +76,8 @@ public class Vala.Interface : DataType {
         *
         * @return list of base types
         */
-       public ref List<weak TypeReference> get_base_types () {
-               return base_types.copy ();
+       public ref List<weak TypeReference> get_prerequisites () {
+               return prerequisites.copy ();
        }
        
        /**
@@ -182,7 +182,7 @@ public class Vala.Interface : DataType {
        public override void accept (CodeVisitor! visitor) {
                visitor.visit_begin_interface (this);
                
-               foreach (TypeReference type in base_types) {
+               foreach (TypeReference type in prerequisites) {
                        type.accept (visitor);
                }
 
@@ -222,9 +222,9 @@ public class Vala.Interface : DataType {
        }
 
        public override bool is_subtype_of (DataType! t) {
-               foreach (TypeReference base_type in base_types) {
-                       if (base_type.data_type == t ||
-                           base_type.data_type.is_subtype_of (t)) {
+               foreach (TypeReference prerequisite in prerequisites) {
+                       if (prerequisite.data_type == t ||
+                           prerequisite.data_type.is_subtype_of (t)) {
                                return true;
                        }
                }
index 31d755a..fd20e1e 100644 (file)
@@ -106,6 +106,11 @@ public class Vala.Method : Member, Invokable {
        public weak Method base_method { get; set; }
        
        /**
+        * Specifies the abstract interface method this method implements.
+        */
+       public Method base_interface_method { get; set; }
+       
+       /**
         * Specifies the generated `this' parameter for instance methods.
         */
        public FormalParameter this_parameter { get; set; }
@@ -219,7 +224,7 @@ public class Vala.Method : Member, Invokable {
         * @return the name to be used in C code
         */
        public ref string! get_real_cname () {
-               if (is_virtual || overrides) {
+               if (base_method != null || base_interface_method != null) {
                        var parent = (Class) symbol.parent_symbol.node;
                        return "%s_real_%s".printf (parent.get_lower_case_cname (null), name);
                } else {
index 0fc5c93..16942f6 100644 (file)
@@ -136,8 +136,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public override void visit_begin_interface (Interface! iface) {
                current_symbol = iface.symbol;
                
-               foreach (TypeReference base_type_reference in iface.get_base_types ()) {
-                       current_source_file.add_symbol_dependency (base_type_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL);
+               foreach (TypeReference prerequisite_reference in iface.get_prerequisites ()) {
+                       current_source_file.add_symbol_dependency (prerequisite_reference.data_type.symbol, SourceFileDependencyType.HEADER_FULL);
                }
        }
 
@@ -178,8 +178,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                }
        }
 
-       private void find_base_method (Method! m, DataType! datatype) {
-               var sym = datatype.symbol.lookup (m.name);
+       private void find_base_class_method (Method! m, Class! cl) {
+               var sym = cl.symbol.lookup (m.name);
                if (sym != null && sym.node is Method) {
                        var base_method = (Method) sym.node;
                        if (base_method.is_abstract || base_method.is_virtual) {
@@ -194,21 +194,28 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                }
 
+               if (cl.base_class != null) {
+                       find_base_class_method (m, cl.base_class);
+               }
+       }
+
+       private void find_base_interface_method (Method! m, Class! cl) {
                // FIXME report error if multiple possible base methods are found
-               if (datatype is Class) {
-                       var cl = (Class) datatype;
-                       foreach (TypeReference type in cl.get_base_types ()) {
-                               find_base_method (m, type.data_type);
-                               if (m.base_method != null) {
-                                       return;
-                               }
-                       }
-               } else {
-                       var iface = (Interface) datatype;
-                       foreach (TypeReference type in iface.get_base_types ()) {
-                               find_base_method (m, type.data_type);
-                               if (m.base_method != null) {
-                                       return;
+               foreach (TypeReference type in cl.get_base_types ()) {
+                       if (type.data_type is Interface) {
+                               var sym = type.data_type.symbol.lookup (m.name);
+                               if (sym != null && sym.node is Method) {
+                                       var base_method = (Method) sym.node;
+                                       if (base_method.is_abstract) {
+                                               if (!m.equals (base_method)) {
+                                                       m.error = true;
+                                                       Report.error (m.source_reference, "Return type and/or parameters of overriding method `%s' do not match overridden method `%s'.".printf (m.symbol.get_full_name (), base_method.symbol.get_full_name ()));
+                                                       return;
+                                               }
+                                               
+                                               m.base_interface_method = base_method;
+                                               return;
+                                       }
                                }
                        }
                }
@@ -225,13 +232,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        current_return_type = up_method.return_type;
                }
                
-               if (m.is_virtual || m.overrides) {
-                       if (current_symbol.node is Class) {
-                               find_base_method (m, (Class) current_symbol.node);
-                               if (m.base_method == null) {
-                                       Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ()));
+               if (current_symbol.node is Class) {
+                       if (!(m is CreationMethod)) {
+                               find_base_interface_method (m, (Class) current_symbol.node);
+                               if (m.is_virtual || m.overrides) {
+                                       find_base_class_method (m, (Class) current_symbol.node);
+                                       if (m.base_method == null) {
+                                               // FIXME remove check after interface override transition
+                                               if (m.base_interface_method == null) {
+                                                       Report.error (m.source_reference, "%s: no suitable method found to override".printf (m.symbol.get_full_name ()));
+                                               }
+                                       }
                                }
-                       } else if (current_symbol.node is Struct) {
+                       }
+               } else if (current_symbol.node is Struct) {
+                       if (m.is_abstract || m.is_virtual || m.overrides) {
                                Report.error (m.source_reference, "A struct member `%s' cannot be marked as override, virtual, or abstract".printf (m.symbol.get_full_name ()));
                                return;
                        }
@@ -785,8 +800,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                } else if (sym.node is Interface) {
                        var iface = (Interface) sym.node;
-                       foreach (TypeReference base_type in iface.get_base_types ()) {
-                               result = symbol_lookup_inherited (base_type.data_type.symbol, name);
+                       foreach (TypeReference prerequisite in iface.get_prerequisites ()) {
+                               result = symbol_lookup_inherited (prerequisite.data_type.symbol, name);
                                if (result != null) {
                                        return result;
                                }