]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Prepare support for generic delegates
authorJürg Billeter <j@bitron.ch>
Sat, 3 Jul 2010 07:28:33 +0000 (09:28 +0200)
committerJürg Billeter <j@bitron.ch>
Sat, 3 Jul 2010 10:47:58 +0000 (12:47 +0200)
vala/valaassignment.vala
vala/valacodewriter.vala
vala/valadelegate.vala
vala/valadelegatetype.vala
vala/valalambdaexpression.vala
vala/valalocalvariable.vala
vala/valamethodcall.vala
vala/valamethodtype.vala
vala/valasemanticanalyzer.vala

index 575ff966fd8a1e6c29f8e292d355e2318407bd24..7cb5b1f2520529f4211d924c9dfb7228594d64c7 100644 (file)
@@ -331,7 +331,7 @@ public class Vala.Assignment : Expression {
                                        var cb = dt.delegate_symbol;
 
                                        /* check whether method matches callback type */
-                                       if (!cb.matches_method (m)) {
+                                       if (!cb.matches_method (m, dt)) {
                                                error = true;
                                                Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
                                                return false;
@@ -353,7 +353,7 @@ public class Vala.Assignment : Expression {
                                        var cb = dt.delegate_symbol;
 
                                        /* check whether method matches callback type */
-                                       if (!cb.matches_method (m)) {
+                                       if (!cb.matches_method (m, dt)) {
                                                f.error = true;
                                                Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
                                                return false;
index e27b981dd5ecb641b35f553e785a2357a0dc230f..22d9d4ee1d73db2b9140370951563f36b8805600 100644 (file)
@@ -887,7 +887,22 @@ public class Vala.CodeWriter : CodeVisitor {
                
                write_string (" ");
                write_identifier (cb.name);
-               
+
+               var type_params = cb.get_type_parameters ();
+               if (type_params.size > 0) {
+                       write_string ("<");
+                       bool first = true;
+                       foreach (TypeParameter type_param in type_params) {
+                               if (first) {
+                                       first = false;
+                               } else {
+                                       write_string (",");
+                               }
+                               write_identifier (type_param.name);
+                       }
+                       write_string (">");
+               }
+
                write_string (" ");
                
                write_params (cb.get_parameters ());
index 6952409953d96136650b414e09a7cf4b623b14bb..85ada07ccb3dd85892a059fdfdb3c462e57f2fb1 100644 (file)
@@ -108,7 +108,22 @@ public class Vala.Delegate : TypeSymbol {
                type_parameters.add (p);
                scope.add (p.name, p);
        }
-       
+
+       public List<TypeParameter> get_type_parameters () {
+               return type_parameters;
+       }
+
+       public override int get_type_parameter_index (string name) {
+               int i = 0;
+               foreach (TypeParameter parameter in type_parameters) {
+                       if (parameter.name == name) {
+                               return i;
+                       }
+                       i++;
+               }
+               return -1;
+       }
+
        /**
         * Appends paramater to this callback function.
         *
@@ -141,9 +156,9 @@ public class Vala.Delegate : TypeSymbol {
         * @param m a method
         * @return  true if the specified method is compatible to this callback
         */
-       public bool matches_method (Method m) {
+       public bool matches_method (Method m, DataType dt) {
                // method is allowed to ensure stricter return type (stronger postcondition)
-               if (!m.return_type.stricter (return_type)) {
+               if (!m.return_type.stricter (return_type.get_actual_type (dt, null, this))) {
                        return false;
                }
                
@@ -179,7 +194,7 @@ public class Vala.Delegate : TypeSymbol {
 
                        // method is allowed to accept arguments of looser types (weaker precondition)
                        var method_param = method_params_it.get ();
-                       if (!param.parameter_type.stricter (method_param.parameter_type)) {
+                       if (!param.parameter_type.get_actual_type (dt, null, this).stricter (method_param.parameter_type)) {
                                return false;
                        }
                }
index 15dc2c3dde8ca7da935abc6a3f33a2a95f866763..5e4938503b4019778f343b4f60fdab0676209334 100644 (file)
@@ -1,6 +1,6 @@
 /* valadelegatetype.vala
  *
- * Copyright (C) 2007-2009  Jürg Billeter
+ * Copyright (C) 2007-2010  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
@@ -48,6 +48,24 @@ public class Vala.DelegateType : DataType {
 
        public override string to_qualified_string (Scope? scope) {
                string s = delegate_symbol.get_full_name ();
+
+               var type_args = get_type_arguments ();
+               if (type_args.size > 0) {
+                       s += "<";
+                       bool first = true;
+                       foreach (DataType type_arg in type_args) {
+                               if (!first) {
+                                       s += ",";
+                               } else {
+                                       first = false;
+                               }
+                               if (!type_arg.value_owned) {
+                                       s += "weak ";
+                               }
+                               s += type_arg.to_qualified_string (scope);
+                       }
+                       s += ">";
+               }
                if (nullable) {
                        s += "?";
                }
index 4bc618ff130e01a34075ef462f8245be2b1f007e..086b36f31a21c01ec92295aa1e68985ccd176931 100644 (file)
@@ -181,7 +181,8 @@ public class Vala.LambdaExpression : Expression {
                        }
 
                        string lambda_param = lambda_param_it.get ();
-                       var param = new FormalParameter (lambda_param, cb_param.parameter_type);
+                       var param_type = cb_param.parameter_type.get_actual_type (target_type, null, this);
+                       var param = new FormalParameter (lambda_param, param_type);
                        method.add_parameter (param);
                }
 
index f0450340a0f2dd65ca2761e180c53e5925b1a212..f252ceeac9ff68e35084e2559da7b6a542ffc857 100644 (file)
@@ -168,7 +168,7 @@ public class Vala.LocalVariable : Symbol {
                                        var cb = dt.delegate_symbol;
 
                                        /* check whether method matches callback type */
-                                       if (!cb.matches_method (m)) {
+                                       if (!cb.matches_method (m, dt)) {
                                                error = true;
                                                Report.error (source_reference, "declaration of method `%s' doesn't match declaration of callback `%s'".printf (m.get_full_name (), cb.get_full_name ()));
                                                return false;
index 8f9940f5a4a5e6492f502be80a4b18203eff4a49..f4fa66cd93495dae114ed6f435eb80e3676fd5b5 100644 (file)
@@ -144,7 +144,10 @@ public class Vala.MethodCall : Expression {
                // type of target object
                DataType target_object_type = null;
 
-               if (call is MemberAccess) {
+               if (call.value_type is DelegateType) {
+                       // delegate invocation, resolve generic types relative to delegate
+                       target_object_type = call.value_type;
+               } else if (call is MemberAccess) {
                        var ma = (MemberAccess) call;
                        if (ma.prototype_access) {
                                error = true;
index fe69e6ab49847c8eca3315bfa34ae3a1bd95c9f1..a2ad6d4c097ff37de429ba434aa2324780a95bd3 100644 (file)
@@ -55,7 +55,7 @@ public class Vala.MethodType : DataType {
                        return false;
                }
                
-               return dt.delegate_symbol.matches_method (method_symbol);
+               return dt.delegate_symbol.matches_method (method_symbol, dt);
        }
 
        public override string to_qualified_string (Scope? scope) {
index 70685dc5afa6cf26531683df9a9ecbf1c1d0ee4c..c2eb9c7648c3c7967a984c4e10e94536dcfcfc23 100644 (file)
@@ -613,7 +613,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                }
 
-               if (instance_type.data_type == type_symbol) {
+               if (instance_type is DelegateType && ((DelegateType) instance_type).delegate_symbol == type_symbol) {
+                       return instance_type;
+               } else if (instance_type.data_type == type_symbol) {
                        return instance_type;
                }
 
@@ -687,7 +689,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                                assert (instance_type != null);
 
-                               int param_index = instance_type.data_type.get_type_parameter_index (generic_type.type_parameter.name);
+                               int param_index;
+                               if (instance_type is DelegateType) {
+                                       param_index = ((DelegateType) instance_type).delegate_symbol.get_type_parameter_index (generic_type.type_parameter.name);
+                               } else {
+                                       param_index = instance_type.data_type.get_type_parameter_index (generic_type.type_parameter.name);
+                               }
                                if (param_index == -1) {
                                        Report.error (node_reference.source_reference, "internal error: unknown type parameter %s".printf (generic_type.type_parameter.name));
                                        node_reference.error = true;
@@ -776,7 +783,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                }
 
-               init.initializer.target_type = member_type;
+               init.initializer.formal_target_type = member_type;
+               init.initializer.target_type = init.initializer.formal_target_type.get_actual_type (type, null, init);;
 
                init.check (this);