[vala] Add initial support for static methods in generic types
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Subject: [vala] Add initial support for static methods in generic types
- Date: Wed, 3 Jun 2009 03:26:58 -0400 (EDT)
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]