]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support virtual default handler for signals
authorJürg Billeter <j@bitron.ch>
Tue, 28 Jul 2009 15:20:37 +0000 (17:20 +0200)
committerJürg Billeter <j@bitron.ch>
Tue, 28 Jul 2009 15:51:47 +0000 (17:51 +0200)
Based on patch by Yu Feng, fixes part of 571685.

codegen/valaccodemethodcallmodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagsignalmodule.vala
codegen/valagtypemodule.vala
vala/valamethod.vala
vala/valaparser.vala
vala/valasignal.vala

index 8fc87db1bc0042280f1da03e7001eef9f5a45773..4cf641d4ee7d06cd30ad6d381f3217f3a46f9080 100644 (file)
@@ -53,7 +53,7 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
                } else if (itype is SignalType) {
                        var sig_type = (SignalType) itype;
                        if (ma != null && ma.inner is BaseAccess && sig_type.signal_symbol.is_virtual) {
-                               m = sig_type.signal_symbol.get_method_handler ();
+                               m = sig_type.signal_symbol.default_handler;
                        } else {
                                ccall = (CCodeFunctionCall) expr.call.ccodenode;
                        }
index d76fbce168831825064c5f87da10b9b1934cafee..d8342a6f113dab0b0d4639e45d5c6181dc1350de 100644 (file)
@@ -599,7 +599,12 @@ internal class Vala.CCodeMethodModule : CCodeStructModule {
                        }
                }
 
