]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add further support for params arrays in constructors
authorRico Tzschichholz <ricotz@ubuntu.com>
Thu, 28 Jan 2021 11:12:53 +0000 (12:12 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Thu, 28 Jan 2021 12:00:24 +0000 (13:00 +0100)
In addition to 98ab3da89640b8b8a6c67044b4df1194672774bb

See https://gitlab.gnome.org/GNOME/vala/issues/128

codegen/valaccodearraymodule.vala
codegen/valaccodebasemodule.vala
codegen/valaccodemethodmodule.vala
tests/Makefile.am
tests/methods/params-array.vala
tests/semantic/params-array-objectcreation-multiple.test [new file with mode: 0644]
tests/semantic/params-array-objectcreation-struct-length.test [new file with mode: 0644]
vala/valacreationmethod.vala
vala/valamethod.vala
vala/valaobjectcreationexpression.vala

index 9fac7349ed340af02edfc170d71e01567a85ac3c..b2b2e7e1e7685cab3f8f860306e9a510fb35b0a5 100644 (file)
@@ -879,7 +879,8 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                return main_cparam;
        }
 
-       public override void append_params_array (LocalVariable local) {
+       public override void append_params_array (Method m) {
+               var local = m.params_array_var;
                var array_type = (ArrayType) local.variable_type;
 
                var local_length = new LocalVariable (array_type.length_type.copy (), get_array_length_cname (local.name, 1), null, local.source_reference);
@@ -913,11 +914,14 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
                if (context.profile == Profile.POSIX) {
                        cfile.add_include ("stdarg.h");
                }
-               ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local))));
-               var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
-               vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local))));
-               vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local))));
-               ccode.add_expression (vastart);
+
+               if (!(m is CreationMethod)) {
+                       ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_va_list_%s".printf (get_ccode_name (local))));
+                       var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
+                       vastart.add_argument (new CCodeIdentifier ("_va_list_%s".printf (get_ccode_name (local))));
+                       vastart.add_argument (new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local))));
+                       ccode.add_expression (vastart);
+               }
 
                ccode.add_assignment (get_local_cexpression (element), new CCodeIdentifier ("_first_%s".printf (get_ccode_name (local))));
                ccode.open_while (new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_local_cexpression (element), new CCodeConstant ("NULL")));
index 0c872775e5d82f4a104307b513ee9916f7a7b73a..9f570049b7afef64ed997dbc613e7fbba1c953c5 100644 (file)
@@ -717,7 +717,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
        public virtual void append_vala_array_length () {
        }
 
-       public virtual void append_params_array (LocalVariable local) {
+       public virtual void append_params_array (Method m) {
        }
 
        public void append_vala_clear_mutex (string typename, string funcprefix) {
index c14d76120b05d5bab8b6581e063a9866f3aed3cf..ae05c917a0405f97e5a2abf47a94244c83388e76 100644 (file)
@@ -539,7 +539,7 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                foreach (Parameter param in m.get_parameters ()) {
                                        if (param.ellipsis || param.params_array) {
                                                if (param.params_array) {
-                                                       append_params_array (m.params_array_var);
+                                                       append_params_array (m);
                                                }
                                                break;
                                        }
@@ -885,6 +885,8 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                cparam.modifiers = CCodeModifiers.FORMAT_ARG;
                        }
                } else {
+                       var va_list_name = "_vala_va_list";
+
                        // Add _first_* parameter for the params array parameter
                        if (param.params_array) {
                                var param_type = ((ArrayType) param.variable_type).element_type;
@@ -908,10 +910,12 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
 
                                cparam = new CCodeParameter ("_first_%s".printf (get_ccode_name (param)), ctypename);
                                cparam_map.set (get_param_pos (get_ccode_pos (param), false), cparam);
+
+                               va_list_name = "_va_list_%s".printf (get_ccode_name (param));
                        }
 
                        if (ellipses_to_valist) {
-                               cparam = new CCodeParameter ("_vala_va_list", "va_list");
+                               cparam = new CCodeParameter (va_list_name, "va_list");
                        } else {
                                cparam = new CCodeParameter.with_ellipsis ();
                        }
@@ -1287,9 +1291,16 @@ public abstract class Vala.CCodeMethodModule : CCodeStructModule {
                                }
                        }
 
+                       var carg = carg_map.get (second_last_pos);
+                       if (carg == null) {
+                               // params arrays have an implicit first argument, refer to the cparameter name
+                               carg = new CCodeIdentifier (cparam_map.get (second_last_pos).name);
+                               vcall.add_argument (carg);
+                       }
+
                        var va_start = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
                        va_start.add_argument (new CCodeIdentifier ("_vala_va_list_obj"));
-                       va_start.add_argument (carg_map.get (second_last_pos));
+                       va_start.add_argument (carg);
 
                        ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("_vala_va_list_obj"));
                        ccode.add_expression (va_start);
