]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Handle synchronous out-parameters in async methods wip/async-out 701e703dbcddbfd94df81815da865c9ce8060e70 3/head
authorRico Tzschichholz <ricotz@ubuntu.com>
Tue, 5 Jun 2018 09:05:09 +0000 (11:05 +0200)
committerRico Tzschichholz <ricotz@ubuntu.com>
Tue, 5 Jun 2018 16:31:31 +0000 (18:31 +0200)
Although setting them is not supported yet.

Fixes https://gitlab.gnome.org/GNOME/vala/issues/636

codegen/valaccodeassignmentmodule.vala
codegen/valaccodebasemodule.vala
codegen/valaccodemethodmodule.vala
codegen/valagasyncmodule.vala
tests/Makefile.am
tests/asynchronous/sync-args.vala [new file with mode: 0644]
vala/valagirparser.vala
vala/valamethod.vala
vala/valaparameter.vala
vala/valausedattr.vala

index c8f24383ee9673caf41c23cb40da89ad7f1cdbde..4f9552443721c538f06ef4e0eb5f14e8555b0fd9 100644 (file)
@@ -183,6 +183,11 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
 
                bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine ();
 
+               if (capturing_parameter_in_coroutine && param.sync_arg) {
+                       Report.error (source_reference, "Assigning synchronous out-parameters of async methods is not supported yet.");
+                       return;
+               }
+
                var param_type = param.variable_type.copy ();
                if (param.captured || is_in_coroutine ()) {
                        if (!param_type.value_owned && !no_implicit_copy (param_type)) {
index 9147a5fa00f9f8278fbc8362af7eb43e0a3b35f3..e93d3e7954f99042b5cecdde414c8dc4d0823f7e 100644 (file)
@@ -4767,7 +4767,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                        param = params_it.get ();
                                        ellipsis = param.ellipsis;
                                        if (!ellipsis) {
-                                               if (param.direction == ParameterDirection.OUT) {
+                                               if (param.direction == ParameterDirection.OUT && !param.sync_arg) {
                                                        carg_map = out_arg_map;
                                                }
 
index 66e3ad1a70513ceadf95560973debdfd73678c64..3a02aa386c1cf979327e281b2d888c6e84cf5391 100644 (file)
@@ -1015,12 +1015,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                CCodeParameter? prev_cparam = null;
                foreach (Parameter param in m.get_parameters ()) {
-                       if (param.direction != ParameterDirection.OUT) {
+                       if (param.direction != ParameterDirection.OUT || param.sync_arg) {
                                if ((direction & 1) == 0) {
                                        // no in parameters
                                        continue;
                                }
-                       } else {
+                       } else if (!param.sync_arg) {
                                if ((direction & 2) == 0) {
                                        // no out parameters
                                        continue;
index 715c35f56de7c7f8b519a93151cfa30d68bc75c1..306438113f882e5c9588f0f1d238bac55ae3c48d 100644 (file)
@@ -51,6 +51,10 @@ public class Vala.GAsyncModule : GtkModule {
                }
 
                foreach (Parameter param in m.get_parameters ()) {
+                       if (param.direction == ParameterDirection.OUT && param.sync_arg) {
+                               continue;
+                       }
+
                        bool is_unowned_delegate = param.variable_type is DelegateType && !param.variable_type.value_owned;
 
                        var param_type = param.variable_type.copy ();
@@ -645,7 +649,7 @@ public class Vala.GAsyncModule : GtkModule {
 
                emit_context.push_symbol (m);
                foreach (Parameter param in m.get_parameters ()) {
-                       if (param.direction != ParameterDirection.IN) {
+                       if (param.direction != ParameterDirection.IN && !param.sync_arg) {
                                return_out_parameter (param);
                                if (!(param.variable_type is ValueType) || param.variable_type.nullable) {
                                        ccode.add_assignment (new CCodeMemberAccess.pointer (data_var, get_variable_cname (param.name)), new CCodeConstant ("NULL"));
index c05a68d51ecfe93021ef1cde228ff2c8aa521bef..a4179f0554a0d88a94e662a61228039cc4c023e1 100644 (file)
@@ -363,6 +363,7 @@ TESTS = \
        asynchronous/bug793158.vala \
        asynchronous/closures.vala \
        asynchronous/generator.vala \
+       asynchronous/sync-args.vala \
        asynchronous/yield.vala \
        generics/bug694765-1.vala \
        generics/bug694765-2.vala \
diff --git a/tests/asynchronous/sync-args.vala b/tests/asynchronous/sync-args.vala
new file mode 100644 (file)
index 0000000..8f4f49c
--- /dev/null
@@ -0,0 +1,44 @@
+public interface IFoo : Object {
+       public abstract async string ifunc (int i, out int out_j, string s) throws Error;
+}
+
+public class Foo : Object, IFoo {
+       public async string ifunc (int i, out int out_j, string s) throws Error {
+               assert (i == 23);
+               assert (s == "ifoo");
+               return "result_ifoo";
+       }
+
+       public virtual async string vfunc (int i, out int out_j, string s) throws Error {
+               assert (i == 42);
+               assert (s == "vfoo");
+               return "result_vfoo";
+       }
+
+       public async string func (int i, string s, [SyncArg] out int out_j) throws Error {
+               assert (i == 4711);
+               assert (s == "foo");
+               return "result_foo";
+       }
+}
+
+async void run () {
+       var foo = new Foo ();
+       int i;
+       foo.ifunc.begin (23, out i, "ifoo", (o, r) => {
+               var result = ((Foo) o).ifunc.end (r);
+               assert (result == "result_ifoo");
+       });
+       foo.vfunc.begin (42, out i, "vfoo", (o, r) => {
+               var result = ((Foo) o).ifunc.end (r);
+               assert (result == "result_vfoo");
+       });
+       foo.func.begin (4711, "foo", out i, (o, r) => {
+               var result = ((Foo) o).ifunc.end (r);
+               assert (result == "result_foo");
+       });
+}
+
+void main () {
+       run.begin ();
+}
index 95ad5c9d2ed5e9ab5d4c721551203ee4e9e2b4be..a6eb0590029bf18b166231e83519782249bce288 100644 (file)
@@ -4049,6 +4049,23 @@ public class Vala.GirParser : CodeVisitor {
 
                Method method = m;
 
+               if (m.coroutine) {
+                       var parameters = m.get_parameters ();
+                       bool requires_explicit_attribute = true;
+                       for (int i = parameters.size - 1; i >= 0; i--) {
+                               var param = parameters[i];
+                               if (param.direction == ParameterDirection.IN) {
+                                       requires_explicit_attribute = false;
+                               } else {
+                                       param.sync_arg = true;
+                                       if (requires_explicit_attribute) {
+                                               param.set_attribute ("SyncArg", true);
+                                               requires_explicit_attribute = false;
+                                       }
+                               }
+                       }
+               }
+
                if (finish_method_node != null && finish_method_node.symbol is Method) {
                        finish_method_node.process (this);
                        var finish_method = (Method) finish_method_node.symbol;
index e6d9fb59099aaaaf546659a0ed5562d5e50a88e8..d71e3dcb7660413cee94a6e0442d0aa79577da49 100644 (file)
@@ -728,6 +728,19 @@ public class Vala.Method : Subroutine, Callable {
                        Report.error (parameters[0].source_reference, "Named parameter required before `...'");
                }
 
+               // implicitly mark synchronous out-parameter as such
+               if (coroutine) {
+                       bool requires_attribute = false;
+                       for (int i = parameters.size - 1; i >= 0; i--) {
+                               var param = parameters[i];
+                               if (param.direction == ParameterDirection.IN) {
+                                       requires_attribute = true;
+                               } else if (requires_attribute) {
+                                       param.sync_arg = true;
+                               }
+                       }
+               }
+
                var optional_param = false;
                foreach (Parameter param in parameters) {
                        param.check (context);
@@ -1042,7 +1055,7 @@ public class Vala.Method : Subroutine, Callable {
                foreach (var param in parameters) {
                        if (param.ellipsis) {
                                ellipsis = param;
-                       } else if (param.direction == ParameterDirection.IN) {
+                       } else if (param.direction == ParameterDirection.IN || param.sync_arg) {
                                params.add (param);
                        }
                }
@@ -1080,7 +1093,7 @@ public class Vala.Method : Subroutine, Callable {
                params.add (result_param);
 
                foreach (var param in parameters) {
-                       if (param.direction == ParameterDirection.OUT) {
+                       if (param.direction == ParameterDirection.OUT && !param.sync_arg) {
                                params.add (param);
                        }
                }
index bfc340bc55aa66f0688d28bf994bbbfa4b225fb7..76f234f453e1f07532f59d800b9df09bc7a6d9a9 100644 (file)
@@ -50,11 +50,28 @@ public class Vala.Parameter : Variable {
                }
        }
 
+       public bool sync_arg {
+               get {
+                       return _sync_arg || get_attribute ("SyncArg") != null || (base_parameter != null && base_parameter.sync_arg);
+               }
+               set {
+                       if (!value) {
+                               set_attribute ("SyncArg", false);
+                               _sync_arg = false;
+                       } else if (direction != ParameterDirection.IN) {
+                               _sync_arg = true;
+                       }
+               }
+       }
+
        /**
         * The base parameter of this parameter relative to the base method.
         */
        public Parameter base_parameter { get; set; }
 
+
+       bool _sync_arg = false;
+
        /**
         * Creates a new formal parameter.
         *
index 999cfc8675583151814b11573db3eba2d4ac76c9..2764989143bba70052a8a110e667fd3ed2945df9 100644 (file)
@@ -74,6 +74,7 @@ public class Vala.UsedAttr : CodeVisitor {
                "PrintfFormat", "",
                "ScanfFormat", "",
                "FormatArg", "",
+               "SyncArg", "",
 
                "GtkChild", "name", "internal", "",
                "GtkTemplate", "ui", "",