]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
vala: Transform assignment of an array element as needed
authorwxx <769218589@qq.com>
Tue, 30 Nov 2021 18:54:04 +0000 (02:54 +0800)
committerRico Tzschichholz <ricotz@ubuntu.com>
Wed, 9 Feb 2022 21:23:51 +0000 (22:23 +0100)
Fixes https://gitlab.gnome.org/GNOME/vala/issues/889
Fixes https://gitlab.gnome.org/GNOME/vala/issues/1258

tests/Makefile.am
tests/arrays/element-nullable-assignment.vala [new file with mode: 0644]
tests/basic-types/string-array-append.vala [new file with mode: 0644]
vala/valaassignment.vala

index 69f687dc1ff939978e97fcbfd840af45910579a4..48369672a79a84bf6d6c35c40ae85e66b79c9423 100644 (file)
@@ -50,6 +50,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 \
@@ -111,6 +112,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 (file)
index 0000000..29dc295
--- /dev/null
@@ -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 (file)
index 0000000..4b1ae32
--- /dev/null
@@ -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");
+}
+
index 8c0948ef3f61623caad67f8a90c7aea58856b01f..150c34723c83496368a3def06200103aab26a219 100644 (file)
@@ -229,13 +229,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;
 
@@ -361,9 +384,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'", right.value_type.to_string (), left.value_type.to_string ());