]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support capturing parameters in closures
authorJürg Billeter <j@bitron.ch>
Tue, 15 Sep 2009 15:48:44 +0000 (17:48 +0200)
committerJürg Billeter <j@bitron.ch>
Tue, 15 Sep 2009 15:48:44 +0000 (17:48 +0200)
codegen/valaccodebasemodule.vala
codegen/valaccodedelegatemodule.vala
codegen/valaccodememberaccessmodule.vala
vala/valaformalparameter.vala
vala/valamemberaccess.vala

index 44b5e4bd65c5345c53c40f97d95dba08671a667f..efc3d0b884ac2f506a28f3f1150f5ec034c57805 100644 (file)
@@ -1670,6 +1670,21 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), "self"), ref_call)));
                        }
 
+                       if (b.parent_symbol is Method) {
+                               // parameters are captured with the top-level block of the method
+                               foreach (var param in ((Method) b.parent_symbol).get_parameters ()) {
+                                       if (param.captured) {
+                                               data.add_field (param.parameter_type.get_cname (), get_variable_cname (param.name));
+                                               cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_variable_cname (param.name)), new CCodeIdentifier (get_variable_cname (param.name)))));
+
+                                               if (param.parameter_type is DelegateType) {
+                                                       data.add_field ("gpointer", get_delegate_target_cname (get_variable_cname (param.name)));
+                                                       cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (block_id)), get_delegate_target_cname (get_variable_cname (param.name))), new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name))))));
+                                               }
+                                       }
+                               }
+                       }
+
                        var data_free = new CCodeFunctionCall (new CCodeIdentifier ("g_slice_free"));
                        data_free.add_argument (new CCodeIdentifier (struct_name));
                        data_free.add_argument (new CCodeIdentifier ("data"));
@@ -1856,6 +1871,10 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                                        ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs));
 
                                        var lhs_delegate_target = get_variable_cexpression (get_delegate_target_cname (get_variable_cname (local.name)));
+                                       if (local.captured) {
+                                               var block = (Block) local.parent_symbol;
+                                               lhs_delegate_target = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (local.name));
+                                       }
                                        var rhs_delegate_target = get_delegate_target_cexpression (local.initializer);
                                        ccomma.append_expression (new CCodeAssignment (lhs_delegate_target, rhs_delegate_target));
                                
index 357e1dcf9073c11ffc1e6dc69fdb8e93d9c02cc2..3ff96666e4c3e28e0268b0cc807232d9bb06b771 100644 (file)
@@ -150,16 +150,22 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                } else if (delegate_expr.symbol_reference != null) {
                        if (delegate_expr.symbol_reference is FormalParameter) {
                                var param = (FormalParameter) delegate_expr.symbol_reference;
-                               CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)));
-                               if (param.direction != ParameterDirection.IN) {
-                                       // accessing argument of out/ref param
-                                       target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
-                               }
-                               if (is_out) {
-                                       // passing array as out/ref
-                                       return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+                               if (param.captured) {
+                                       // captured variables are stored on the heap
+                                       var block = ((Method) param.parent_symbol).body;
+                                       return new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (get_block_id (block))), get_delegate_target_cname (param.name));
                                } else {
-                                       return target_expr;
+                                       CCodeExpression target_expr = new CCodeIdentifier (get_delegate_target_cname (get_variable_cname (param.name)));
+                                       if (param.direction != ParameterDirection.IN) {
+                                               // accessing argument of out/ref param
+                                               target_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, target_expr);
+                                       }
+                                       if (is_out) {
+                                               // passing array as out/ref
+                                               return new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, target_expr);
+                                       } else {
+                                               return target_expr;
+                                       }
                                }
                        } else if (delegate_expr.symbol_reference is LocalVariable) {
                                var local = (LocalVariable) delegate_expr.symbol_reference;
@@ -337,7 +343,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
                var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
                int i = 0;
-               if (m.binding == MemberBinding.INSTANCE) {
+               if (m.binding == MemberBinding.INSTANCE || m.closure) {
                        CCodeExpression arg;
                        if (d.has_target) {
                                arg = new CCodeIdentifier ("self");
index 027d4a227d77e3a20deecfc10ed8e62153343c25..85424fc9a6edfa50ba999d83bf52b2166941ed68 100644 (file)
@@ -366,7 +366,11 @@ internal class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                                        }
                                }
                        } else {
-                               if (current_method != null && current_method.coroutine) {
+                               if (p.captured) {
+                                       // captured variables are stored on the heap
+                                       var block = ((Method) p.parent_symbol).body;
+                                       expr.ccodenode = new CCodeMemberAccess.pointer (new CCodeIdentifier ("_data%d_".printf (get_block_id (block))), get_variable_cname (p.name));
+                               } else if (current_method != null && current_method.coroutine) {
                                        // use closure
                                        expr.ccodenode = get_variable_cexpression (p.name);
                                } else {
index 6c6e575b5cc7fa33a2760819ed1342cf3d199485..3a35aebcc713dcb3f55035dbadd72b09e9c426da 100644 (file)
@@ -101,6 +101,8 @@ public class Vala.FormalParameter : Symbol {
         */
        public string? ctype { get; set; }
 
+       public bool captured { get; set; }
+
        private DataType _data_type;
        private Expression? _default_expression;
 
index 1e076e435a6e257172bf5a1d6d3ab5a935de01c1..79f64df371d429f570443f32f263dd3e1705ff7d 100644 (file)
@@ -427,6 +427,14 @@ public class Vala.MemberAccess : Expression {
                                block.captured = true;
                                analyzer.current_method.closure = true;
                        }
+               } else if (member is FormalParameter) {
+                       var param = (FormalParameter) member;
+                       var m = param.parent_symbol as Method;
+                       if (m != null && m != analyzer.current_method) {
+                               param.captured = true;
+                               m.body.captured = true;
+                               analyzer.current_method.closure = true;
+                       }
                } else if (member is Field) {
                        var f = (Field) member;
                        access = f.access;