[vala] Support delegates with delegate parameters and results
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Subject: [vala] Support delegates with delegate parameters and results
- Date: Thu, 7 May 2009 12:05:25 -0400 (EDT)
commit 63b56c1367fb640c30d9a0248f767b07c36a0930
Author: Jürg Billeter <j bitron ch>
Date: Thu May 7 17:21:59 2009 +0200
Support delegates with delegate parameters and results
Based on patch by Levi Bard, fixes bug 578415.
---
gobject/valaccodedelegatemodule.vala | 56 ++++++++++++++++++++++++++++++-
gobject/valaccodemethodcallmodule.vala | 50 ++++++++++++++++++++++++++++
gobject/valaccodemethodmodule.vala | 2 +-
tests/delegates/delegates.test | 1 +
4 files changed, 106 insertions(+), 3 deletions(-)
diff --git a/gobject/valaccodedelegatemodule.vala b/gobject/valaccodedelegatemodule.vala
index 7975204..99c5602 100644
--- a/gobject/valaccodedelegatemodule.vala
+++ b/gobject/valaccodedelegatemodule.vala
@@ -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 += "*";
diff --git a/gobject/valaccodemethodcallmodule.vala b/gobject/valaccodemethodcallmodule.vala
index adb0106..8e328ca 100644
--- a/gobject/valaccodemethodcallmodule.vala
+++ b/gobject/valaccodemethodcallmodule.vala
@@ -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)) {
diff --git a/gobject/valaccodemethodmodule.vala b/gobject/valaccodemethodmodule.vala
index 5643639..ffbe24d 100644
--- a/gobject/valaccodemethodmodule.vala
+++ b/gobject/valaccodemethodmodule.vala
@@ -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));
diff --git a/tests/delegates/delegates.test b/tests/delegates/delegates.test
index 0885f3e..b225dd3 100644
--- a/tests/delegates/delegates.test
+++ b/tests/delegates/delegates.test
@@ -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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]