[vala/wip/issue/839] WIP vala: Allow to access function pointers of .begin and .end methods



commit 9b92b3d1f875fcc1c504481354baf52cdc660f91
Author: Rico Tzschichholz <ricotz ubuntu com>
Date:   Sat Aug 24 23:36:40 2019 +0200

    WIP vala: Allow to access function pointers of .begin and .end methods

 codegen/valaccodeattribute.vala                | 12 +++++
 codegen/valaccodememberaccessmodule.vala       |  3 +-
 tests/Makefile.am                              |  1 +
 tests/asynchronous/begin-end-as-delegates.vala | 62 ++++++++++++++++++++++++++
 vala/valamethod.vala                           | 31 ++++++++++++-
 vala/valamethodtype.vala                       |  4 +-
 6 files changed, 108 insertions(+), 5 deletions(-)
---
diff --git a/codegen/valaccodeattribute.vala b/codegen/valaccodeattribute.vala
index 87d5142e8..73c8dbb27 100644
--- a/codegen/valaccodeattribute.vala
+++ b/codegen/valaccodeattribute.vala
@@ -717,6 +717,18 @@ public class Vala.CCodeAttribute : AttributeCache {
                                unowned Method m = (Method) sym;
                                if (m.is_async_callback) {
                                        return "%s_co".printf (get_ccode_real_name ((Method) 
m.parent_symbol));
+                               } else if (m.is_async_begin) {
+                                       if (m.parent_symbol is CreationMethod) {
+                                               return get_ccode_real_name ((Method) m.parent_symbol);
+                                       } else {
+                                               return get_ccode_name ((Method) m.parent_symbol);
+                                       }
+                               } else if (m.is_async_end) {
+                                       if (m.parent_symbol is CreationMethod) {
+                                               return get_ccode_finish_real_name ((Method) m.parent_symbol);
+                                       } else {
+                                               return get_ccode_finish_name ((Method) m.parent_symbol);
+                                       }
                                }
                                if (m.signal_reference != null) {
                                        return "%s%s".printf (get_ccode_lower_case_prefix (m.parent_symbol), 
get_ccode_lower_case_name (m.signal_reference));
diff --git a/codegen/valaccodememberaccessmodule.vala b/codegen/valaccodememberaccessmodule.vala
index 5ef5f4eb9..7c8770fc7 100644
--- a/codegen/valaccodememberaccessmodule.vala
+++ b/codegen/valaccodememberaccessmodule.vala
@@ -36,7 +36,8 @@ public abstract class Vala.CCodeMemberAccessModule : CCodeControlFlowModule {
                if (expr.symbol_reference is Method) {
                        var m = (Method) expr.symbol_reference;
 
-                       if (!(m is DynamicMethod || m is ArrayMoveMethod || m is ArrayResizeMethod || m is 
ArrayCopyMethod)) {
+                       if (!(m is DynamicMethod || m is ArrayMoveMethod || m is ArrayResizeMethod || m is 
ArrayCopyMethod)
+                           && !m.is_async_begin && !m.is_async_end) {
                                generate_method_declaration (m, cfile);
 
                                if (!m.external && m.external_package) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9e5190a5b..d3a8e9297 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -464,6 +464,7 @@ TESTS = \
        asynchronous/bug792660.vala \
        asynchronous/bug792942.vala \
        asynchronous/bug793158.vala \
+       asynchronous/begin-end-as-delegates.vala \
        asynchronous/catch-error-scope.vala \
        asynchronous/catch-in-finally.vala \
        asynchronous/closures.vala \
diff --git a/tests/asynchronous/begin-end-as-delegates.vala b/tests/asynchronous/begin-end-as-delegates.vala
new file mode 100644
index 000000000..e07e7c513
--- /dev/null
+++ b/tests/asynchronous/begin-end-as-delegates.vala
@@ -0,0 +1,62 @@
+[CCode (has_target = false)]
+delegate void FooBegin (int i, AsyncReadyCallback cb);
+[CCode (has_target = false)]
+delegate int FooEnd (AsyncResult res, out string s);
+
+async int foo (int i, out string s) {
+       s = "foo";
+       return i;
+}
+
+delegate void BarBegin (int i, AsyncReadyCallback cb);
+delegate int BarEnd (AsyncResult res, out string s);
+
+class Bar {
+       public async int bar (int i, out string s) {
+               s = "bar";
+               return i;
+       }
+}
+
+MainLoop loop;
+
+int count = 2;
+
+void main () {
+       loop = new MainLoop ();
+
+       {
+               FooBegin begin = foo.begin;
+               FooEnd end = foo.end;
+
+               begin (23, (o,a) => {
+                       string s;
+                       assert (end (a, out s) == 23);
+                       assert (s == "foo");
+
+                       count--;
+                       if (count <= 0)
+                               loop.quit ();
+                       }
+               });
+       }
+
+       {
+               var bar = new Bar ();
+               BarBegin begin = bar.bar.begin;
+               BarEnd end = bar.bar.end;
+
+               begin (42, (o,a) => {
+                       string s;
+                       assert (end (a, out s) == 42);
+                       assert (s == "bar");
+
+                       count--;
+                       if (count <= 0)
+                               loop.quit ();
+                       }
+               });
+       }
+
+       loop.run ();
+}
diff --git a/vala/valamethod.vala b/vala/valamethod.vala
index 60a1a3543..2a632677a 100644
--- a/vala/valamethod.vala
+++ b/vala/valamethod.vala
@@ -181,8 +181,12 @@ public class Vala.Method : Subroutine, Callable {
 
        public bool coroutine { get; set; }
 
+       public bool is_async_begin { get; set; }
+
        public bool is_async_callback { get; set; }
 
+       public bool is_async_end { get; set; }
+
        private List<Parameter> parameters = new ArrayList<Parameter> ();
        private List<Expression> preconditions;
        private List<Expression> postconditions;
@@ -195,6 +199,7 @@ public class Vala.Method : Subroutine, Callable {
        private DataType _base_interface_type;
        private bool base_methods_valid;
 
+       Method? begin_method;
        Method? callback_method;
        Method? end_method;
 
@@ -1094,14 +1099,36 @@ public class Vala.Method : Subroutine, Callable {
                return n;
        }
 
+       public Method get_begin_method () {
+               assert (this.coroutine);
+
+               if (begin_method == null) {
+                       begin_method = new Method ("begin", new VoidType (), source_reference);
+                       begin_method.access = access;
+                       begin_method.external = true;
+                       begin_method.binding = ((this is CreationMethod) ? MemberBinding.STATIC : binding);
+                       begin_method.owner = scope;
+                       begin_method.is_async_begin = true;
+                       foreach (var param in get_async_begin_parameters ()) {
+                               begin_method.add_parameter (param.copy ());
+                       }
+                       foreach (var param in get_type_parameters ()) {
+                               begin_method.add_type_parameter (param);
+                       }
+               }
+               return begin_method;
+       }
+
        public Method get_end_method () {
                assert (this.coroutine);
 
                if (end_method == null) {
-                       end_method = new Method ("end", return_type, source_reference);
-                       end_method.access = SymbolAccessibility.PUBLIC;
+                       end_method = new Method ("end", ((this is CreationMethod) ? 
SemanticAnalyzer.get_this_type (this) : return_type), source_reference);
+                       end_method.access = access;
                        end_method.external = true;
+                       end_method.binding = ((this is CreationMethod) ? MemberBinding.STATIC : binding);
                        end_method.owner = scope;
+                       end_method.is_async_end = true;
                        foreach (var param in get_async_end_parameters ()) {
                                end_method.add_parameter (param.copy ());
                        }
diff --git a/vala/valamethodtype.vala b/vala/valamethodtype.vala
index a2effdec6..16c92fce2 100644
--- a/vala/valamethodtype.vala
+++ b/vala/valamethodtype.vala
@@ -64,9 +64,9 @@ public class Vala.MethodType : CallableType {
 
        public override Symbol? get_member (string member_name) {
                if (method_symbol.coroutine && member_name == "begin") {
-                       return method_symbol;
+                       return method_symbol.get_begin_method ();
                } else if (method_symbol.coroutine && member_name == "end") {
-                       return method_symbol;
+                       return method_symbol.get_end_method ();
                } else if (method_symbol.coroutine && member_name == "callback") {
                        return method_symbol.get_callback_method ();
                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]