[vala] Fix nested closures
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [vala] Fix nested closures
- Date: Fri, 18 Sep 2009 13:18:11 +0000 (UTC)
commit c0aac5d3405fc30133b67546126cabae10ff7ab1
Author: Jürg Billeter <j bitron ch>
Date: Fri Sep 18 15:17:35 2009 +0200
Fix nested closures
Fixes bug 595538.
codegen/valaccodebasemodule.vala | 28 ++++++++++++++++++++++++----
codegen/valaccodedelegatemodule.vala | 5 +----
codegen/valaccodemethodmodule.vala | 15 +++------------
vala/valamemberaccess.vala | 28 +++++++++++++++++++++++++---
4 files changed, 53 insertions(+), 23 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 1b686c4..d3caef8 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -91,6 +91,29 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
+ public Block? current_closure_block {
+ get {
+ return next_closure_block (current_symbol);
+ }
+ }
+
+ public unowned Block? next_closure_block (Symbol sym) {
+ unowned Block block = null;
+ while (true) {
+ block = sym as Block;
+ if (!(sym is Block || sym is Method)) {
+ // no closure block
+ break;
+ }
+ if (block != null && block.captured) {
+ // closure block found
+ break;
+ }
+ sym = sym.parent_symbol;
+ }
+ return block;
+ }
+
public CCodeDeclarationSpace header_declarations;
public CCodeDeclarationSpace internal_header_declarations;
public CCodeDeclarationSpace source_declarations;
@@ -1610,10 +1633,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
var cblock = new CCodeBlock ();
if (b.captured) {
- var parent_block = b.parent_symbol as Block;
- while (parent_block != null && !parent_block.captured) {
- parent_block = parent_block.parent_symbol as Block;
- }
+ var parent_block = next_closure_block (b.parent_symbol);
int block_id = get_block_id (b);
string struct_name = "Block%dData".printf (block_id);
diff --git a/codegen/valaccodedelegatemodule.vala b/codegen/valaccodedelegatemodule.vala
index 85d9ea9..8611b0a 100644
--- a/codegen/valaccodedelegatemodule.vala
+++ b/codegen/valaccodedelegatemodule.vala
@@ -143,10 +143,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
}
return invocation_expr.delegate_target;
} else if (delegate_expr is LambdaExpression) {
- var closure_block = current_symbol as Block;
- while (closure_block != null && !closure_block.captured) {
- closure_block = closure_block.parent_symbol as Block;
- }
+ var closure_block = current_closure_block;
if (closure_block != null) {
int block_id = get_block_id (closure_block);
var delegate_target = get_variable_cexpression ("_data%d_".printf (block_id));
diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala
index 363c6c4..bb28ecf 100644
--- a/codegen/valaccodemethodmodule.vala
+++ b/codegen/valaccodemethodmodule.vala
@@ -416,16 +416,10 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
if (m.closure) {
// add variables for parent closure blocks
// as closures only have one parameter for the innermost closure block
- var closure_block = m.parent_symbol as Block;
- while (closure_block != null && !closure_block.captured) {
- closure_block = closure_block.parent_symbol as Block;
- }
+ var closure_block = current_closure_block;
int block_id = get_block_id (closure_block);
while (true) {
- var parent_closure_block = closure_block.parent_symbol as Block;
- while (parent_closure_block != null && !parent_closure_block.captured) {
- parent_closure_block = parent_closure_block.parent_symbol as Block;
- }
+ var parent_closure_block = next_closure_block (closure_block.parent_symbol);
if (parent_closure_block == null) {
break;
}
@@ -776,10 +770,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
public override void generate_cparameters (Method m, CCodeDeclarationSpace decl_space, Map<int,CCodeFormalParameter> cparam_map, CCodeFunction func, CCodeFunctionDeclarator? vdeclarator = null, Map<int,CCodeExpression>? carg_map = null, CCodeFunctionCall? vcall = null, int direction = 3) {
if (m.closure) {
- var closure_block = m.parent_symbol as Block;
- while (closure_block != null && !closure_block.captured) {
- closure_block = closure_block.parent_symbol as Block;
- }
+ var closure_block = current_closure_block;
int block_id = get_block_id (closure_block);
var instance_param = new CCodeFormalParameter ("_data%d_".printf (block_id), "Block%dData*".printf (block_id));
cparam_map.set (get_param_pos (m.cinstance_parameter_position), instance_param);
diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala
index 70f3a26..80e0b00 100644
--- a/vala/valamemberaccess.vala
+++ b/vala/valamemberaccess.vala
@@ -423,18 +423,40 @@ public class Vala.MemberAccess : Expression {
var local = (LocalVariable) member;
var block = (Block) local.parent_symbol;
if (analyzer.find_parent_method (block) != analyzer.current_method) {
+ // mark all methods between current method and the captured
+ // block as closures (to support nested closures)
+ Symbol sym = analyzer.current_method;
+ while (sym != block) {
+ var method = sym as Method;
+ if (method != null) {
+ method.closure = true;
+ // consider captured variables as used
+ // as we require captured variables to be initialized
+ method.add_captured_variable (local);
+ }
+ sym = sym.parent_symbol;
+ }
+
local.captured = true;
block.captured = true;
- analyzer.current_method.closure = true;
- analyzer.current_method.add_captured_variable (local);
}
} else if (member is FormalParameter) {
var param = (FormalParameter) member;
var m = param.parent_symbol as Method;
if (m != null && m != analyzer.current_method && param != m.this_parameter) {
+ // mark all methods between current method and the captured
+ // parameter as closures (to support nested closures)
+ Symbol sym = analyzer.current_method;
+ while (sym != m) {
+ var method = sym as Method;
+ if (method != null) {
+ method.closure = true;
+ }
+ sym = sym.parent_symbol;
+ }
+
param.captured = true;
m.body.captured = true;
- analyzer.current_method.closure = true;
}
} else if (member is Field) {
var f = (Field) member;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]