index a46e471937c69b1a3e0f4dcf7cb3ebcc648de67e..cadc9cb98a6febbef996f18f7acd609394577ec6 100644 (file)
@@ -1008,6 +1008,8 @@ TESTS = \
        semantic/parameter-ref-default.test \
        semantic/parameter-void.test \
        semantic/params-array-multiple.test \
+       semantic/params-array-objectcreation-multiple.test \
+       semantic/params-array-objectcreation-struct-length.test \
        semantic/params-array-struct-length.test \
        semantic/pointer-indirection-type-not-supported.test \
        semantic/pointer-indirection-void-not-supported.test \
index 3c76d7048262417c4121b870f672e586509e7670..12339e7d20048bfa4f85b3987ddc54aeadd161b0 100644 (file)
@@ -1,3 +1,40 @@
+class Foo {
+       public Foo (params string[] strv) {
+               assert (strv.length == 3);
+               assert (strv[0] == "foo");
+               assert (strv[1] == "bar");
+               assert (strv[2] == "manam");
+       }
+
+       public Foo.bar (params int[] intv) {
+               assert (intv.length == 3);
+               assert (intv[0] == 23);
+               assert (intv[1] == 42);
+               assert (intv[2] == 4711);
+       }
+
+       public Foo.manam (params Value?[] valuev) {
+               assert (valuev.length == 3);
+               assert (valuev[0] == "foo");
+               assert (valuev[1] == 4711);
+               assert (valuev[2] == 3.1415);
+       }
+
+       public Foo.manam_owned (params owned Value?[] valuev) {
+               assert (valuev.length == 3);
+               assert (valuev[0] == "foo");
+               assert (valuev[1] == 4711);
+               assert (valuev[2] == 3.1415);
+       }
+
+       public Foo.minim (params Variant[] variantv) {
+               assert (variantv.length == 3);
+               assert ((string) variantv[0] == "foo");
+               assert ((int) variantv[1] == 4711);
+               assert ((double) variantv[2] == 3.1415);
+       }
+}
+
 void foo (params string[] strv) {
        assert (strv.length == 3);
        assert (strv[0] == "foo");
@@ -34,6 +71,14 @@ void minim (params Variant[] variantv) {
 }
 
 void main () {
+       Foo f;
+
+       f = new Foo ("foo", "bar", "manam");
+       f = new Foo.bar (23, 42, 4711);
+       f = new Foo.manam ("foo", 4711, 3.1415);
+       f = new Foo.manam_owned ("foo", 4711, 3.1415);
+       f = new Foo.minim ("foo", 4711, 3.1415);
+
        foo ("foo", "bar", "manam");
        bar (23, 42, 4711);
        manam ("foo", 4711, 3.1415);
diff --git a/tests/semantic/params-array-objectcreation-multiple.test b/tests/semantic/params-array-objectcreation-multiple.test
new file mode 100644 (file)
index 0000000..b128e92
--- /dev/null
@@ -0,0 +1,9 @@
+Invalid Code
+
+class Foo {
+       public Foo (params string[] strv, params int[] intv) {
+       }
+}
+
+void main () {
+}
diff --git a/tests/semantic/params-array-objectcreation-struct-length.test b/tests/semantic/params-array-objectcreation-struct-length.test
new file mode 100644 (file)
index 0000000..b4cd001
--- /dev/null
@@ -0,0 +1,14 @@
+Invalid Code
+
+struct Foo {
+       public int i;
+       public string s;
+}
+
+class Bar {
+       public Bar (params Foo foov[3]) {
+       }
+}
+
+void main () {
+}
index c5a98dc08bd36aee8a043834d373ccc48db0cdeb..77b311f3163a063fe4c842a65ca340be9c6ea64c 100644 (file)
@@ -115,6 +115,31 @@ public class Vala.CreationMethod : Method {
                                Report.error (param.source_reference, "Named parameter required before `...'");
                        }
                        i++;
+
+                       // Add local variable to provide access to params arrays which will be constructed out of the given va-args
+                       if (param.params_array && body != null) {
+                               if (params_array_var != null) {
+                                       error = true;
+                                       Report.error (param.source_reference, "Only one params-array parameter is allowed");
+                                       continue;
+                               }
+                               if (!context.experimental) {
+                                       Report.warning (param.source_reference, "Support of params-arrays is experimental");
+                               }
+                               var type = (ArrayType) param.variable_type.copy ();
+                               type.element_type.value_owned = type.value_owned;
+                               type.value_owned = true;
+                               if (type.element_type.is_real_struct_type () && !type.element_type.nullable) {
+                                       error = true;
+                                       Report.error (param.source_reference, "Only nullable struct elements are supported in params-array");
+                               }
+                               if (type.length != null) {
+                                       error = true;
+                                       Report.error (param.source_reference, "Passing length to params-array is not supported yet");
+                               }
+                               params_array_var = new LocalVariable (type, param.name, null, param.source_reference);
+                               body.insert_statement (0, new DeclarationStatement (params_array_var, param.source_reference));
+                       }
                }
 
                if (error_types != null) {
index 335bf4224bfce0247ae2da1ddeec2a9dbd62fa28..4a76c5d39c9e65f608326fe5e0dfa838acf5d48d 100644 (file)
@@ -175,7 +175,7 @@ public class Vala.Method : Subroutine, Callable {
                }
        }
 
-       public LocalVariable? params_array_var { get; private set; }
+       public LocalVariable? params_array_var { get; protected set; }
 
        public weak Signal signal_reference { get; set; }
 
index 62e7b105ee9b39118cb5f5599d5dee7d45ffef5b..1f792f30ced00bc5a5fffc878df476f53deca231 100644 (file)
@@ -387,6 +387,18 @@ public class Vala.ObjectCreationExpression : Expression, CallableExpression {
                                        break;
                                }
 
+                               if (param.params_array) {
+                                       var array_type = (ArrayType) param.variable_type;
+                                       while (arg_it.next ()) {
+                                               Expression arg = arg_it.get ();
+
+                                               /* store expected type for callback parameters */
+                                               arg.target_type = array_type.element_type;
+                                               arg.target_type.value_owned = array_type.value_owned;
+                                       }
+                                       break;
+                               }
+
                                if (arg_it.next ()) {
                                        Expression arg = arg_it.get ();
 
@@ -415,7 +427,7 @@ public class Vala.ObjectCreationExpression : Expression, CallableExpression {
                                                // recreate iterator and skip to right position
                                                arg_it = argument_list.iterator ();
                                                foreach (Parameter param in m.get_parameters ()) {
-                                                       if (param.ellipsis) {
+                                                       if (param.ellipsis || param.params_array) {
                                                                break;
                                                        }
                                                        arg_it.next ();