]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Support connecting to and emitting detailed signals, fixes bug 536794
authorJürg Billeter <j@bitron.ch>
Mon, 23 Jun 2008 18:23:59 +0000 (18:23 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Mon, 23 Jun 2008 18:23:59 +0000 (18:23 +0000)
2008-06-23  Jürg Billeter  <j@bitron.ch>

* vala/valacfgbuilder.vala:
* vala/valaelementaccess.vala:
* vala/valanullchecker.vala:
* vala/valasemanticanalyzer.vala:
* vala/valasignal.vala:
* vala/valasymbolresolver.vala:
* gobject/valaccodeassignmentbinding.vala:
* gobject/valaccodeelementaccessbinding.vala:
* gobject/valaccodegenerator.vala:
* gobject/valaccodeinvocationexpressionbinding.vala:

Support connecting to and emitting detailed signals,
fixes bug 536794

svn path=/trunk/; revision=1639

ChangeLog
gobject/valaccodeassignmentbinding.vala
gobject/valaccodeelementaccessbinding.vala
gobject/valaccodegenerator.vala
gobject/valaccodeinvocationexpressionbinding.vala
vala/valacfgbuilder.vala
vala/valaelementaccess.vala
vala/valanullchecker.vala
vala/valasemanticanalyzer.vala
vala/valasignal.vala
vala/valasymbolresolver.vala

index 22044b28894e8560c836daf73a8a09e99a2d01c0..2f1669ef5b35fa8f1333f8d9870be01fbee1f06c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2008-06-23  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valacfgbuilder.vala:
+       * vala/valaelementaccess.vala:
+       * vala/valanullchecker.vala:
+       * vala/valasemanticanalyzer.vala:
+       * vala/valasignal.vala:
+       * vala/valasymbolresolver.vala:
+       * gobject/valaccodeassignmentbinding.vala:
+       * gobject/valaccodeelementaccessbinding.vala:
+       * gobject/valaccodegenerator.vala:
+       * gobject/valaccodeinvocationexpressionbinding.vala:
+
+       Support connecting to and emitting detailed signals,
+       fixes bug 536794
+
 2008-06-23  Jürg Billeter  <j@bitron.ch>
 
        * vala/valaattribute.vala:
index 25064650da64f618eeb401933dae48d0baf5cf13..e0a927965d8ec279726de8afa17316443c4d04c4 100644 (file)
@@ -93,8 +93,6 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
        }
 
        private void emit_signal_assignment () {
-               var ma = assignment.left as MemberAccess;
-
                var sig = (Signal) assignment.left.symbol_reference;
                
                var m = (Method) assignment.right.symbol_reference;
@@ -126,7 +124,23 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
 
                var ccall = new CCodeFunctionCall (new CCodeIdentifier (connect_func));
 
+               string signal_detail = null;
+
                // first argument: instance of sender
+               MemberAccess ma;
+               if (assignment.left is ElementAccess) {
+                       var ea = (ElementAccess) assignment.left;
+                       ma = (MemberAccess) ea.container;
+                       var detail_expr = ea.get_indices ().get (0) as StringLiteral;
+                       if (detail_expr == null) {
+                               assignment.error = true;
+                               Report.error (detail_expr.source_reference, "internal error: only literal string details supported");
+                               return;
+                       }
+                       signal_detail = detail_expr.eval ();
+               } else {
+                       ma = (MemberAccess) assignment.left;
+               }
                if (ma.inner != null) {
                        ccall.add_argument ((CCodeExpression) ma.inner.ccodenode);
                } else {
@@ -142,7 +156,7 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
                        // g_signal_connect_object or g_signal_connect
 
                        // second argument: signal name
-                       ccall.add_argument (sig.get_canonical_cconstant ());
+                       ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
                } else {
                        // g_signal_handlers_disconnect_matched
 
index 78cf7279e2f282b2671c933e150f32c5a37ffda5..2a3d4e1c9a4035b08045a8ff5fbe414378ed21db 100644 (file)
@@ -87,6 +87,24 @@ public class Vala.CCodeElementAccessBinding : CCodeExpressionBinding {
                        get_ccall.add_argument (cindex);
 
                        codenode = codegen.convert_from_generic_pointer (get_ccall, expr.value_type);
+               } else if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+                       // detailed signal emission
+                       var sig = (Signal) expr.symbol_reference;
+                       var ma = (MemberAccess) expr.container;
+
+                       var detail_expr = expr.get_indices ().get (0) as StringLiteral;
+                       string signal_detail = detail_expr.eval ();
+                       
+                       var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+
+                       // FIXME: use C cast if debugging disabled
+                       var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
+                       ccast.add_argument ((CCodeExpression) ma.inner.ccodenode);
+                       ccall.add_argument (ccast);
+
+                       ccall.add_argument (sig.get_canonical_cconstant (signal_detail));
+                       
+                       codenode = ccall;
                } else {
                        // access to element in an array
                        for (int i = 1; i < rank; i++) {
index 17dd2450904a3e99bedb0712918dda0cd0f2cbfd..e47eaddb6a9b6dfb7761f4637105dab74a3d3682 100644 (file)
@@ -2895,6 +2895,8 @@ public class Vala.CCodeGenerator : CodeGenerator {
        }
 
        public override void visit_element_access (ElementAccess expr) {
+               expr.accept_children (this);
+
                code_binding (expr).emit ();
        }
 
index 8c85067f22e370afaff723f127b60ace0c6fb167..dab917104833179de9ed50ac11a3e78872b5b7ae 100644 (file)
@@ -43,18 +43,13 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
                Method m = null;
                Gee.List<FormalParameter> params;
                
-               if (!(expr.call is MemberAccess)) {
-                       expr.error = true;
-                       Report.error (expr.source_reference, "unsupported method invocation");
-                       return;
-               }
-               
-               var ma = (MemberAccess) expr.call;
+               var ma = expr.call as MemberAccess;
                
                var itype = expr.call.value_type;
                params = itype.get_parameters ();
                
                if (itype is MethodType) {
+                       assert (ma != null);
                        m = ((MethodType) itype).method_symbol;
                } else if (itype is SignalType) {
                        ccall = (CCodeFunctionCall) expr.call.ccodenode;
index fa81ac448c59891ae172fbe55a9805550550216e..13ba9fd924b8202a8ebc2fc364d17a18c5c67f3a 100644 (file)
@@ -209,7 +209,7 @@ public class Vala.CFGBuilder : CodeVisitor {
                if (stmt.expression is InvocationExpression) {
                        var expr = (InvocationExpression) stmt.expression;
                        var ma = expr.call as MemberAccess;
-                       if (ma.symbol_reference != null && ma.symbol_reference.get_attribute ("NoReturn") != null) {
+                       if (ma != null && ma.symbol_reference != null && ma.symbol_reference.get_attribute ("NoReturn") != null) {
                                current_block = null;
                                unreachable_reported = false;
                                return;
index 45c7ada84667049bf78ada552312a223c93c5747..b8d5c1a6678eaa9ca9ce204c1842fef1e4431ad2 100644 (file)
@@ -53,14 +53,16 @@ public class Vala.ElementAccess : Expression {
        }
        
        public override void accept (CodeVisitor visitor) {
+               visitor.visit_element_access (this);
+
+               visitor.visit_expression (this);
+       }
+
+       public override void accept_children (CodeVisitor visitor) {
                container.accept (visitor);
                foreach (Expression e in indices) {
                        e.accept (visitor);
                }
-
-               visitor.visit_element_access (this);
-
-               visitor.visit_expression (this);
        }
 
        public override void replace_expression (Expression old_node, Expression new_node) {
index b081ded0ebd3b2c178af722ea4d61bbcfa23ea9c..738dbfc581f64b1ce5459feef3e16ed1b987392b 100644 (file)
@@ -205,6 +205,8 @@ public class Vala.NullChecker : CodeVisitor {
        }
 
        public override void visit_element_access (ElementAccess expr) {
+               expr.accept_children (this);
+
                check_non_null (expr.container);
        }
 
index 230e4291db098845a5eef2d7f20f7bf3f257f5e5..2407dc98ba760ce06368224b13cfeef0bb7529d7 100644 (file)
@@ -2453,6 +2453,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_element_access (ElementAccess expr) {
+               expr.container.accept (this);
+
                if (expr.container.value_type == null) {
                        /* don't proceed if a child expression failed */
                        expr.error = true;
@@ -2461,6 +2463,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                var container_type = expr.container.value_type.data_type;
 
+               if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+                       // signal detail access
+                       if (expr.get_indices ().size != 1) {
+                               expr.error = true;
+                               Report.error (expr.source_reference, "Element access with more than one dimension is not supported for signals");
+                               return;
+                       }
+                       expr.get_indices ().get (0).target_type = string_type.copy ();
+               }
+
+               foreach (Expression index in expr.get_indices ()) {
+                       index.accept (this);
+               }
+
                bool index_int_type_check = true;
 
                var pointer_type = expr.container.value_type as PointerType;
@@ -2524,6 +2540,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                // get () returns owned value, set () accepts unowned value
                                expr.value_type.value_owned = false;
                        }
+               } else if (expr.container is MemberAccess && expr.container.symbol_reference is Signal) {
+                       index_int_type_check = false;
+
+                       expr.symbol_reference = expr.container.symbol_reference;
+                       expr.value_type = expr.container.value_type;
                } else {
                        expr.error = true;
                        Report.error (expr.source_reference, "The expression `%s' does not denote an Array".printf (expr.container.value_type.to_string ()));
@@ -3378,7 +3399,15 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                a.right.target_type = ma.value_type;
                        }
                } else if (a.left is ElementAccess) {
-                       a.right.target_type = a.left.value_type;
+                       var ea = (ElementAccess) a.left;
+
+                       if (ea.container is MemberAccess && ea.container.symbol_reference is Signal) {
+                               var ma = (MemberAccess) ea.container;
+                               var sig = (Signal) ea.container.symbol_reference;
+                               a.right.target_type = new DelegateType (sig.get_delegate (ma.inner.value_type));
+                       } else {
+                               a.right.target_type = a.left.value_type;
+                       }
                } else if (a.left is PointerIndirection) {
                        a.right.target_type = a.left.value_type;
                } else {
@@ -3439,40 +3468,40 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        }
                }
 
-               if (a.left is MemberAccess) {
-                       var ma = (MemberAccess) a.left;
+               if (a.left.symbol_reference is Signal) {
+                       var sig = (Signal) a.left.symbol_reference;
 
-                       if (ma.symbol_reference is Signal) {
-                               var sig = (Signal) ma.symbol_reference;
+                       var m = a.right.symbol_reference as Method;
 
-                               var m = a.right.symbol_reference as Method;
+                       if (m == null) {
+                               a.error = true;
+                               Report.error (a.right.source_reference, "unsupported expression for signal handler");
+                               return;
+                       }
 
-                               if (m == null) {
-                                       a.error = true;
-                                       Report.error (a.right.source_reference, "unsupported expression for signal handler");
-                                       return;
+                       var dynamic_sig = sig as DynamicSignal;
+                       if (dynamic_sig != null) {
+                               bool first = true;
+                               foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
+                                       if (first) {
+                                               // skip sender parameter
+                                               first = false;
+                                       } else {
+                                               dynamic_sig.add_parameter (param);
+                                       }
                                }
+                               a.right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
+                       } else if (!a.right.value_type.compatible (a.right.target_type)) {
+                               var delegate_type = (DelegateType) a.right.target_type;
 
-                               var dynamic_sig = sig as DynamicSignal;
-                               if (dynamic_sig != null) {
-                                       bool first = true;
-                                       foreach (FormalParameter param in dynamic_sig.handler.value_type.get_parameters ()) {
-                                               if (first) {
-                                                       // skip sender parameter
-                                                       first = false;
-                                               } else {
-                                                       dynamic_sig.add_parameter (param);
-                                               }
-                                       }
-                                       a.right.target_type = new DelegateType (sig.get_delegate (new ObjectType ((ObjectTypeSymbol) sig.parent_symbol)));
-                               } else if (!a.right.value_type.compatible (a.right.target_type)) {
-                                       var delegate_type = (DelegateType) a.right.target_type;
+                               a.error = true;
+                               Report.error (a.right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (a.right.value_type.to_string (), a.right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
+                               return;
+                       }
+               } else if (a.left is MemberAccess) {
+                       var ma = (MemberAccess) a.left;
 
-                                       a.error = true;
-                                       Report.error (a.right.source_reference, "method `%s' is incompatible with signal `%s', expected `%s'".printf (a.right.value_type.to_string (), a.right.target_type.to_string (), delegate_type.delegate_symbol.get_prototype_string (m.name)));
-                                       return;
-                               }
-                       } else if (ma.symbol_reference is Property) {
+                       if (ma.symbol_reference is Property) {
                                var prop = (Property) ma.symbol_reference;
 
                                var dynamic_prop = prop as DynamicProperty;
index 4f6d69a3c64d2915fddb986d1303df8963249204..9a44d4bc0c95fe80f6763df7e2df21a61e15488f 100644 (file)
@@ -66,9 +66,9 @@ public class Vala.Signal : Member, Lockable {
         * @return            newly created signal
         */
        public Signal (string name, DataType return_type, SourceReference? source_reference = null) {
+               this.name = name;
                this.return_type = return_type;
                this.source_reference = source_reference;
-               this.name = name;
        }
        
        /**
@@ -137,7 +137,7 @@ public class Vala.Signal : Member, Lockable {
         *
         * @return string literal to be used in C code
         */
-       public CCodeConstant get_canonical_cconstant () {
+       public CCodeConstant get_canonical_cconstant (string? detail = null) {
                var str = new StringBuilder ("\"");
                
                string i = name;
@@ -152,7 +152,12 @@ public class Vala.Signal : Member, Lockable {
                        
                        i = i.next_char ();
                }
-               
+
+               if (detail != null) {
+                       str.append ("::");
+                       str.append (detail);
+               }
+
                str.append_c ('"');
                
                return new CCodeConstant (str.str);
index 42f7b2074e3d03a455b20bf07386298ce5ca40c0..84a417efee42c3e53a2cf0f80907d395604498e6 100644 (file)
@@ -361,6 +361,10 @@ public class Vala.SymbolResolver : CodeVisitor {
                expr.accept_children (this);
        }
 
+       public override void visit_element_access (ElementAccess expr) {
+               expr.accept_children (this);
+       }
+
        public override void visit_object_creation_expression (ObjectCreationExpression expr) {
                expr.accept_children (this);
        }