[vala] Support use of generics in closures
- From: Jürg Billeter <juergbi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Support use of generics in closures
- Date: Mon, 25 Oct 2010 21:07:28 +0000 (UTC)
commit 837258146130818b9d02aba9ec63d586c611544d
Author: Jürg Billeter <j bitron ch>
Date: Mon Oct 25 23:07:02 2010 +0200
Support use of generics in closures
codegen/valaccodebasemodule.vala | 60 ++++++++++++++++++++++++++++-------
codegen/valaccodemethodmodule.vala | 19 +++++++++++-
vala/valalambdaexpression.vala | 11 ++++++
3 files changed, 77 insertions(+), 13 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 6fd4b7e..2045dff 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1727,13 +1727,31 @@ public class Vala.CCodeBaseModule : CodeGenerator {
var unref_call = new CCodeFunctionCall (new CCodeIdentifier ("block%d_data_unref".printf (parent_block_id)));
unref_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)));
free_block.add_statement (new CCodeExpressionStatement (unref_call));
- } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
- (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
- data.add_field ("%s *".printf (current_class.get_cname ()), "self");
+ } else {
+ if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE) ||
+ (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
+ data.add_field ("%s *".printf (current_class.get_cname ()), "self");
+
+ var ma = new MemberAccess.simple ("this");
+ ma.symbol_reference = current_class;
+ free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"), new ObjectType (current_class), ma)));
+ }
+
+ if (current_method != null) {
+ // allow capturing generic type parameters
+ foreach (var type_param in current_method.get_type_parameters ()) {
+ string func_name;
- var ma = new MemberAccess.simple ("this");
- ma.symbol_reference = current_class;
- free_block.add_statement (new CCodeExpressionStatement (get_unref_expression (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"), new ObjectType (current_class), ma)));
+ func_name = "%s_type".printf (type_param.name.down ());
+ data.add_field ("GType", func_name);
+
+ func_name = "%s_dup_func".printf (type_param.name.down ());
+ data.add_field ("GBoxedCopyFunc", func_name);
+
+ func_name = "%s_destroy_func".printf (type_param.name.down ());
+ data.add_field ("GDestroyNotify", func_name);
+ }
+ }
}
foreach (var local in local_vars) {
if (local.captured) {
@@ -1799,13 +1817,31 @@ public class Vala.CCodeBaseModule : CodeGenerator {
ref_call.add_argument (get_variable_cexpression ("_data%d_".printf (parent_block_id)));
ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "_data%d_".printf (parent_block_id)), ref_call));
- } else if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE &&
- (!(current_method is CreationMethod) || current_method.body != b)) ||
- (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
- var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
- ref_call.add_argument (get_result_cexpression ("self"));
+ } else {
+ if (in_constructor || (current_method != null && current_method.binding == MemberBinding.INSTANCE &&
+ (!(current_method is CreationMethod) || current_method.body != b)) ||
+ (current_property_accessor != null && current_property_accessor.prop.binding == MemberBinding.INSTANCE)) {
+ var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), b.source_reference));
+ ref_call.add_argument (get_result_cexpression ("self"));
+
+ ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call));
+ }
+
+ if (current_method != null) {
+ // allow capturing generic type parameters
+ foreach (var type_param in current_method.get_type_parameters ()) {
+ string func_name;
- ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), "self"), ref_call));
+ func_name = "%s_type".printf (type_param.name.down ());
+ ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name), new CCodeIdentifier (func_name)));
+
+ func_name = "%s_dup_func".printf (type_param.name.down ());
+ ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name), new CCodeIdentifier (func_name)));
+
+ func_name = "%s_destroy_func".printf (type_param.name.down ());
+ ccode.add_expression (new CCodeAssignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name), new CCodeIdentifier (func_name)));
+ }
+ }
}
if (b.parent_symbol is Method) {
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index a7022c2..a457f89 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -410,6 +410,23 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
ccode.add_declaration ("%s *".printf (current_class.get_cname ()), new CCodeVariableDeclarator ("self"));
ccode.add_expression (new CCodeAssignment (new CCodeIdentifier ("self"), cself));
}
+
+ // allow capturing generic type parameters
+ foreach (var type_param in m.get_type_parameters ()) {
+ string func_name;
+
+ func_name = "%s_type".printf (type_param.name.down ());
+ ccode.add_declaration ("GType", new CCodeVariableDeclarator (func_name));
+ ccode.add_expression (new CCodeAssignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name)));
+
+ func_name = "%s_dup_func".printf (type_param.name.down ());
+ ccode.add_declaration ("GBoxedCopyFunc", new CCodeVariableDeclarator (func_name));
+ ccode.add_expression (new CCodeAssignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name)));
+
+ func_name = "%s_destroy_func".printf (type_param.name.down ());
+ ccode.add_declaration ("GDestroyNotify", new CCodeVariableDeclarator (func_name));
+ ccode.add_expression (new CCodeAssignment (new CCodeIdentifier (func_name), new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (block_id)), func_name)));
+ }
} else if (m.parent_symbol is Class && !m.coroutine) {
var cl = (Class) m.parent_symbol;
if (m.overrides || (m.base_interface_method != null && !m.is_abstract && !m.is_virtual)) {
@@ -828,7 +845,7 @@ public class Vala.CCodeMethodModule : CCodeStructModule {
}
type_param_index++;
}
- } else {
+ } else if (!m.closure) {
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"));
diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala
index d71c4b5..889905b 100644
--- a/vala/valalambdaexpression.vala
+++ b/vala/valalambdaexpression.vala
@@ -224,6 +224,17 @@ public class Vala.LambdaExpression : Expression {
}
method.body.owner = method.scope;
+ // support use of generics in closures
+ var m = analyzer.find_parent_method (analyzer.current_symbol);
+ if (m != null) {
+ foreach (var type_param in m.get_type_parameters ()) {
+ method.add_type_parameter (new TypeParameter (type_param.name, type_param.source_reference));
+
+ method.closure = true;
+ m.body.captured = true;
+ }
+ }
+
/* lambda expressions should be usable like MemberAccess of a method */
symbol_reference = method;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]