[vala/wip/issue/607: 47/48] Add native support to specify non default length-type for arrays
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/issue/607: 47/48] Add native support to specify non default length-type for arrays
- Date: Sat, 30 Oct 2021 12:31:31 +0000 (UTC)
commit bc41b66ca94c6374eb18f5a23cfb01fe72e30289
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Thu Apr 15 16:49:14 2021 +0200
Add native support to specify non default length-type for arrays
string[:long] foo = new string[:long] { "foo" };
This applies to generated bindings where this new syntax will be
picked up. It will apply a stricker variable type checking for
such array types.
Fixes https://gitlab.gnome.org/GNOME/vala/issues/607
tests/Makefile.am | 4 +
tests/arrays/length-type.c-expected | 210 +++++++++++++++++++++++++++++
tests/arrays/length-type.vala | 49 +++++++
tests/gir/bug651773.test | 4 +-
tests/gir/bug788775.test | 4 +-
tests/gir/delegate-array-length-type.test | 4 +-
tests/gir/method-array-length-type.test | 4 +-
tests/gir/parameter-array-length-type.test | 2 +-
tests/parser/array-length.c-expected | 90 +++++++++++++
tests/parser/array-length.vala | 13 ++
tests/semantic/array-length-invalid.test | 5 +
tests/semantic/array-length-nullable.test | 5 +
vala/valaarraycreationexpression.vala | 4 +
vala/valaarraytype.vala | 8 +-
vala/valacodewriter.vala | 5 +
vala/valagirparser.vala | 22 +--
vala/valaparser.vala | 33 ++++-
17 files changed, 437 insertions(+), 29 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 2628320bb..f6bd6cab8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -126,6 +126,7 @@ TESTS = \
arrays/inline-struct-field.test \
arrays/in-operator-with-boxed-needle.vala \
arrays/length-inline-assignment.vala \
+ arrays/length-type.vala \
arrays/length-type-include.vala \
arrays/length-no-int-type.test \
arrays/struct-field-length-cname.vala \
@@ -845,6 +846,7 @@ TESTS = \
scanner/string-escape-x.vala \
parser/argument-list-incomplete.test \
parser/array-creation-invalid.test \
+ parser/array-length.vala \
parser/assignment.vala \
parser/attribute-duplicate.test \
parser/attribute-missing-literal.test \
@@ -963,6 +965,8 @@ TESTS = \
semantic/array-incompatible-initializer.test \
semantic/array-incompatible-initializer2.test \
semantic/array-invalid-type-argument.test \
+ semantic/array-length-invalid.test \
+ semantic/array-length-nullable.test \
semantic/array-too-few-type-arguments.test \
semantic/array-too-many-type-arguments.test \
semantic/assignment-element-incompatible-ownership.test \
diff --git a/tests/arrays/length-type.c-expected b/tests/arrays/length-type.c-expected
new file mode 100644
index 000000000..7da10b31d
--- /dev/null
+++ b/tests/arrays/length-type.c-expected
@@ -0,0 +1,210 @@
+/* arrays_length_type.c generated by valac, the Vala compiler
+ * generated from arrays_length_type.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_MSC_VER)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef guint8* (*ManamFunc) (guint8* param, gsize param_length1, guint64* result_length1);
+#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);
+
+VALA_EXTERN guint8* field;
+VALA_EXTERN gsize field_length1;
+guint8* field = NULL;
+gsize field_length1 = 0;
+static gsize _field_size_ = 0;
+
+VALA_EXTERN guint8* manam (guint8* param,
+ gsize param_length1,
+ guint64* result_length1);
+VALA_EXTERN void test_pass (void);
+static guint8* _manam_manam_func (guint8* param,
+ gsize param_length1,
+ guint64* result_length1);
+VALA_EXTERN void foo (guint8** param,
+ gssize* param_length1);
+VALA_EXTERN void test_ref (void);
+VALA_EXTERN void bar (guint8** param,
+ gssize* param_length1);
+VALA_EXTERN void test_out (void);
+static void _vala_main (void);
+
+guint8*
+manam (guint8* param,
+ gsize param_length1,
+ guint64* result_length1)
+{
+ guint8* _tmp0_;
+ guint64 _tmp0__length1;
+ guint8* result = NULL;
+ _vala_assert (((gint64) param_length1) == 2147483648LL, "param.length == 2147483648LL");
+ _tmp0_ = param;
+ _tmp0__length1 = param_length1;
+ if (result_length1) {
+ *result_length1 = _tmp0__length1;
+ }
+ result = _tmp0_;
+ return result;
+}
+
+static guint8*
+_manam_manam_func (guint8* param,
+ gsize param_length1,
+ guint64* result_length1)
+{
+ guint8* result;
+ result = manam (param, param_length1, result_length1);
+ return result;
+}
+
+void
+test_pass (void)
+{
+ guint8* foo = NULL;
+ guint8* _tmp0_;
+ gssize foo_length1;
+ gssize _foo_size_;
+ guint8* _tmp1_;
+ gssize _tmp1__length1;
+ ManamFunc func = NULL;
+ guint8* bar = NULL;
+ guint8* _tmp2_;
+ gssize _tmp2__length1;
+ guint64 _tmp3_ = 0;
+ guint8* _tmp4_;
+ guint64 bar_length1;
+ guint64 _bar_size_;
+ guint8* _tmp5_;
+ gssize _tmp5__length1;
+ guint8* _tmp6_;
+ gsize _tmp6__length1;
+ _tmp0_ = g_new0 (guint8, 2147483648LL);
+ foo = _tmp0_;
+ foo_length1 = 2147483648LL;
+ _foo_size_ = foo_length1;
+ _tmp1_ = foo;
+ _tmp1__length1 = foo_length1;
+ _vala_assert (((gint64) _tmp1__length1) == 2147483648LL, "foo.length == 2147483648LL");
+ func = _manam_manam_func;
+ _tmp2_ = foo;
+ _tmp2__length1 = foo_length1;
+ _tmp4_ = func (_tmp2_, (gsize) _tmp2__length1, &_tmp3_);
+ bar = _tmp4_;
+ bar_length1 = _tmp3_;
+ _bar_size_ = bar_length1;
+ _vala_assert (bar_length1 == ((guint64) 2147483648LL), "bar.length == 2147483648LL");
+ _tmp5_ = foo;
+ _tmp5__length1 = foo_length1;
+ foo = NULL;
+ foo_length1 = 0;
+ field = (g_free (field), NULL);
+ field = _tmp5_;
+ field_length1 = _tmp5__length1;
+ _field_size_ = field_length1;
+ _tmp6_ = field;
+ _tmp6__length1 = field_length1;
+ _vala_assert (((gint64) _tmp6__length1) == 2147483648LL, "field.length == 2147483648LL");
+ field = (g_free (field), NULL);
+ field = NULL;
+ field_length1 = 0;
+ _field_size_ = field_length1;
+ foo = (g_free (foo), NULL);
+}
+
+void
+foo (guint8** param,
+ gssize* param_length1)
+{
+ guint8* _tmp0_;
+ _tmp0_ = g_new0 (guint8, 2147483648LL);
+ *param = (g_free (*param), NULL);
+ *param = _tmp0_;
+ *param_length1 = 2147483648LL;
+}
+
+void
+test_ref (void)
+{
+ guint8* a = NULL;
+ guint8* _tmp0_;
+ gssize a_length1;
+ gssize _a_size_;
+ guint8* _tmp1_;
+ gssize _tmp1__length1;
+ _tmp0_ = g_new0 (guint8, 0);
+ a = _tmp0_;
+ a_length1 = 0;
+ _a_size_ = a_length1;
+ foo (&a, (gssize*) (&a_length1));
+ _a_size_ = a_length1;
+ _tmp1_ = a;
+ _tmp1__length1 = a_length1;
+ _vala_assert (((gint64) _tmp1__length1) == 2147483648LL, "a.length == 2147483648LL");
+ a = (g_free (a), NULL);
+}
+
+void
+bar (guint8** param,
+ gssize* param_length1)
+{
+ guint8* _vala_param = NULL;
+ gssize _vala_param_length1 = 0;
+ guint8* _tmp0_;
+ _tmp0_ = g_new0 (guint8, 2147483648LL);
+ _vala_param = (g_free (_vala_param), NULL);
+ _vala_param = _tmp0_;
+ _vala_param_length1 = 2147483648LL;
+ if (param) {
+ *param = _vala_param;
+ } else {
+ _vala_param = (g_free (_vala_param), NULL);
+ }
+ if (param_length1) {
+ *param_length1 = _vala_param_length1;
+ }
+}
+
+void
+test_out (void)
+{
+ guint8* a = NULL;
+ gssize a_length1 = 0L;
+ gssize _a_size_ = 0L;
+ guint8* _tmp0_ = NULL;
+ gssize _tmp1_ = 0;
+ bar (&_tmp0_, &_tmp1_);
+ a = (g_free (a), NULL);
+ a = _tmp0_;
+ a_length1 = _tmp1_;
+ _a_size_ = a_length1;
+ _vala_assert (((gint64) a_length1) == 2147483648LL, "a.length == 2147483648LL");
+ a = (g_free (a), NULL);
+}
+
+static void
+_vala_main (void)
+{
+ test_pass ();
+ test_ref ();
+ test_out ();
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/arrays/length-type.vala b/tests/arrays/length-type.vala
new file mode 100644
index 000000000..63f6124d6
--- /dev/null
+++ b/tests/arrays/length-type.vala
@@ -0,0 +1,49 @@
+[CCode (has_target = false)]
+delegate unowned uint8[:uint64] ManamFunc (uint8[:size_t] param);
+
+unowned uint8[:uint64] manam (uint8[:size_t] param) {
+ assert (param.length == 2147483648LL);
+ return param;
+}
+
+uint8[:size_t] field;
+
+void test_pass () {
+ var foo = new uint8[2147483648LL:ssize_t];
+ assert (foo.length == 2147483648LL);
+
+ ManamFunc func = manam;
+ unowned var bar = func (foo);
+ assert (bar.length == 2147483648LL);
+
+ field = (owned) foo;
+ assert (field.length == 2147483648LL);
+
+ field = null;
+}
+
+void foo (ref uint8[:ssize_t] param) {
+ param = new uint8[2147483648LL:ssize_t];
+}
+
+void test_ref () {
+ var a = new uint8[:ssize_t] {};
+ foo (ref a);
+ assert (a.length == 2147483648LL);
+}
+
+void bar (out uint8[:ssize_t] param) {
+ param = new uint8[2147483648LL:ssize_t];
+}
+
+void test_out () {
+ uint8[:ssize_t] a;
+ bar (out a);
+ assert (a.length == 2147483648LL);
+}
+
+void main () {
+ test_pass ();
+ test_ref ();
+ test_out ();
+}
diff --git a/tests/gir/bug651773.test b/tests/gir/bug651773.test
index 7f499de5b..ff97bc290 100644
--- a/tests/gir/bug651773.test
+++ b/tests/gir/bug651773.test
@@ -20,5 +20,5 @@ Input:
Output:
-[CCode (array_length_pos = 0.1, array_length_type = "gsize", cheader_filename = "test.h")]
-public static unowned uint8[] get_array ();
+[CCode (array_length_pos = 0.1, cheader_filename = "test.h")]
+public static unowned uint8[:size_t] get_array ();
diff --git a/tests/gir/bug788775.test b/tests/gir/bug788775.test
index 80ae7cd21..08a6a90e5 100644
--- a/tests/gir/bug788775.test
+++ b/tests/gir/bug788775.test
@@ -25,5 +25,5 @@ Input:
Output:
-[CCode (array_length = true, array_length_pos = 1.1, array_length_type = "gsize", array_null_terminated =
true, cheader_filename = "test.h")]
-public static string[] get_string_list (string key);
+[CCode (array_length = true, array_length_pos = 1.1, array_null_terminated = true, cheader_filename =
"test.h")]
+public static string[:size_t] get_string_list (string key);
diff --git a/tests/gir/delegate-array-length-type.test b/tests/gir/delegate-array-length-type.test
index 127ac8a76..798955dd3 100644
--- a/tests/gir/delegate-array-length-type.test
+++ b/tests/gir/delegate-array-length-type.test
@@ -24,5 +24,5 @@ Input:
Output:
-[CCode (array_length_pos = 0.1, array_length_type = "gsize", cheader_filename = "test.h", instance_pos =
0.9)]
-public delegate string[] Foo ();
+[CCode (array_length_pos = 0.1, cheader_filename = "test.h", instance_pos = 0.9)]
+public delegate string[:size_t] Foo ();
diff --git a/tests/gir/method-array-length-type.test b/tests/gir/method-array-length-type.test
index b7ebccfc5..b13df3967 100644
--- a/tests/gir/method-array-length-type.test
+++ b/tests/gir/method-array-length-type.test
@@ -17,5 +17,5 @@ Input:
Output:
-[CCode (array_length_pos = 0.1, array_length_type = "gsize", cheader_filename = "test.h")]
-public static string[] function ();
+[CCode (array_length_pos = 0.1, cheader_filename = "test.h")]
+public static string[:size_t] function ();
diff --git a/tests/gir/parameter-array-length-type.test b/tests/gir/parameter-array-length-type.test
index 3bbbe9ec6..9c2b22921 100644
--- a/tests/gir/parameter-array-length-type.test
+++ b/tests/gir/parameter-array-length-type.test
@@ -21,4 +21,4 @@ Input:
Output:
[CCode (cheader_filename = "test.h")]
-public static void function ([CCode (array_length_cname = "foo_length", array_length_pos = 1.1,
array_length_type = "gsize")] string[] foo);
+public static void function ([CCode (array_length_cname = "foo_length", array_length_pos = 1.1)]
string[:size_t] foo);
diff --git a/tests/parser/array-length.c-expected b/tests/parser/array-length.c-expected
new file mode 100644
index 000000000..53433362a
--- /dev/null
+++ b/tests/parser/array-length.c-expected
@@ -0,0 +1,90 @@
+/* parser_array_length.c generated by valac, the Vala compiler
+ * generated from parser_array_length.vala, do not modify */
+
+#include <glib.h>
+
+#if !defined(VALA_EXTERN)
+#if defined(_MSC_VER)
+#define VALA_EXTERN __declspec(dllexport) extern
+#elif __GNUC__ >= 4
+#define VALA_EXTERN __attribute__((visibility("default"))) extern
+#else
+#define VALA_EXTERN extern
+#endif
+#endif
+
+typedef guint8* (*FooFunc) (guint8* param0, gsize param0_length1, guint8** param1, gint64* param1_length1,
guint8** param2, guint* param2_length1, guint8* param3, guint64* result_length1, gpointer user_data);
+
+VALA_EXTERN guint8* field0;
+VALA_EXTERN gssize field0_length1;
+guint8* field0 = NULL;
+gssize field0_length1 = 0;
+static gssize _field0_size_ = 0;
+VALA_EXTERN guint8 field1[4711];
+guint8 field1[4711] = {0};
+
+VALA_EXTERN guint8* func (guint8* param0,
+ gsize param0_length1,
+ guint8** param1,
+ gint64* param1_length1,
+ guint8** param2,
+ guint* param2_length1,
+ guint8* param3,
+ guint64* result_length1);
+static void _vala_main (void);
+
+guint8*
+func (guint8* param0,
+ gsize param0_length1,
+ guint8** param1,
+ gint64* param1_length1,
+ guint8** param2,
+ guint* param2_length1,
+ guint8* param3,
+ guint64* result_length1)
+{
+ guint8* _vala_param2 = NULL;
+ guint _vala_param2_length1 = 0;
+ guint8* _tmp0_;
+ guint64 _tmp0__length1;
+ guint8* result = NULL;
+ _tmp0_ = param0;
+ _tmp0__length1 = param0_length1;
+ if (result_length1) {
+ *result_length1 = _tmp0__length1;
+ }
+ result = _tmp0_;
+ if (param2) {
+ *param2 = _vala_param2;
+ } else {
+ _vala_param2 = (g_free (_vala_param2), NULL);
+ }
+ if (param2_length1) {
+ *param2_length1 = _vala_param2_length1;
+ }
+ return result;
+}
+
+static void
+_vala_main (void)
+{
+ guint8* local_heap = NULL;
+ guint8* _tmp0_;
+ gssize local_heap_length1;
+ gssize _local_heap_size_;
+ guint8 local_stack[42] = {0};
+ _tmp0_ = g_new0 (guint8, 23);
+ local_heap = _tmp0_;
+ local_heap_length1 = 23;
+ _local_heap_size_ = local_heap_length1;
+ local_heap = (g_free (local_heap), NULL);
+}
+
+int
+main (int argc,
+ char ** argv)
+{
+ _vala_main ();
+ return 0;
+}
+
diff --git a/tests/parser/array-length.vala b/tests/parser/array-length.vala
new file mode 100644
index 000000000..4de401cf4
--- /dev/null
+++ b/tests/parser/array-length.vala
@@ -0,0 +1,13 @@
+delegate unowned uint8[:uint64] FooFunc (uint8[:size_t] param0, ref uint8[:int64] param1, out uint8[:uint]
param2, uint8 param3[42:ssize_t]);
+
+unowned uint8[:uint64] func (uint8[:size_t] param0, ref uint8[:int64] param1, out uint8[:uint] param2, uint8
param3[42:ssize_t]) {
+ return param0;
+}
+
+uint8[:ssize_t] field0;
+uint8 field1[4711:ssize_t];
+
+void main () {
+ var local_heap = new uint8[23:ssize_t];
+ uint8 local_stack[42:ssize_t];
+}
diff --git a/tests/semantic/array-length-invalid.test b/tests/semantic/array-length-invalid.test
new file mode 100644
index 000000000..aee2cfdb8
--- /dev/null
+++ b/tests/semantic/array-length-invalid.test
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+ var foo = new uint8[23:float];
+}
diff --git a/tests/semantic/array-length-nullable.test b/tests/semantic/array-length-nullable.test
new file mode 100644
index 000000000..fa56e48ee
--- /dev/null
+++ b/tests/semantic/array-length-nullable.test
@@ -0,0 +1,5 @@
+Invalid Code
+
+void main () {
+ var foo = new uint8[23:size_t?];
+}
diff --git a/vala/valaarraycreationexpression.vala b/vala/valaarraycreationexpression.vala
index 70fc4425a..3b423b224 100644
--- a/vala/valaarraycreationexpression.vala
+++ b/vala/valaarraycreationexpression.vala
@@ -167,6 +167,10 @@ public class Vala.ArrayCreationExpression : Expression {
builder.append_printf (", %s", size.to_string ());
}
}
+ var length_str = length_type.to_string ();
+ if (length_str != "int") {
+ builder.append_printf (":%s", length_str);
+ }
builder.append_c (']');
if (initializer_list != null) {
builder.append (initializer_list.to_string ());
diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala
index 55847d5db..b032de4f7 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -199,7 +199,13 @@ public class Vala.ArrayType : ReferenceType {
}
if (!fixed_length) {
- return "%s[%s]%s".printf (elem_str, string.nfill (rank - 1, ','), nullable ? "?" :
"");
+ var length_str = length_type == null ? "int" : length_type.to_qualified_string
(scope);
+ if (length_str != "int") {
+ length_str = ":%s".printf (length_str);
+ } else {
+ length_str = "";
+ }
+ return "%s[%s%s]%s".printf (elem_str, string.nfill (rank - 1, ','), length_str,
nullable ? "?" : "");
} else {
return elem_str;
}
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index cb3bd998d..f9f1fccd1 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -1569,6 +1569,11 @@ public class Vala.CodeWriter : CodeVisitor {
if (array_type != null && array_type.fixed_length) {
write_string ("[");
array_type.length.accept (this);
+ var length_type = array_type.length_type.to_qualified_string (current_scope);
+ if (length_type != "int") {
+ write_string (":");
+ write_string (length_type);
+ }
write_string ("]");
}
}
diff --git a/vala/valagirparser.vala b/vala/valagirparser.vala
index 6a4b572af..a9ca6001c 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -1195,13 +1195,7 @@ public class Vala.GirParser : CodeVisitor {
var length_field = (Field) array_length.symbol;
// array has length
field.set_attribute_string ("CCode",
"array_length_cname", length_field.name);
- var length_type =
length_field.variable_type.to_qualified_string ();
- if (length_type != "int") {
- var st = parser.root.lookup (length_type);
- if (st != null) {
- field.set_attribute_string ("CCode",
"array_length_type", st.get_cname ());
- }
- }
+ ((ArrayType) field.variable_type).length_type =
length_field.variable_type.copy ();
field.remove_attribute_argument ("CCode",
"array_length");
field.remove_attribute_argument ("CCode",
"array_null_terminated");
}
@@ -1990,17 +1984,13 @@ public class Vala.GirParser : CodeVisitor {
void set_array_ccode (Symbol sym, ParameterInfo info) {
sym.set_attribute_double ("CCode", "array_length_pos", info.vala_idx);
+ var length_type = info.param.variable_type.copy ();
+ length_type.nullable = false;
if (sym is Parameter) {
sym.set_attribute_string ("CCode", "array_length_cname", info.param.name);
- }
- var type_name = info.param.variable_type.to_qualified_string ();
- if (type_name != "int") {
- var st = root.lookup (type_name);
- if (st != null) {
- if (sym is Callable || sym is Parameter) {
- sym.set_attribute_string ("CCode", "array_length_type", st.get_cname
());
- }
- }
+ ((ArrayType) ((Parameter) sym).variable_type).length_type = length_type;
+ } else if (sym is Callable) {
+ ((ArrayType) ((Callable) sym).return_type).length_type = length_type;
}
}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 93031cee1..0fb839bf1 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -459,10 +459,13 @@ public class Vala.Parser : CodeVisitor {
while (accept (TokenType.OPEN_BRACKET)) {
do {
// required for decision between expression and declaration statement
- if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
+ if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET &&
current () != TokenType.COLON) {
parse_expression ();
}
} while (accept (TokenType.COMMA));
+ if (accept (TokenType.COLON)) {
+ skip_symbol_name ();
+ }
expect (TokenType.CLOSE_BRACKET);
accept (TokenType.INTERR);
}
@@ -549,18 +552,22 @@ public class Vala.Parser : CodeVisitor {
// array brackets in types are read from right to left,
// this is more logical, especially when nullable arrays
// or pointers are involved
+ DataType? array_length_type = null;
while (accept (TokenType.OPEN_BRACKET)) {
bool invalid_array = false;
int array_rank = 0;
do {
array_rank++;
// required for decision between expression and declaration statement
- if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
+ if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET &&
current () != TokenType.COLON) {
parse_expression ();
// only used for parsing, reject use as real type
invalid_array = true;
}
} while (accept (TokenType.COMMA));
+ if (accept (TokenType.COLON)) {
+ array_length_type = parse_type (true, false);
+ }
expect (TokenType.CLOSE_BRACKET);
type.value_owned = inner_type_owned;
@@ -568,6 +575,9 @@ public class Vala.Parser : CodeVisitor {
var array_type = new ArrayType (type, array_rank, get_src (begin));
array_type.nullable = accept (TokenType.INTERR);
array_type.invalid_syntax = invalid_array;
+ if (array_length_type != null) {
+ array_type.length_type = array_length_type.copy ();
+ }
type = array_type;
}
@@ -591,10 +601,14 @@ public class Vala.Parser : CodeVisitor {
// inline-allocated array
if (type != null && accept (TokenType.OPEN_BRACKET)) {
Expression array_length = null;
+ DataType? array_length_type = null;
if (current () != TokenType.CLOSE_BRACKET) {
array_length = parse_expression ();
}
+ if (accept (TokenType.COLON)) {
+ array_length_type = parse_type (true, false);
+ }
expect (TokenType.CLOSE_BRACKET);
var array_type = new ArrayType (type, 1, get_src (begin));
@@ -603,6 +617,9 @@ public class Vala.Parser : CodeVisitor {
array_type.fixed_length = true;
array_type.length = array_length;
}
+ if (array_length_type != null) {
+ array_type.length_type = array_length_type;
+ }
array_type.value_owned = type.value_owned;
return array_type;
@@ -1033,6 +1050,7 @@ public class Vala.Parser : CodeVisitor {
bool size_specified = false;
List<Expression> size_specifier_list = null;
bool first = true;
+ DataType? array_length_type = null;
do {
if (!first) {
// array of arrays: new T[][42]
@@ -1042,6 +1060,9 @@ public class Vala.Parser : CodeVisitor {
}
element_type = new ArrayType (element_type, size_specifier_list.size,
element_type.source_reference);
+ if (array_length_type != null) {
+ ((ArrayType) element_type).length_type = array_length_type.copy ();
+ }
} else {
first = false;
}
@@ -1049,12 +1070,15 @@ public class Vala.Parser : CodeVisitor {
size_specifier_list = new ArrayList<Expression> ();
do {
Expression size = null;
- if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA) {
+ if (current () != TokenType.CLOSE_BRACKET && current () != TokenType.COMMA &&
current () != TokenType.COLON) {
size = parse_expression ();
size_specified = true;
}
size_specifier_list.add (size);
} while (accept (TokenType.COMMA));
+ if (accept (TokenType.COLON)) {
+ array_length_type = parse_type (true, false);
+ }
expect (TokenType.CLOSE_BRACKET);
} while (accept (TokenType.OPEN_BRACKET));
@@ -1065,6 +1089,9 @@ public class Vala.Parser : CodeVisitor {
initializer = parse_initializer ();
}
var expr = new ArrayCreationExpression (element_type, size_specifier_list.size, initializer,
src);
+ if (array_length_type != null) {
+ expr.length_type = array_length_type.copy ();
+ }
if (size_specified) {
foreach (Expression size in size_specifier_list) {
expr.append_size (size);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]