Fixes bug 595538.
}
}
+ 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;
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);
}
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));
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;
}
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);
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;