From: Jürg Billeter Date: Sat, 3 Jul 2010 07:28:33 +0000 (+0200) Subject: Prepare support for generic delegates X-Git-Tag: 0.9.3~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac780b92d6b561f422e7935a8a9735464dc1540a;p=thirdparty%2Fvala.git Prepare support for generic delegates --- diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala index 575ff966f..7cb5b1f25 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 e27b981dd..22d9d4ee1 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 695240995..85ada07cc 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 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 15dc2c3dd..5e4938503 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 4bc618ff1..086b36f31 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 f0450340a..f252ceeac 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 8f9940f5a..f4fa66cd9 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 fe69e6ab4..a2ad6d4c0 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 70685dc5a..c2eb9c764 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);