Fixes bug 492483.
private CCodeExpression get_type_id_expression (DataType type) {
if (type is GenericType) {
string var_name = "%s_type".printf (type.type_parameter.name.down ());
- return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), var_name);
+ if (type.type_parameter.parent_symbol is TypeSymbol) {
+ return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), var_name);
+ } else {
+ return new CCodeIdentifier (var_name);
+ }
} else {
string type_id = type.get_type_id ();
if (type_id == null) {
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 ());
- return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+ if (type.type_parameter.parent_symbol is TypeSymbol) {
+ return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+ } else {
+ return new CCodeIdentifier (func_name);
+ }
} else if (type is PointerType) {
var pointer_type = (PointerType) type;
return get_dup_func_expression (pointer_type.base_type, source_reference);
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 ());
- return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+ if (type.type_parameter.parent_symbol is TypeSymbol) {
+ return new CCodeMemberAccess.pointer (new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv"), func_name);
+ } else {
+ return new CCodeIdentifier (func_name);
+ }
} else if (type is ArrayType) {
return new CCodeIdentifier ("g_free");
} else if (type is PointerType) {
foreach (DataType base_type in current_class.get_base_types ()) {
if (base_type.data_type is Class) {
- foreach (DataType type_arg in base_type.get_type_arguments ()) {
- if (type_arg is GenericType) {
- // map generic type parameter
- string type_param = type_arg.type_parameter.name.down ();
- ccall.add_argument (new CCodeIdentifier ("%s_type".printf (type_param)));
- ccall.add_argument (new CCodeIdentifier ("%s_dup_func".printf (type_param)));
- ccall.add_argument (new CCodeIdentifier ("%s_destroy_func".printf (type_param)));
- } else {
- ccall.add_argument (new CCodeIdentifier (type_arg.get_type_id ()));
- if (requires_copy (type_arg)) {
- var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference);
- if (dup_func == null) {
- // type doesn't contain a copy function
- expr.error = true;
- return;
- }
- ccall.add_argument (new CCodeCastExpression (dup_func, "GBoxedCopyFunc"));
- ccall.add_argument (get_destroy_func_expression (type_arg));
- } else {
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (new CCodeConstant ("NULL"));
- }
- }
- }
-
+ add_generic_type_arguments (ccall, base_type.get_type_arguments (), expr);
break;
}
}
+ } else if (m != null && 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
expr.ccodenode = ccomma;
}
}
+
+ void add_generic_type_arguments (CCodeFunctionCall ccall, Gee.List<DataType> type_args, CodeNode expr) {
+ foreach (var type_arg in type_args) {
+ if (type_arg is GenericType) {
+ // map generic type parameter
+ string type_param = type_arg.type_parameter.name.down ();
+ ccall.add_argument (new CCodeIdentifier ("%s_type".printf (type_param)));
+ ccall.add_argument (new CCodeIdentifier ("%s_dup_func".printf (type_param)));
+ ccall.add_argument (new CCodeIdentifier ("%s_destroy_func".printf (type_param)));
+ } else {
+ ccall.add_argument (new CCodeIdentifier (type_arg.get_type_id ()));
+ if (requires_copy (type_arg)) {
+ var dup_func = get_dup_func_expression (type_arg, type_arg.source_reference);
+ if (dup_func == null) {
+ // type doesn't contain a copy function
+ expr.error = true;
+ return;
+ }
+ ccall.add_argument (new CCodeCastExpression (dup_func, "GBoxedCopyFunc"));
+ ccall.add_argument (get_destroy_func_expression (type_arg));
+ } else {
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ }
+ }
+ }
+ }
}
}
type_param_index++;
}
+ } else {
+ int type_param_index = 0;
+ 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"));
+ 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 (FormalParameter param in m.get_parameters ()) {
/* valadatatype.vala
*
- * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2009 Jürg Billeter
+ * Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
return false;
}
- public DataType get_actual_type (DataType? derived_instance_type, CodeNode node_reference) {
- if (derived_instance_type == null) {
+ public DataType get_actual_type (DataType? derived_instance_type, MemberAccess? method_access, CodeNode node_reference) {
+ if (derived_instance_type == null && method_access == null) {
return this;
}
DataType result = this;
if (result is GenericType) {
- result = SemanticAnalyzer.get_actual_type (derived_instance_type, (GenericType) result, node_reference);
+ result = SemanticAnalyzer.get_actual_type (derived_instance_type, method_access, (GenericType) result, node_reference);
// don't try to resolve type arguments of returned actual type
// they can never be resolved and are not related to the instance type
} else if (result.type_argument_list != null) {
// recursely get actual types for type arguments
result = result.copy ();
for (int i = 0; i < result.type_argument_list.size; i++) {
- result.type_argument_list[i] = result.type_argument_list[i].get_actual_type (derived_instance_type, node_reference);
+ result.type_argument_list[i] = result.type_argument_list[i].get_actual_type (derived_instance_type, method_access, node_reference);
}
}
*/
public void add_type_parameter (TypeParameter p) {
type_parameters.add (p);
- p.type = this;
scope.add (p.name, p);
}
error = true;
return false;
}
- var iterator_type = iterator_method.return_type.get_actual_type (collection_type, this);
+ var iterator_type = iterator_method.return_type.get_actual_type (collection_type, null, this);
if (iterator_type is VoidType) {
Report.error (collection.source_reference, "`%s' must return an iterator".printf (iterator_method.get_full_name ()));
error = true;
error = true;
return false;
}
- var element_type = get_method.return_type.get_actual_type (iterator_type, this);
+ var element_type = get_method.return_type.get_actual_type (iterator_type, null, this);
if (element_type is VoidType) {
Report.error (collection.source_reference, "`%s' must return an element".printf (get_method.get_full_name ()));
error = true;
formal_value_type = analyzer.get_value_type_for_symbol (symbol_reference, lvalue);
if (inner != null && formal_value_type != null) {
- value_type = formal_value_type.get_actual_type (inner.value_type, this);
+ value_type = formal_value_type.get_actual_type (inner.value_type, null, this);
} else {
value_type = formal_value_type;
}
* Represents a type or namespace method.
*/
public class Vala.Method : Member {
+ Gee.List<TypeParameter> type_parameters = new ArrayList<TypeParameter> ();
+
public const string DEFAULT_SENTINEL = "NULL";
/**
}
}
- var actual_base_type = base_method.return_type.get_actual_type (object_type, this);
+ var actual_base_type = base_method.return_type.get_actual_type (object_type, null, this);
if (!return_type.equals (actual_base_type)) {
invalid_match = "incompatible return type";
return false;
return false;
}
- actual_base_type = base_param.parameter_type.get_actual_type (object_type, this);
+ actual_base_type = base_param.parameter_type.get_actual_type (object_type, null, this);
if (!actual_base_type.equals (method_params_it.get ().parameter_type)) {
invalid_match = "incompatible type of parameter %d".printf (param_index);
return false;
return true;
}
+ /**
+ * Appends the specified parameter to the list of type parameters.
+ *
+ * @param p a type parameter
+ */
+ public void add_type_parameter (TypeParameter p) {
+ type_parameters.add (p);
+ scope.add (p.name, p);
+ }
+
+ /**
+ * Returns a copy of the type parameter list.
+ *
+ * @return list of type parameters
+ */
+ public Gee.List<TypeParameter> get_type_parameters () {
+ return new ReadOnlyList<TypeParameter> (type_parameters);
+ }
+
+ public 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;
+ }
+
/**
* Adds a precondition to this method.
*
/* store expected type for callback parameters */
arg.formal_target_type = param.parameter_type;
- arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, this);
+ arg.target_type = arg.formal_target_type.get_actual_type (target_object_type, call as MemberAccess, this);
last_arg = arg;
}
}
formal_value_type = ret_type;
- value_type = formal_value_type.get_actual_type (target_object_type, this);
+ value_type = formal_value_type.get_actual_type (target_object_type, call as MemberAccess, this);
bool may_throw = false;
/* store expected type for callback parameters */
arg.formal_target_type = param.parameter_type;
- arg.target_type = arg.formal_target_type.get_actual_type (value_type, this);
+ arg.target_type = arg.formal_target_type.get_actual_type (value_type, null, this);
}
}
/* valaobjecttypesymbol.vala
*
- * Copyright (C) 2008 Jürg Billeter
+ * Copyright (C) 2008-2009 Jürg Billeter
* Copyright (C) 2008 Philip Van Hoof
*
* This library is free software; you can redistribute it and/or
*/
public void add_type_parameter (TypeParameter p) {
type_parameters.add (p);
- p.type = this;
scope.add (p.name, p);
}
var flags = parse_member_declaration_modifiers ();
var type = parse_type ();
string id = parse_identifier ();
- parse_type_parameter_list ();
+ var type_param_list = parse_type_parameter_list ();
var method = new Method (id, type, get_src_com (begin));
method.access = access;
set_attributes (method, attrs);
+ foreach (TypeParameter type_param in type_param_list) {
+ method.add_type_parameter (type_param);
+ }
if (ModifierFlags.STATIC in flags) {
method.binding = MemberBinding.STATIC;
} else if (ModifierFlags.CLASS in flags) {
return null;
}
- public static DataType? get_actual_type (DataType derived_instance_type, GenericType generic_type, CodeNode 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);
+ public static DataType? get_actual_type (DataType? derived_instance_type, MemberAccess? method_access, GenericType generic_type, CodeNode node_reference) {
+ if (generic_type.type_parameter.parent_symbol is TypeSymbol) {
+ if (derived_instance_type == null) {
+ return generic_type;
+ }
- assert (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);
- 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;
- }
+ assert (instance_type != null);
- 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 = 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;
+ }
+
+ 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;
+ }
+ 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;
+
+ if (method_access == null) {
+ return generic_type;
+ }
+
+ int param_index = m.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;
+ }
+
+ 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;
}
- 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 () {
* @return delegate
*/
public Delegate get_delegate (DataType sender_type, CodeNode node_reference) {
- var actual_return_type = return_type.get_actual_type (sender_type, node_reference);
+ var actual_return_type = return_type.get_actual_type (sender_type, null, node_reference);
var generated_delegate = new Delegate (null, actual_return_type);
generated_delegate.has_target = true;
foreach (FormalParameter param in parameters) {
var actual_param = param.copy ();
- actual_param.parameter_type = actual_param.parameter_type.get_actual_type (sender_type, node_reference);
+ actual_param.parameter_type = actual_param.parameter_type.get_actual_type (sender_type, null, node_reference);
generated_delegate.add_parameter (actual_param);
}
*/
public void add_type_parameter (TypeParameter p) {
type_parameters.add (p);
- p.type = this;
scope.add (p.name, p);
}
/* valatypeparameter.vala
*
- * Copyright (C) 2006-2008 Jürg Billeter
+ * Copyright (C) 2006-2009 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
* Represents a generic type parameter in the source code.
*/
public class Vala.TypeParameter : Symbol {
- /**
- * The generic type declaring this parameter.
- */
- public weak TypeSymbol type;
-
/**
* Creates a new generic type parameter.
*