Commit 63b56c13 authored by Jürg Billeter's avatar Jürg Billeter

Support delegates with delegate parameters and results

Based on patch by Levi Bard, fixes bug 578415.
parent 3ad7e0d8
......@@ -37,7 +37,14 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
return;
}
generate_type_declaration (d.return_type, decl_space);
string return_type_cname = d.return_type.get_cname ();
if (return_type_cname == d.get_cname ()) {
// recursive delegate
return_type_cname = "GCallback";
} else {
generate_type_declaration (d.return_type, decl_space);
}
var cfundecl = new CCodeFunctionDeclarator (d.get_cname ());
foreach (FormalParameter param in d.get_parameters ()) {
......@@ -59,6 +66,15 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
cfundecl.add_parameter (cparam);
}
}
// handle delegate parameters
if (param.parameter_type is DelegateType) {
var deleg_type = (DelegateType) param.parameter_type;
var param_d = deleg_type.delegate_symbol;
if (param_d.has_target) {
var cparam = new CCodeFormalParameter (get_delegate_target_cname (get_variable_cname (param.name)), "void*");
cfundecl.add_parameter (cparam);
}
}
}
if (!d.no_array_length && d.return_type is ArrayType) {
// return array length if appropriate
......@@ -68,6 +84,14 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
var cparam = new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*");
cfundecl.add_parameter (cparam);
}
} else if (d.return_type is DelegateType) {
// return delegate target if appropriate
var deleg_type = (DelegateType) d.return_type;
var result_d = deleg_type.delegate_symbol;
if (result_d.has_target) {
var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void**");
cfundecl.add_parameter (cparam);
}
}
if (d.has_target) {
var cparam = new CCodeFormalParameter ("user_data", "void*");
......@@ -78,7 +102,7 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
cfundecl.add_parameter (cparam);
}
var ctypedef = new CCodeTypeDefinition (d.return_type.get_cname (), cfundecl);
var ctypedef = new CCodeTypeDefinition (return_type_cname, cfundecl);
if (d.source_reference != null && d.source_reference.comment != null) {
decl_space.add_type_declaration (new CCodeComment (d.source_reference.comment));
......@@ -263,6 +287,14 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
var cparam = new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*");
cparam_map.set (get_param_pos (d.carray_length_parameter_position + 0.01 * dim), cparam);
}
} else if (d.return_type is DelegateType) {
// return delegate target if appropriate
var deleg_type = (DelegateType) d.return_type;
if (deleg_type.delegate_symbol.has_target) {
var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void**");
cparam_map.set (get_param_pos (d.cdelegate_target_parameter_position), cparam);
}
}
if (m.get_error_types ().size > 0) {
......@@ -337,6 +369,13 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
}
carg_map.set (get_param_pos (param.carray_length_parameter_position + 0.01 * dim), clength);
}
} else if (param.parameter_type is DelegateType) {
var deleg_type = (DelegateType) param.parameter_type;
if (deleg_type.delegate_symbol.has_target) {
var ctarget = new CCodeIdentifier (get_delegate_target_cname (d_params.get (i).name));
carg_map.set (get_param_pos (param.cdelegate_target_parameter_position), ctarget);
}
}
i++;
......@@ -352,6 +391,13 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
}
carg_map.set (get_param_pos (m.carray_length_parameter_position + 0.01 * dim), clength);
}
} else if (m.return_type is DelegateType) {
var deleg_type = (DelegateType) m.return_type;
if (deleg_type.delegate_symbol.has_target) {
var ctarget = new CCodeIdentifier (get_delegate_target_cname ("result"));
carg_map.set (get_param_pos (m.cdelegate_target_parameter_position), ctarget);
}
}
if (m.get_error_types ().size > 0) {
......@@ -402,6 +448,12 @@ internal class Vala.CCodeDelegateModule : CCodeArrayModule {
string ctypename = param.parameter_type.get_cname ();
string target_ctypename = "void*";
if (param.parent_symbol is Delegate
&& param.parameter_type.get_cname () == ((Delegate) param.parent_symbol).get_cname ()) {
// recursive delegate
ctypename = "GCallback";
}
if (param.direction != ParameterDirection.IN) {
ctypename += "*";
target_ctypename += "*";
......
......@@ -39,6 +39,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
CCodeFunctionCall async_call = null;
Method m = null;
Delegate deleg = null;
Gee.List<FormalParameter> params;
var ma = expr.call as MemberAccess;
......@@ -62,6 +63,8 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
m = cl.default_construction_method;
generate_method_declaration (m, source_declarations);
ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_real_cname ()));
} else if (itype is DelegateType) {
deleg = ((DelegateType) itype).delegate_symbol;
}
HashMap<int,CCodeExpression> in_arg_map, out_arg_map;
......@@ -463,6 +466,53 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
}
}
// add length argument for delegates returning arrays
// TODO: avoid code duplication with methods returning arrays, see above
if (deleg != null && deleg.return_type is ArrayType) {
var array_type = (ArrayType) deleg.return_type;
for (int dim = 1; dim <= array_type.rank; dim++) {
if (deleg.array_null_terminated) {
// handle calls to methods returning null-terminated arrays
var temp_var = get_temp_variable (itype.get_return_type ());
var temp_ref = get_variable_cexpression (temp_var.name);
temp_vars.insert (0, temp_var);
ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
requires_array_length = true;
var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
len_call.add_argument (temp_ref);
expr.append_array_size (len_call);
} else if (!deleg.no_array_length) {
var temp_var = get_temp_variable (int_type);
var temp_ref = get_variable_cexpression (temp_var.name);
temp_vars.insert (0, temp_var);
out_arg_map.set (get_param_pos (deleg.carray_length_parameter_position + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
expr.append_array_size (temp_ref);
} else {
expr.append_array_size (new CCodeConstant ("-1"));
}
}
} else if (deleg != null && deleg.return_type is DelegateType) {
var deleg_type = (DelegateType) deleg.return_type;
var d = deleg_type.delegate_symbol;
if (d.has_target) {
var temp_var = get_temp_variable (new PointerType (new VoidType ()));
var temp_ref = get_variable_cexpression (temp_var.name);
temp_vars.insert (0, temp_var);
out_arg_map.set (get_param_pos (deleg.cdelegate_target_parameter_position), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
expr.delegate_target = temp_ref;
}
}
if (m != null && m.coroutine) {
if ((current_method != null && current_method.coroutine)
|| (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference)) {
......
......@@ -96,7 +96,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
var deleg_type = (DelegateType) m.return_type;
var d = deleg_type.delegate_symbol;
if (d.has_target) {
var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void*");
var cparam = new CCodeFormalParameter (get_delegate_target_cname ("result"), "void**");
cparam_map.set (get_param_pos (m.cdelegate_target_parameter_position), cparam);
if (carg_map != null) {
carg_map.set (get_param_pos (m.cdelegate_target_parameter_position), get_variable_cexpression (cparam.name));
......
......@@ -8,6 +8,7 @@ public static delegate void Maman.VoidCallback ();
public static delegate int Maman.ActionCallback ();
public delegate void Maman.InstanceCallback (int i);
public delegate Maman.SelfCallback Maman.SelfCallback (Maman.SelfCallback scb);
struct Maman.DelegateStruct {
public VoidCallback callback;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment