From: Jürg Billeter Date: Wed, 3 Jun 2009 07:21:36 +0000 (+0200) Subject: Add initial support for static methods in generic types X-Git-Tag: 0.7.4~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9460d48c8ae8e53b0189b06ec021db0a3b493578;p=thirdparty%2Fvala.git Add initial support for static methods in generic types Fixes bug 471512. --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index bd639cb11..c7d1bf074 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 adb443454..f62ff3aca 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 0bd87c89c..e1e3de1af 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 1bef37711..cf3c1e66f 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 () {