From: Juerg Billeter Date: Wed, 6 Feb 2008 23:18:01 +0000 (+0000) Subject: create wrapper functions for signal handlers to support public signal X-Git-Tag: VALA_0_1_7~108 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cffd3fa144afa88445647dec0ba3bfcc378f101d;p=thirdparty%2Fvala.git create wrapper functions for signal handlers to support public signal 2008-02-07 Juerg Billeter * vala/valasemanticanalyzer.vala, vala/valasignal.vala, gobject/valaccodeassignmentbinding.vala, gobject/valaccodegenerator.vala, gobject/valaccodegeneratorinvocationexpression.vala, gobject/valaccodegeneratorsourcefile.vala, tests/classes-properties.vala, vapi/glib-2.0.vapi: create wrapper functions for signal handlers to support public signal handlers, fixes bug 508834 svn path=/trunk/; revision=983 --- diff --git a/ChangeLog b/ChangeLog index 4bb8dfe77..99c43f329 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-02-07 Jürg Billeter + + * vala/valasemanticanalyzer.vala, vala/valasignal.vala, + gobject/valaccodeassignmentbinding.vala, + gobject/valaccodegenerator.vala, + gobject/valaccodegeneratorinvocationexpression.vala, + gobject/valaccodegeneratorsourcefile.vala, + tests/classes-properties.vala, vapi/glib-2.0.vapi: create wrapper + functions for signal handlers to support public signal handlers, + fixes bug 508834 + 2008-02-06 Jürg Billeter * vala/parser.y, vala/valaarrayresizemethod.vala, diff --git a/gobject/valaccodeassignmentbinding.vala b/gobject/valaccodeassignmentbinding.vala index c63fa94c5..765fca151 100644 --- a/gobject/valaccodeassignmentbinding.vala +++ b/gobject/valaccodeassignmentbinding.vala @@ -195,7 +195,7 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { } // third resp. sixth argument: handler - ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback")); + ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (generate_signal_handler_wrapper (m, sig)), "GCallback")); if (m.instance) { // g_signal_connect_object or g_signal_handlers_disconnect_matched @@ -296,6 +296,109 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding { } } + private string generate_signal_handler_wrapper (Method m, Signal sig) { + string wrapper_name = "_%s_%s%s".printf (m.get_cname (), sig.parent_symbol.get_lower_case_cprefix (), sig.get_cname ()); + + if (!codegen.add_wrapper (wrapper_name)) { + // wrapper already defined + return wrapper_name; + } + + // declaration + + var function = new CCodeFunction (wrapper_name, m.return_type.get_cname ()); + function.modifiers = CCodeModifiers.STATIC; + m.ccodenode = function; + + var cparam_map = new HashMap (direct_hash, direct_equal); + + var cparam = new CCodeFormalParameter ("self", "gpointer"); + cparam_map.set (codegen.get_param_pos (-1), cparam); + + cparam = new CCodeFormalParameter ("sender", ((Typesymbol) sig.parent_symbol).get_cname () + "*"); + cparam_map.set (codegen.get_param_pos (0), cparam); + + var sig_params = sig.get_parameters (); + foreach (FormalParameter param in sig_params) { + // ensure that C code node has been generated + param.accept (codegen); + + cparam_map.set (codegen.get_param_pos (param.cparameter_position), (CCodeFormalParameter) param.ccodenode); + } + + // append C parameters in the right order + int last_pos = -1; + int min_pos; + while (true) { + min_pos = -1; + foreach (int pos in cparam_map.get_keys ()) { + if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { + min_pos = pos; + } + } + if (min_pos == -1) { + break; + } + function.add_parameter (cparam_map.get (min_pos)); + last_pos = min_pos; + } + + + // definition + + var carg_map = new HashMap (direct_hash, direct_equal); + + if (m.instance) { + carg_map.set (codegen.get_param_pos (m.cinstance_parameter_position), new CCodeIdentifier ("self")); + } + + int i = -1; + foreach (FormalParameter param in m.get_parameters ()) { + CCodeExpression arg; + if (i < 0) { + arg = new CCodeIdentifier ("sender"); + } else { + arg = new CCodeIdentifier (sig_params.get (i).name); + } + carg_map.set (codegen.get_param_pos (param.cparameter_position), arg); + i++; + } + + var ccall = new CCodeFunctionCall (new CCodeIdentifier (m.get_cname ())); + + // append C arguments in the right order + last_pos = -1; + while (true) { + min_pos = -1; + foreach (int pos in carg_map.get_keys ()) { + if (pos > last_pos && (min_pos == -1 || pos < min_pos)) { + min_pos = pos; + } + } + if (min_pos == -1) { + break; + } + ccall.add_argument (carg_map.get (min_pos)); + last_pos = min_pos; + } + + var block = new CCodeBlock (); + if (m.return_type is VoidType) { + block.add_statement (new CCodeExpressionStatement (ccall)); + } else { + block.add_statement (new CCodeReturnStatement (ccall)); + } + + // append to file + + codegen.source_type_member_declaration.append (function.copy ()); + + function.block = block; + codegen.source_type_member_definition.append (function); + + return wrapper_name; + } + private void emit_non_array_element_access () { // custom element access CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode; diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala index 776dd0d5f..4719bd54a 100644 --- a/gobject/valaccodegenerator.vala +++ b/gobject/valaccodegenerator.vala @@ -45,9 +45,9 @@ public class Vala.CCodeGenerator : CodeGenerator { CCodeFragment header_type_member_declaration; CCodeFragment source_begin; CCodeFragment source_include_directives; - CCodeFragment source_type_member_declaration; + public CCodeFragment source_type_member_declaration; CCodeFragment source_signal_marshaller_declaration; - CCodeFragment source_type_member_definition; + public CCodeFragment source_type_member_definition; CCodeFragment class_init_fragment; CCodeFragment instance_init_fragment; CCodeFragment instance_dispose_fragment; @@ -121,6 +121,8 @@ public class Vala.CCodeGenerator : CodeGenerator { private bool requires_array_move; private bool requires_strcmp0; + private Set wrappers; + public CCodeGenerator () { } @@ -3108,6 +3110,10 @@ public class Vala.CCodeGenerator : CodeGenerator { return ccomma; } + public bool add_wrapper (string wrapper_name) { + return wrappers.add (wrapper_name); + } + public override CodeBinding create_namespace_binding (Namespace! node) { return null; } diff --git a/gobject/valaccodegeneratorinvocationexpression.vala b/gobject/valaccodegeneratorinvocationexpression.vala index b38a82a90..97d0fdb29 100644 --- a/gobject/valaccodegeneratorinvocationexpression.vala +++ b/gobject/valaccodegeneratorinvocationexpression.vala @@ -539,7 +539,7 @@ public class Vala.CCodeGenerator { return carray_type; } - private int get_param_pos (double param_pos, bool ellipsis = false) { + public int get_param_pos (double param_pos, bool ellipsis = false) { if (!ellipsis) { if (param_pos >= 0) { return (int) (param_pos * 1000); diff --git a/gobject/valaccodegeneratorsourcefile.vala b/gobject/valaccodegeneratorsourcefile.vala index 40ff0804b..c04bb1517 100644 --- a/gobject/valaccodegeneratorsourcefile.vala +++ b/gobject/valaccodegeneratorsourcefile.vala @@ -193,7 +193,9 @@ public class Vala.CCodeGenerator { requires_array_free = false; requires_array_move = false; requires_strcmp0 = false; - + + wrappers = new HashSet (str_hash, str_equal); + header_begin.append (new CCodeIncludeDirective ("glib.h")); header_begin.append (new CCodeIncludeDirective ("glib-object.h")); if (context.basedir != null || context.library != null) { diff --git a/tests/classes-properties.vala b/tests/classes-properties.vala index 922e37a7e..b35440ed1 100644 --- a/tests/classes-properties.vala +++ b/tests/classes-properties.vala @@ -1,18 +1,13 @@ using GLib; public class Sample : Object { - private string automatic { - get; set; - } + private string automatic { get; set; } private string _name; + [Notify] public string name { get { return _name; } - - set { - _name = value; - notify("name"); - } + set { _name = value; } } private string _read_only; @@ -30,12 +25,8 @@ public class Sample : Object { public void run() { notify += (s, p) => { - /* FIXME Cast needed as signatures conflict for the - * notify method and the notify signal of GObject. - * See Bug 473804. - */ stdout.printf("property `%s' has changed!\n", - ((ParamSpec) p).name); + p.name); }; diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala index 7995452a7..a05edcf2d 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -2768,26 +2768,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor { Report.error (a.right.source_reference, "unsupported expression for signal handler"); return; } - - var m = (Method) a.right.symbol_reference; - - if (m.instance && m.access != SymbolAccessibility.PRIVATE) { - /* TODO: generate wrapper function */ - - ma.error = true; - Report.error (a.right.source_reference, "public instance methods not yet supported as signal handlers"); - return; - } - - if (m.instance) { - /* instance signal handlers must have the self - * parameter at the end - * do not use G_CONNECT_SWAPPED as this would - * rearrange the parameters for instance - * methods and non-instance methods - */ - m.cinstance_parameter_position = -1; - } } else if (ma.symbol_reference is Property) { var prop = (Property) ma.symbol_reference; diff --git a/vala/valasignal.vala b/vala/valasignal.vala index f22015c9e..17304e433 100644 --- a/vala/valasignal.vala +++ b/vala/valasignal.vala @@ -69,12 +69,15 @@ public class Vala.Signal : Member, Lockable { * @param param a formal parameter */ public void add_parameter (FormalParameter! param) { + // default C parameter position + param.cparameter_position = parameters.size + 1; + parameters.add (param); scope.add (param.name, param); } - public Collection get_parameters () { - return new ReadOnlyCollection (parameters); + public Gee.List get_parameters () { + return new ReadOnlyList (parameters); } /** diff --git a/vapi/glib-2.0.vapi b/vapi/glib-2.0.vapi index 69d148e03..28e48e193 100644 --- a/vapi/glib-2.0.vapi +++ b/vapi/glib-2.0.vapi @@ -735,13 +735,7 @@ namespace GLib { public virtual void finalize (); public virtual void constructed (); - /* FIXME The notify passes a ParamSpec where the - * wrapper expects a string. Fortunatly Vala doesn't - * verify signatures of signal handlers yet. - * See Bug 473804. - */ - [HasEmitter] - public signal void notify(string! property_name); + public signal void notify (ParamSpec pspec); public weak Object connect (string! signal_spec, ...); }