[vala/0.48] vala: Transform assignment of an array element as needed



commit d67eddd6649ef449d1847b290579c461b2963dd2
Author: wxx <769218589 qq com>
Date:   Wed Dec 1 02:54:04 2021 +0800

    vala: Transform assignment of an array element as needed
    
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/889
    Fixes https://gitlab.gnome.org/GNOME/vala/issues/1258

 tests/Makefile.am                             |  2 ++
 tests/arrays/element-nullable-assignment.vala | 11 +++++++++
 tests/basic-types/string-array-append.vala    | 12 +++++++++
 vala/valaassignment.vala                      | 35 +++++++++++++++++++++------
 4 files changed, 53 insertions(+), 7 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index f01ad7079..0dd5fc9d4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -49,6 +49,7 @@ TESTS = \
        basic-types/custom-types.vala \
        basic-types/default-gtype.vala \
        basic-types/strings.vala \
+       basic-types/string-array-append.vala \
        basic-types/string-concat-null.test \
        basic-types/arrays.vala \
        basic-types/arrays-generics.vala \
@@ -110,6 +111,7 @@ TESTS = \
        arrays/class-field-initializer.vala \
        arrays/class-field-length-cname.vala \
        arrays/constant-element-access.vala \
+       arrays/element-nullable-assignment.vala \
        arrays/empty-length-0.vala \
        arrays/expression-bracket.test \
        arrays/fixed-length-init0-not-allowed.vala \
diff --git a/tests/arrays/element-nullable-assignment.vala b/tests/arrays/element-nullable-assignment.vala
new file mode 100644
index 000000000..29dc2950e
--- /dev/null
+++ b/tests/arrays/element-nullable-assignment.vala
@@ -0,0 +1,11 @@
+void main () {
+       int?[] foo = { 23, 42, 4711 };
+
+       foo[0] += 1;
+       foo[1] *= 3;
+       foo[2] -= 2;
+
+       assert (foo[0] == 24);
+       assert (foo[1] == 126);
+       assert (foo[2] == 4709);
+}
diff --git a/tests/basic-types/string-array-append.vala b/tests/basic-types/string-array-append.vala
new file mode 100644
index 000000000..4b1ae328e
--- /dev/null
+++ b/tests/basic-types/string-array-append.vala
@@ -0,0 +1,12 @@
+void main () {
+       string[] foo = { "foo", "bar", "foo bar" };
+
+       foo[0] += "abc";
+       foo[1] += 123.to_string ();
+       foo[2] += " abc" + 123.to_string ();
+
+       assert (foo[0] == "fooabc");
+       assert (foo[1] == "bar123");
+       assert (foo[2] == "foo bar abc123");
+}
+
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index b386f7c4c..676157b8d 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -223,13 +223,36 @@ public class Vala.Assignment : Expression {
                }
 
                unowned MemberAccess? ma = left as MemberAccess;
-               if (operator != AssignmentOperator.SIMPLE && ma != null
-                   && !(left.value_type.is_non_null_simple_type () && ma.symbol_reference is LocalVariable)) 
{
+               unowned ElementAccess? ea = left as ElementAccess;
+               bool transform_assignment = false;
+
+               if (ma != null && !(ma.symbol_reference is LocalVariable)) {
+                       transform_assignment = true;
+               } else if (left.value_type != null && !left.value_type.is_non_null_simple_type ()) {
+                       transform_assignment = true;
+               } else if (ea != null && ea.container.value_type is ArrayType) {
+                       // check if the left is an array and its element is non-null simple type
+                       unowned ArrayType array_type = (ArrayType) ea.container.value_type;
+                       transform_assignment = !array_type.element_type.is_non_null_simple_type ();
+               }
+
+               if ((operator != AssignmentOperator.SIMPLE) && transform_assignment) {
                        // transform into simple assignment
                        // FIXME: only do this if the backend doesn't support
                        // the assignment natively
-
-                       var old_value = new MemberAccess (ma.inner, ma.member_name, source_reference);
+                       Expression old_value = null;
+
+                       if (ma != null) {
+                               old_value = new MemberAccess (ma.inner, ma.member_name, 
left.source_reference);
+                       } else if (ea !=null) {
+                               old_value = new ElementAccess (ea.container, left.source_reference);
+                               var indices = ea.get_indices ();
+                               foreach (var index in indices) {
+                                       ((ElementAccess) old_value).append_index (index);
+                               }
+                       } else {
+                               assert_not_reached ();
+                       }
 
                        BinaryOperator bop;
 
@@ -355,9 +378,7 @@ public class Vala.Assignment : Expression {
                                        }
                                }
                        }
-               } else if (left is ElementAccess) {
-                       unowned ElementAccess ea = (ElementAccess) left;
-
+               } else if (ea != null) {
                        if (!right.value_type.compatible (left.value_type)) {
                                error = true;
                                Report.error (source_reference, "Assignment: Cannot convert from `%s' to 
`%s'".printf (right.value_type.to_string (), left.value_type.to_string ()));


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