[vala] Prepare support for generic delegates
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Prepare support for generic delegates
- Date: Sat, 3 Jul 2010 11:10:44 +0000 (UTC)
commit ac780b92d6b561f422e7935a8a9735464dc1540a
Author: Jürg Billeter <j bitron ch>
Date: Sat Jul 3 09:28:33 2010 +0200
Prepare support for generic delegates
vala/valaassignment.vala | 4 ++--
vala/valacodewriter.vala | 17 ++++++++++++++++-
vala/valadelegate.vala | 23 +++++++++++++++++++----
vala/valadelegatetype.vala | 20 +++++++++++++++++++-
vala/valalambdaexpression.vala | 3 ++-
vala/valalocalvariable.vala | 2 +-
vala/valamethodcall.vala | 5 ++++-
vala/valamethodtype.vala | 2 +-
vala/valasemanticanalyzer.vala | 14 +++++++++++---
9 files changed, 75 insertions(+), 15 deletions(-)
---
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 575ff96..7cb5b1f 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 e27b981..22d9d4e 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 6952409..85ada07 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<TypeParameter> 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 15dc2c3..5e49385 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 4bc618f..086b36f 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 f045034..f252cee 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 8f9940f..f4fa66c 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 fe69e6a..a2ad6d4 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 70685dc..c2eb9c7 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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]