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"));
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));
} 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;
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");
}
}
} 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 {
*/
public string? ctype { get; set; }
+ public bool captured { get; set; }
+
private DataType _data_type;
private Expression? _default_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;