-               if ((m.is_abstract || m.is_virtual) && !m.coroutine) {
+               if ((m.is_abstract || m.is_virtual) && !m.coroutine &&
+               /* If the method is a signal handler, the declaration
+                * is not needed. -- the name should be reserved for the
+                * emitter! */
+                           m.signal_reference == null) {
+
                        cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
                        var carg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
 
index f4ed94d709270653633d1f010ec94cf8131039f4..fe7c8649913529ae629f6da0d197a061567f6fef 100644 (file)
@@ -355,10 +355,18 @@ internal class Vala.GSignalModule : GObjectModule {
 
        public override CCodeFunctionCall get_signal_creation (Signal sig, TypeSymbol type) {   
                var csignew = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_new"));
+               var cl = sig.parent_symbol as Class;
                csignew.add_argument (new CCodeConstant ("\"%s\"".printf (sig.get_cname ())));
                csignew.add_argument (new CCodeIdentifier (type.get_type_id ()));
                csignew.add_argument (new CCodeConstant ("G_SIGNAL_RUN_LAST"));
-               csignew.add_argument (new CCodeConstant ("0"));
+               if (sig.default_handler == null) {
+                       csignew.add_argument (new CCodeConstant ("0"));
+               } else {
+                       var struct_offset = new CCodeFunctionCall (new CCodeIdentifier ("G_STRUCT_OFFSET"));
+                       struct_offset.add_argument (new CCodeIdentifier ("%sClass".printf (cl.get_cname ())));
+                       struct_offset.add_argument (new CCodeIdentifier (sig.default_handler.vfunc_name));
+                       csignew.add_argument (struct_offset);
+               }
                csignew.add_argument (new CCodeConstant ("NULL"));
                csignew.add_argument (new CCodeConstant ("NULL"));
 
@@ -608,7 +616,7 @@ internal class Vala.GSignalModule : GObjectModule {
                        var cl = (TypeSymbol) sig.parent_symbol;
                        
                        if (expr.inner is BaseAccess && sig.is_virtual) {
-                               var m = sig.get_method_handler ();
+                               var m = sig.default_handler;
                                var base_class = (Class) m.parent_symbol;
                                var vcast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (base_class.get_upper_case_cname (null))));
                                vcast.add_argument (new CCodeIdentifier ("%s_parent_class".printf (current_class.get_lower_case_cname (null))));
index e5bf70e53e7b7a54714b30fe8f7573d22955b03c..81573a6906cb0348803ef495b2990419a4a78bc0 100644 (file)
@@ -206,6 +206,12 @@ internal class Vala.GTypeModule : GErrorModule {
                        generate_virtual_method_declaration (m, decl_space, type_struct);
                }
 
+               foreach (Signal sig in cl.get_signals ()) {
+                       if (sig.default_handler != null) {
+                               generate_virtual_method_declaration (sig.default_handler, decl_space, type_struct);
+                       }
+               }
+
                foreach (Property prop in cl.get_properties ()) {
                        if (!prop.is_abstract && !prop.is_virtual) {
                                continue;
@@ -1140,6 +1146,16 @@ internal class Vala.GTypeModule : GErrorModule {
                        init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, m.base_method.vfunc_name), new CCodeIdentifier (m.get_real_cname ()))));
                }
 
+               /* connect default signal handlers */
+               foreach (Signal sig in cl.get_signals ()) {
+                       if (sig.default_handler == null) {
+                               continue;
+                       }
+                       var ccast = new CCodeFunctionCall (new CCodeIdentifier ("%s_CLASS".printf (cl.get_upper_case_cname (null))));
+                       ccast.add_argument (new CCodeIdentifier ("klass"));
+                       init_block.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (ccast, sig.default_handler.vfunc_name), new CCodeIdentifier (sig.default_handler.get_real_cname ()))));
+               }
+
                /* connect overridden properties */
                foreach (Property prop in cl.get_properties ()) {
                        if (prop.base_property == null) {
index 5fa7dd08bde2ac41794ba25beb6a668aa6769cfe..79e9d5c00f15005422c19210eaa519da451ef079 100644 (file)
@@ -593,7 +593,7 @@ public class Vala.Method : Member {
                } else if (sym is Signal) {
                        var sig = (Signal) sym;
                        if (sig.is_virtual) {
-                               var base_method = sig.get_method_handler ();
+                               var base_method = sig.default_handler;
                                string invalid_match;
                                if (!compatible (base_method, out invalid_match)) {
                                        error = true;
index 88dacd5455f27edfaca9985b3adbbde4651707f0..93e5cbf328991af8279c5bceaf9bceea5d18d585 100644 (file)
@@ -2390,7 +2390,10 @@ public class Vala.Parser : CodeVisitor {
                        } while (accept (TokenType.COMMA));
                }
                expect (TokenType.CLOSE_PARENS);
-               expect (TokenType.SEMICOLON);
+               if (!accept (TokenType.SEMICOLON)) {
+                       sig.body = parse_block ();
+               }
+
                return sig;
        }
 
index 9b85e89b901f736d2af6ccb8e330cc2cc9d2672f..3a69f598fc842e16b37267f02e0073aaa339a95d 100644 (file)
@@ -38,6 +38,16 @@ public class Vala.Signal : Member, Lockable {
                }
        }
 
+       public Block body {
+               get { return _body; }
+               set {
+                       _body = value;
+                       if (_body != null) {
+                               _body.owner = scope;
+                       }
+               }
+       }
+
        /**
         * Specifies whether this signal has an emitter wrapper function.
         */
@@ -49,7 +59,11 @@ public class Vala.Signal : Member, Lockable {
        public bool is_virtual { get; set; }
 
        private Gee.List<FormalParameter> parameters = new ArrayList<FormalParameter> ();
-       private Method generated_method;
+       /**
+        * Refers to the default signal handler, which is an anonymous
+        * function in the scope.
+        * */
+       public Method default_handler { get; private set; }
 
        private string cname;
        
@@ -57,6 +71,8 @@ public class Vala.Signal : Member, Lockable {
 
        private DataType _return_type;
 
+       private Block _body;
+
        /**
         * Creates a new signal.
         *
@@ -179,6 +195,9 @@ public class Vala.Signal : Member, Lockable {
                foreach (FormalParameter param in parameters) {
                        param.accept (visitor);
                }
+               if (default_handler != null) {
+                       default_handler.accept (visitor);
+               }
        }
 
        /**
@@ -206,26 +225,6 @@ public class Vala.Signal : Member, Lockable {
                }
        }
 
-       public Method get_method_handler () {
-               assert (is_virtual);
-
-               if (generated_method == null) {
-                       generated_method = new Method (name, return_type, source_reference);
-                       generated_method.access = access;
-                       generated_method.is_virtual = true;
-                       generated_method.vfunc_name = name;
-                       generated_method.signal_reference = this;
-
-                       foreach (FormalParameter param in parameters) {
-                               generated_method.add_parameter (param);
-                       }
-
-                       parent_symbol.scope.add (null, generated_method);
-               }
-               
-               return generated_method;
-       }
-
        public override bool check (SemanticAnalyzer analyzer) {
                if (checked) {
                        return !error;
@@ -241,6 +240,26 @@ public class Vala.Signal : Member, Lockable {
                        param.check (analyzer);
                }
 
+               if (!is_virtual && body != null) {
+                       Report.error (source_reference, "Only virtual signals can have a default signal handler body");
+               }
+
+
+               if (is_virtual) {
+                       default_handler = new Method (name, return_type, source_reference);
+                       default_handler.access = access;
+                       default_handler.is_virtual = true;
+                       default_handler.vfunc_name = name;
+                       default_handler.signal_reference = this;
+                       default_handler.body = body;
+
+                       foreach (FormalParameter param in parameters) {
+                               default_handler.add_parameter (param);
+                       }
+
+                       parent_symbol.scope.add (null, default_handler);
+                       default_handler.check (analyzer);
+               }
                return !error;
        }
 }