[vala] Support capturing parameters in closures
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [vala] Support capturing parameters in closures
- Date: Tue, 15 Sep 2009 15:55:43 +0000 (UTC)
commit c2326dde18ca91c135831edf9be33fe1ea6b0664
Author: Jürg Billeter <j bitron ch>
Date: Tue Sep 15 17:48:44 2009 +0200
Support capturing parameters in closures
codegen/valaccodebasemodule.vala | 19 +++++++++++++++++++
codegen/valaccodedelegatemodule.vala | 26 ++++++++++++++++----------
codegen/valaccodememberaccessmodule.vala | 6 +++++-
vala/valaformalparameter.vala | 2 ++
vala/valamemberaccess.vala | 8 ++++++++
5 files changed, 50 insertions(+), 11 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 44b5e4b..efc3d0b 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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));
diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala
index 357e1dc..3ff9666 100644
--- a/codegen/valaccodedelegatemodule.vala
+++ b/codegen/valaccodedelegatemodule.vala
@@ -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");
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 027d4a2..85424fc 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -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 {
diff --git a/vala/valaformalparameter.vala b/vala/valaformalparameter.vala
index 6c6e575..3a35aeb 100644
--- a/vala/valaformalparameter.vala
+++ b/vala/valaformalparameter.vala
@@ -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;
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 1e076e4..79f64df 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]