[vala] Prepare support for generic delegates



commit ac780b92d6b561f422e7935a8a9735464dc1540a
Author: Jürg Billeter <j bitron ch>
Date:   Sat Jul 3 09:28:33 2010 +0200

    Prepare support for generic delegates

 vala/valaassignment.vala       |    4 ++--
 vala/valacodewriter.vala       |   17 ++++++++++++++++-
 vala/valadelegate.vala         |   23 +++++++++++++++++++----
 vala/valadelegatetype.vala     |   20 +++++++++++++++++++-
 vala/valalambdaexpression.vala |    3 ++-
 vala/valalocalvariable.vala    |    2 +-
 vala/valamethodcall.vala       |    5 ++++-
 vala/valamethodtype.vala       |    2 +-
 vala/valasemanticanalyzer.vala |   14 +++++++++++---
 9 files changed, 75 insertions(+), 15 deletions(-)
---
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 575ff96..7cb5b1f 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -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;
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index e27b981..22d9d4e 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -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 ());
diff --git a/vala/valadelegate.vala b/vala/valadelegate.vala
index 6952409..85ada07 100644
--- a/vala/valadelegate.vala
+++ b/vala/valadelegate.vala
@@ -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;
 			}
 		}
diff --git a/vala/valadelegatetype.vala b/vala/valadelegatetype.vala
index 15dc2c3..5e49385 100644
--- a/vala/valadelegatetype.vala
+++ b/vala/valadelegatetype.vala
@@ -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 += "?";
 		}
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index 4bc618f..086b36f 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -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);
 		}
 
diff --git a/vala/valalocalvariable.vala b/vala/valalocalvariable.vala
index f045034..f252cee 100644
--- a/vala/valalocalvariable.vala
+++ b/vala/valalocalvariable.vala
@@ -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;
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 8f9940f..f4fa66c 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -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;
diff --git a/vala/valamethodtype.vala b/vala/valamethodtype.vala
index fe69e6a..a2ad6d4 100644
--- a/vala/valamethodtype.vala
+++ b/vala/valamethodtype.vala
@@ -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) {
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 70685dc..c2eb9c7 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -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);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]