[vala/wip/issue/607: 37/38] 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: 37/38] Add native support to specify non default length-type for arrays
- Date: Fri, 2 Jul 2021 12:08:39 +0000 (UTC)
commit c6caa12b8db7f65b6f0d89124f793efd2cef6994
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.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.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 ++++++++++++++++++--
15 files changed, 137 insertions(+), 29 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ca110d712..fd73c9063 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -121,6 +121,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 \
@@ -811,6 +812,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 \
@@ -928,6 +930,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.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.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 85b7b1f45..2d91490fb 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -200,7 +200,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 2b9e19030..f550bb7f4 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -1557,6 +1557,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 2345c355e..2203c8e3e 100644
--- a/vala/valagirparser.vala
+++ b/vala/valagirparser.vala
@@ -1192,13 +1192,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");
}
@@ -1985,17 +1979,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 9ecc96e9b..7d24babdb 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -456,10 +456,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);
}
@@ -546,18 +549,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;
@@ -565,6 +572,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;
}
@@ -588,10 +598,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));
@@ -600,6 +614,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;
@@ -1007,6 +1024,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]
@@ -1016,6 +1034,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;
}
@@ -1023,12 +1044,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));
@@ -1039,6 +1063,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]