[vala] Add initial support for static methods in generic types



commit 9460d48c8ae8e53b0189b06ec021db0a3b493578
Author: Jürg Billeter <j bitron ch>
Date:   Wed Jun 3 09:21:36 2009 +0200

    Add initial support for static methods in generic types
    
    Fixes bug 471512.
---
 codegen/valaccodebasemodule.vala       |   15 ++++++-
 codegen/valaccodemethodcallmodule.vala |   14 ++++++-
 codegen/valaccodemethodmodule.vala     |   15 +++++++
 vala/valasemanticanalyzer.vala         |   66 +++++++++++++++++--------------
 4 files changed, 75 insertions(+), 35 deletions(-)

diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index bd639cb..c7d1bf0 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1716,10 +1716,19 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 		return local;
 	}
 
+	bool is_in_generic_type (DataType type) {
+		if (type.type_parameter.parent_symbol is TypeSymbol
+		    && (current_method == null || current_method.binding == MemberBinding.INSTANCE)) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+
 	private CCodeExpression get_type_id_expression (DataType type) {
 		if (type is GenericType) {
 			string var_name = "%s_type".printf (type.type_parameter.name.down ());
-			if (type.type_parameter.parent_symbol is TypeSymbol) {
+			if (is_in_generic_type (type)) {
 				return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), var_name);
 			} else {
 				return new CCodeIdentifier (var_name);
@@ -1769,7 +1778,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			return new CCodeIdentifier (dup_function);
 		} else if (type.type_parameter != null && current_type_symbol is Class) {
 			string func_name = "%s_dup_func".printf (type.type_parameter.name.down ());
-			if (type.type_parameter.parent_symbol is TypeSymbol) {
+			if (is_in_generic_type (type)) {
 				return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
 			} else {
 				return new CCodeIdentifier (func_name);
@@ -1899,7 +1908,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
 			return new CCodeIdentifier (unref_function);
 		} else if (type.type_parameter != null && current_type_symbol is Class) {
 			string func_name = "%s_destroy_func".printf (type.type_parameter.name.down ());
-			if (type.type_parameter.parent_symbol is TypeSymbol) {
+			if (is_in_generic_type (type)) {
 				return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
 			} else {
 				return new CCodeIdentifier (func_name);
diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala
index adb4434..f62ff3a 100644
--- a/codegen/valaccodemethodcallmodule.vala
+++ b/codegen/valaccodemethodcallmodule.vala
@@ -102,8 +102,18 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
 					break;
 				}
 			}
-		} else if (m != null && m.get_type_parameters ().size > 0) {
-			add_generic_type_arguments (ccall, ma.get_type_arguments (), expr);
+		} else if (m != null) {
+			if (m.binding != MemberBinding.INSTANCE && m.parent_symbol is ObjectTypeSymbol) {
+				// support static methods in generic types
+				var type_symbol = (ObjectTypeSymbol) m.parent_symbol;
+				if (type_symbol.get_type_parameters ().size > 0 && ma.inner is MemberAccess) {
+					var type_ma = (MemberAccess) ma.inner;
+					add_generic_type_arguments (ccall, type_ma.get_type_arguments (), expr);
+				}
+			}
+			if (m.get_type_parameters ().size > 0) {
+				add_generic_type_arguments (ccall, ma.get_type_arguments (), expr);
+			}
 		}
 
 		// the complete call expression, might include casts, comma expressions, and/or assignments
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 0bd87c8..e1e3de1 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -742,6 +742,21 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
 			}
 		} else {
 			int type_param_index = 0;
+			if (m.binding != MemberBinding.INSTANCE && m.parent_symbol is ObjectTypeSymbol) {
+				// support static methods in generic types
+				var type_symbol = (ObjectTypeSymbol) m.parent_symbol;
+				foreach (var type_param in type_symbol.get_type_parameters ()) {
+					cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeFormalParameter ("%s_type".printf (type_param.name.down ()), "GType"));
+					cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
+					cparam_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeFormalParameter ("%s_destroy_func".printf (type_param.name.down ()), "GDestroyNotify"));
+					if (carg_map != null) {
+						carg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier ("%s_type".printf (type_param.name.down ())));
+						carg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier ("%s_dup_func".printf (type_param.name.down ())));
+						carg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier ("%s_destroy_func".printf (type_param.name.down ())));
+					}
+					type_param_index++;
+				}
+			}
 			foreach (var type_param in m.get_type_parameters ()) {
 				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeFormalParameter ("%s_type".printf (type_param.name.down ()), "GType"));
 				cparam_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeFormalParameter ("%s_dup_func".printf (type_param.name.down ()), "GBoxedCopyFunc"));
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 1bef377..cf3c1e6 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -552,34 +552,40 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 	}
 
 	public static DataType? get_actual_type (DataType? derived_instance_type, MemberAccess? method_access, GenericType generic_type, CodeNode node_reference) {
+		DataType actual_type = null;
 		if (generic_type.type_parameter.parent_symbol is TypeSymbol) {
-			if (derived_instance_type == null) {
-				return generic_type;
-			}
+			if (derived_instance_type != null) {
+				// trace type arguments back to the datatype where the method has been declared
+				var instance_type = get_instance_base_type_for_member (derived_instance_type, (TypeSymbol) generic_type.type_parameter.parent_symbol, node_reference);
 
-			// trace type arguments back to the datatype where the method has been declared
-			var instance_type = get_instance_base_type_for_member (derived_instance_type, (TypeSymbol) generic_type.type_parameter.parent_symbol, node_reference);
+				assert (instance_type != null);
 
-			assert (instance_type != null);
+				int 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;
+					return null;
+				}
 
-			int 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;
-				return null;
-			}
+				if (param_index < instance_type.get_type_arguments ().size) {
+					actual_type = (DataType) instance_type.get_type_arguments ().get (param_index);
+				}
+			} else if (method_access != null && method_access.inner is MemberAccess) {
+				// static method in generic type
+				var type_symbol = (ObjectTypeSymbol) generic_type.type_parameter.parent_symbol;
 
-			DataType actual_type = null;
-			if (param_index < instance_type.get_type_arguments ().size) {
-				actual_type = (DataType) instance_type.get_type_arguments ().get (param_index);
-			}
-			if (actual_type == null) {
-				// no actual type available
-				return generic_type;
+				int param_index = type_symbol.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;
+					return null;
+				}
+
+				var type_ma = (MemberAccess) method_access.inner;
+				if (param_index < type_ma.get_type_arguments ().size) {
+					actual_type = (DataType) type_ma.get_type_arguments ().get (param_index);
+				}
 			}
-			actual_type = actual_type.copy ();
-			actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
-			return actual_type;
 		} else {
 			// generic method
 			var m = (Method) generic_type.type_parameter.parent_symbol;
@@ -595,18 +601,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 				return null;
 			}
 
-			DataType actual_type = null;
 			if (param_index < method_access.get_type_arguments ().size) {
 				actual_type = (DataType) method_access.get_type_arguments ().get (param_index);
 			}
-			if (actual_type == null) {
-				// no actual type available
-				return generic_type;
-			}
-			actual_type = actual_type.copy ();
-			actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
-			return actual_type;
 		}
+
+		if (actual_type == null) {
+			// no actual type available
+			return generic_type;
+		}
+		actual_type = actual_type.copy ();
+		actual_type.value_owned = actual_type.value_owned && generic_type.value_owned;
+		return actual_type;
 	}
 
 	public bool is_in_instance_method () {



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