[vala/0.48] vala: Support struct initializer list in non-constant array



commit 9b86647698b33ae10bfba3e87b7ca6f093482b81
Author: Simon Werbeck <simon werbeck gmail com>
Date:   Tue Mar 24 17:35:09 2020 +0100

    vala: Support struct initializer list in non-constant array
    
    A struct initializer list contained in an array initializer list is now
    transformed to a struct creation expression. The pre-existing logic
    ensures that constant expressions are not transformed.
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/949

 tests/Makefile.am                                  |  1 +
 .../structs/struct-initializer-list-in-array.vala  | 24 +++++++++++++++++++
 vala/valaarraycreationexpression.vala              |  2 +-
 vala/valainitializerlist.vala                      | 28 +++++++++++++++++++---
 4 files changed, 51 insertions(+), 4 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7a6d37d8f..c7d6e4554 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -259,6 +259,7 @@ TESTS = \
        structs/struct_only.vala \
        structs/struct-base-types.vala \
        structs/struct-empty-still.test \
+       structs/struct-initializer-list-in-array.vala \
        structs/struct-no-gtype.vala \
        structs/struct-no-gtype-inherit.vala \
        structs/struct-static-field-initializer.vala \
diff --git a/tests/structs/struct-initializer-list-in-array.vala 
b/tests/structs/struct-initializer-list-in-array.vala
new file mode 100755
index 000000000..a37271b99
--- /dev/null
+++ b/tests/structs/struct-initializer-list-in-array.vala
@@ -0,0 +1,24 @@
+struct Foo {
+       public string s;
+       public Bar b;
+       public bool[] ba;
+       public int i;
+}
+
+struct Bar {
+       public string s;
+       public int i;
+}
+
+void main () {
+       Foo[] foos = {
+               { "foo", { "foo", 42 }, { true }, 23 },
+               { "bar", { "bar", 4711 }, { false }, 42 },
+       };
+
+       var f = foos[0];
+       assert (f.i == 23 && f.s == "foo" && f.b.s == "foo" && f.ba[0]);
+
+       f = foos[1];
+       assert (f.i == 42 && f.s == "bar" && f.b.i == 4711 && !f.ba[0]);
+}
diff --git a/vala/valaarraycreationexpression.vala b/vala/valaarraycreationexpression.vala
index 841d8db42..c4b9c7a60 100644
--- a/vala/valaarraycreationexpression.vala
+++ b/vala/valaarraycreationexpression.vala
@@ -201,7 +201,7 @@ public class Vala.ArrayCreationExpression : Expression {
 
                int subsize = -1;
                foreach (Expression e in il.get_initializers ()) {
-                       if (e is InitializerList) {
+                       if (e is InitializerList && e.target_type is ArrayType) {
                                if (rank == 1) {
                                        il.error = true;
                                        e.error = true;
diff --git a/vala/valainitializerlist.vala b/vala/valainitializerlist.vala
index 50d1ed487..8372be3cd 100644
--- a/vala/valainitializerlist.vala
+++ b/vala/valainitializerlist.vala
@@ -194,6 +194,17 @@ public class Vala.InitializerList : Expression {
                                st = st.base_struct;
                        }
 
+                       var in_array_creation_initializer = parent_node is InitializerList && 
parent_node.parent_node is ArrayCreationExpression;
+                       ObjectCreationExpression? struct_creation = null;
+                       if (in_array_creation_initializer) {
+                               var ma = new MemberAccess.simple (st.name, source_reference);
+                               ma.creation_member = true;
+                               ma.symbol_reference = st;
+                               struct_creation = new ObjectCreationExpression (ma, source_reference);
+                               struct_creation.target_type = target_type.copy ();
+                               struct_creation.struct_creation = true;
+                       }
+
                        var field_it = st.get_fields ().iterator ();
                        foreach (Expression e in get_initializers ()) {
                                Field field = null;
@@ -210,11 +221,22 @@ public class Vala.InitializerList : Expression {
                                        }
                                }
 
-                               e.target_type = field.variable_type.copy ();
-                               if (!target_type.value_owned) {
-                                       e.target_type.value_owned = false;
+                               if (in_array_creation_initializer) {
+                                       var member_init = new MemberInitializer (field.name, e, 
e.source_reference);
+                                       struct_creation.add_member_initializer (member_init);
+                               } else {
+                                       e.target_type = field.variable_type.copy ();
+                                       if (!target_type.value_owned) {
+                                               e.target_type.value_owned = false;
+                                       }
                                }
                        }
+
+                       if (in_array_creation_initializer) {
+                               parent_node.replace_expression (this, struct_creation);
+                               checked = false;
+                               return struct_creation.check (context);
+                       }
                } else {
                        error = true;
                        Report.error (source_reference, "initializer list used for `%s', which is neither 
array nor struct".printf (target_type.to_string ()));


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