]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support use of generics in closures
authorJürg Billeter <j@bitron.ch>
Mon, 25 Oct 2010 21:07:02 +0000 (23:07 +0200)
committerJürg Billeter <j@bitron.ch>
Mon, 25 Oct 2010 21:07:02 +0000 (23:07 +0200)
codegen/valaccodebasemodule.vala
codegen/valaccodemethodmodule.vala
vala/valalambdaexpression.vala

index 6fd4b7ed07f58abbd4e330e3793aae70447fe9bb..2045dff62867c971ac37b5751539561a21ac0ada 100644 (file)
@@ -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) {
index a7022c2060718b606a990035fb7d6e516530521b..a457f89adbebe07d23dad57db02944d6971fdcf0 100644 (file)
@@ -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"));
index d71c4b55c967776f8044bb9c92a1d44d70d9c5a3..889905b20beb06b41b3d81990d90d8c68f7bc71b 100644 (file)
@@ -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;