[vala/staging] vala: Transform assignment of an array element as needed
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] vala: Transform assignment of an array element as needed
- Date: Wed, 26 Jan 2022 13:37:13 +0000 (UTC)
commit f853104ebf94ce1f72ab408dc5d5b50c81b69d51
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 +
.../arrays/element-nullable-assignment.c-expected | 154 +++++++++++++++++++++
tests/arrays/element-nullable-assignment.vala | 11 ++
tests/basic-types/string-array-append.c-expected | 118 ++++++++++++++++
tests/basic-types/string-array-append.vala | 12 ++
vala/valaassignment.vala | 35 ++++-
6 files changed, 325 insertions(+), 7 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 0b9f71524..cf9bd1e93 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,6 +51,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 \
@@ -112,6 +113,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.c-expected
b/tests/arrays/element-nullable-assignment.c-expected
new file mode 100644
index 000000000..ffba74e24
--- /dev/null
+++ b/tests/arrays/element-nullable-assignment.c-expected
@@ -0,0 +1,154 @@
+/* arrays_element_nullable_assignment.c generated by valac, the Vala compiler
+ * generated from arrays_element_nullable_assignment.vala, do not modify */
+
+#include <glib.h>
+#include <string.h>
+
+#define _g_free0(var) ((var == NULL) ? NULL : (var = (g_free (var), NULL)))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__,
__LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN,
G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning
(G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__,
__LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+static gint* _int_dup (gint* self);
+static gboolean _int_equal (const gint * s1,
+ const gint * s2);
+static void _vala_array_destroy (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func);
+static void _vala_array_free (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func);
+
+static gint*
+_int_dup (gint* self)
+{
+ gint* dup;
+ dup = g_new0 (gint, 1);
+ memcpy (dup, self, sizeof (gint));
+ return dup;
+}
+
+static gpointer
+__int_dup0 (gpointer self)
+{
+ return self ? _int_dup (self) : NULL;
+}
+
+static gboolean
+_int_equal (const gint * s1,
+ const gint * s2)
+{
+ if (s1 == s2) {
+ return TRUE;
+ }
+ if (s1 == NULL) {
+ return FALSE;
+ }
+ if (s2 == NULL) {
+ return FALSE;
+ }
+ return (*s1) == (*s2);
+}
+
+static void
+_vala_main (void)
+{
+ gint** foo = NULL;
+ gint _tmp0_;
+ gint* _tmp1_;
+ gint _tmp2_;
+ gint* _tmp3_;
+ gint _tmp4_;
+ gint* _tmp5_;
+ gint** _tmp6_;
+ gint foo_length1;
+ gint _foo_size_;
+ gint* _tmp7_;
+ gint _tmp8_;
+ gint* _tmp9_;
+ gint* _tmp10_;
+ gint _tmp11_;
+ gint* _tmp12_;
+ gint* _tmp13_;
+ gint _tmp14_;
+ gint* _tmp15_;
+ gint* _tmp16_;
+ gint _tmp17_;
+ gint* _tmp18_;
+ gint _tmp19_;
+ gint* _tmp20_;
+ gint _tmp21_;
+ _tmp0_ = 23;
+ _tmp1_ = __int_dup0 (&_tmp0_);
+ _tmp2_ = 42;
+ _tmp3_ = __int_dup0 (&_tmp2_);
+ _tmp4_ = 4711;
+ _tmp5_ = __int_dup0 (&_tmp4_);
+ _tmp6_ = g_new0 (gint*, 3);
+ _tmp6_[0] = _tmp1_;
+ _tmp6_[1] = _tmp3_;
+ _tmp6_[2] = _tmp5_;
+ foo = _tmp6_;
+ foo_length1 = 3;
+ _foo_size_ = foo_length1;
+ _tmp7_ = foo[0];
+ _tmp8_ = (*_tmp7_) + 1;
+ _tmp9_ = __int_dup0 (&_tmp8_);
+ _g_free0 (foo[0]);
+ foo[0] = _tmp9_;
+ _tmp10_ = foo[1];
+ _tmp11_ = (*_tmp10_) * 3;
+ _tmp12_ = __int_dup0 (&_tmp11_);
+ _g_free0 (foo[1]);
+ foo[1] = _tmp12_;
+ _tmp13_ = foo[2];
+ _tmp14_ = (*_tmp13_) - 2;
+ _tmp15_ = __int_dup0 (&_tmp14_);
+ _g_free0 (foo[2]);
+ foo[2] = _tmp15_;
+ _tmp16_ = foo[0];
+ _tmp17_ = 24;
+ _vala_assert (_int_equal (_tmp16_, &_tmp17_) == TRUE, "foo[0] == 24");
+ _tmp18_ = foo[1];
+ _tmp19_ = 126;
+ _vala_assert (_int_equal (_tmp18_, &_tmp19_) == TRUE, "foo[1] == 126");
+ _tmp20_ = foo[2];
+ _tmp21_ = 4709;
+ _vala_assert (_int_equal (_tmp20_, &_tmp21_) == TRUE, "foo[2] == 4709");
+ foo = (_vala_array_free (foo, foo_length1, (GDestroyNotify) g_free), NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+static void
+_vala_array_destroy (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func)
+{
+ if ((array != NULL) && (destroy_func != NULL)) {
+ gssize i;
+ for (i = 0; i < array_length; i = i + 1) {
+ if (((gpointer*) array)[i] != NULL) {
+ destroy_func (((gpointer*) array)[i]);
+ }
+ }
+ }
+}
+
+static void
+_vala_array_free (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func)
+{
+ _vala_array_destroy (array, array_length, destroy_func);
+ g_free (array);
+}
+
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.c-expected
b/tests/basic-types/string-array-append.c-expected
new file mode 100644
index 000000000..222f34faa
--- /dev/null
+++ b/tests/basic-types/string-array-append.c-expected
@@ -0,0 +1,118 @@
+/* basic_types_string_array_append.c generated by valac, the Vala compiler
+ * generated from basic_types_string_array_append.vala, do not modify */
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib.h>
+
+#define _g_free0(var) (var = (g_free (var), NULL))
+#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__,
__LINE__, G_STRFUNC, msg);
+#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN,
G_STRFUNC, msg); return; }
+#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning
(G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
+#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__,
__LINE__, G_STRFUNC, msg);
+
+static void _vala_main (void);
+static void _vala_array_destroy (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func);
+static void _vala_array_free (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func);
+
+static void
+_vala_main (void)
+{
+ gchar** foo = NULL;
+ gchar* _tmp0_;
+ gchar* _tmp1_;
+ gchar* _tmp2_;
+ gchar** _tmp3_;
+ gint foo_length1;
+ gint _foo_size_;
+ const gchar* _tmp4_;
+ gchar* _tmp5_;
+ const gchar* _tmp6_;
+ gchar* _tmp7_;
+ gchar* _tmp8_;
+ gchar* _tmp9_;
+ const gchar* _tmp10_;
+ gchar* _tmp11_;
+ gchar* _tmp12_;
+ gchar* _tmp13_;
+ gchar* _tmp14_;
+ gchar* _tmp15_;
+ const gchar* _tmp16_;
+ const gchar* _tmp17_;
+ const gchar* _tmp18_;
+ _tmp0_ = g_strdup ("foo");
+ _tmp1_ = g_strdup ("bar");
+ _tmp2_ = g_strdup ("foo bar");
+ _tmp3_ = g_new0 (gchar*, 3 + 1);
+ _tmp3_[0] = _tmp0_;
+ _tmp3_[1] = _tmp1_;
+ _tmp3_[2] = _tmp2_;
+ foo = _tmp3_;
+ foo_length1 = 3;
+ _foo_size_ = foo_length1;
+ _tmp4_ = foo[0];
+ _tmp5_ = g_strconcat (_tmp4_, "abc", NULL);
+ _g_free0 (foo[0]);
+ foo[0] = _tmp5_;
+ _tmp6_ = foo[1];
+ _tmp7_ = g_strdup_printf ("%i", 123);
+ _tmp8_ = _tmp7_;
+ _tmp9_ = g_strconcat (_tmp6_, _tmp8_, NULL);
+ _g_free0 (foo[1]);
+ foo[1] = _tmp9_;
+ _g_free0 (_tmp8_);
+ _tmp10_ = foo[2];
+ _tmp11_ = g_strdup_printf ("%i", 123);
+ _tmp12_ = _tmp11_;
+ _tmp13_ = g_strconcat (" abc", _tmp12_, NULL);
+ _tmp14_ = _tmp13_;
+ _tmp15_ = g_strconcat (_tmp10_, _tmp14_, NULL);
+ _g_free0 (foo[2]);
+ foo[2] = _tmp15_;
+ _g_free0 (_tmp14_);
+ _g_free0 (_tmp12_);
+ _tmp16_ = foo[0];
+ _vala_assert (g_strcmp0 (_tmp16_, "fooabc") == 0, "foo[0] == \"fooabc\"");
+ _tmp17_ = foo[1];
+ _vala_assert (g_strcmp0 (_tmp17_, "bar123") == 0, "foo[1] == \"bar123\"");
+ _tmp18_ = foo[2];
+ _vala_assert (g_strcmp0 (_tmp18_, "foo bar abc123") == 0, "foo[2] == \"foo bar abc123\"");
+ foo = (_vala_array_free (foo, foo_length1, (GDestroyNotify) g_free), NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
+static void
+_vala_array_destroy (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func)
+{
+ if ((array != NULL) && (destroy_func != NULL)) {
+ gssize i;
+ for (i = 0; i < array_length; i = i + 1) {
+ if (((gpointer*) array)[i] != NULL) {
+ destroy_func (((gpointer*) array)[i]);
+ }
+ }
+ }
+}
+
+static void
+_vala_array_free (gpointer array,
+ gssize array_length,
+ GDestroyNotify destroy_func)
+{
+ _vala_array_destroy (array, array_length, destroy_func);
+ g_free (array);
+}
+
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 8c0948ef3..150c34723 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -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 ());
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]