[vala/staging] Support (unowned type)[] syntax for transfer-container arrays
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] Support (unowned type)[] syntax for transfer-container arrays
- Date: Sat, 17 May 2014 17:35:50 +0000 (UTC)
commit 0ffe72386589ad6a7f52f95a68929277a31cf719
Author: Luca Bruno <lucabru src gnome org>
Date: Sat May 17 19:34:06 2014 +0200
Support (unowned type)[] syntax for transfer-container arrays
Fixes bug 571486
tests/Makefile.am | 1 +
tests/basic-types/bug571486.vala | 29 ++++++
vala/valaparser.vala | 194 +++++++++++++++++++++++++-------------
3 files changed, 158 insertions(+), 66 deletions(-)
---
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 21da161..4833286 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -22,6 +22,7 @@ TESTS = \
basic-types/arrays.vala \
basic-types/pointers.vala \
basic-types/sizeof.vala \
+ basic-types/bug571486.vala \
basic-types/bug591552.vala \
basic-types/bug595751.vala \
basic-types/bug596637.vala \
diff --git a/tests/basic-types/bug571486.vala b/tests/basic-types/bug571486.vala
new file mode 100644
index 0000000..4ba922e
--- /dev/null
+++ b/tests/basic-types/bug571486.vala
@@ -0,0 +1,29 @@
+public unowned (unowned string)[] var1 = null;
+public (unowned string)[] var2 = null;
+
+class Foo {
+ public (unowned string)[] var3 = null;
+
+ public (unowned string)[] meth ((unowned string)[] var4) {
+ var3 = ((unowned string)[]) var4;
+ return ((unowned string)[]) var3;
+ }
+}
+
+void main () {
+ Object o1 = new Object ();
+ Object o2 = new Object ();
+
+ (unowned Object)[] test = new (unowned Object)[] { o1 };
+ assert (o1.ref_count == 1);
+ test[0] = o2;
+ assert (o1.ref_count == 1);
+ assert (o2.ref_count == 1);
+
+ test = null;
+ assert (o1.ref_count == 1);
+ assert (o2.ref_count == 1);
+
+ int[] i = new int[42];
+ int j = (((int*) i)[4] + 5);
+}
\ No newline at end of file
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index 75ba5a4..3a478bc 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -379,14 +379,25 @@ public class Vala.Parser : CodeVisitor {
accept (TokenType.OWNED);
accept (TokenType.UNOWNED);
accept (TokenType.WEAK);
- if (accept (TokenType.VOID)) {
+
+ if (is_inner_array_type ()) {
+ expect (TokenType.OPEN_PARENS);
+ expect (TokenType.UNOWNED);
+ skip_type ();
+ expect (TokenType.CLOSE_PARENS);
+ expect (TokenType.OPEN_BRACKET);
+ prev ();
} else {
- skip_symbol_name ();
- skip_type_argument_list ();
- }
- while (accept (TokenType.STAR)) {
+ if (accept (TokenType.VOID)) {
+ } else {
+ skip_symbol_name ();
+ skip_type_argument_list ();
+ }
+ while (accept (TokenType.STAR)) {
+ }
+ accept (TokenType.INTERR);
}
- accept (TokenType.INTERR);
+
while (accept (TokenType.OPEN_BRACKET)) {
do {
// required for decision between expression and declaration statement
@@ -401,50 +412,73 @@ public class Vala.Parser : CodeVisitor {
accept (TokenType.HASH);
}
- DataType parse_type (bool owned_by_default, bool can_weak_ref) throws ParseError {
+ bool is_inner_array_type () {
+ var begin = get_location ();
+
+ var result = accept (TokenType.OPEN_PARENS) && accept (TokenType.UNOWNED) && current() !=
TokenType.CLOSE_PARENS;
+ rollback (begin);
+ return result;
+ }
+
+ DataType parse_type (bool owned_by_default, bool can_weak_ref, bool require_unowned = false) throws
ParseError {
var begin = get_location ();
bool is_dynamic = accept (TokenType.DYNAMIC);
bool value_owned = owned_by_default;
- if (owned_by_default) {
- if (accept (TokenType.UNOWNED)) {
- value_owned = false;
- } else if (accept (TokenType.WEAK)) {
- if (!can_weak_ref && !context.deprecated) {
- Report.warning (get_last_src (), "deprecated syntax, use `unowned`
modifier");
+ if (require_unowned) {
+ expect (TokenType.UNOWNED);
+ } else {
+ if (owned_by_default) {
+ if (accept (TokenType.UNOWNED)) {
+ value_owned = false;
+ } else if (accept (TokenType.WEAK)) {
+ if (!can_weak_ref && !context.deprecated) {
+ Report.warning (get_last_src (), "deprecated syntax, use
`unowned` modifier");
+ }
+ value_owned = false;
}
- value_owned = false;
+ } else {
+ value_owned = accept (TokenType.OWNED);
}
- } else {
- value_owned = accept (TokenType.OWNED);
}
DataType type;
- if (!is_dynamic && value_owned == owned_by_default && accept (TokenType.VOID)) {
- type = new VoidType (get_src (begin));
- } else {
- var sym = parse_symbol_name ();
- List<DataType> type_arg_list = parse_type_argument_list (false);
+ bool inner_type_owned = true;
+ if (accept (TokenType.OPEN_PARENS)) {
+ type = parse_type (false, false, true);
+ expect (TokenType.CLOSE_PARENS);
+
+ inner_type_owned = false;
- type = new UnresolvedType.from_symbol (sym, get_src (begin));
- if (type_arg_list != null) {
- foreach (DataType type_arg in type_arg_list) {
- type.add_type_argument (type_arg);
+ expect (TokenType.OPEN_BRACKET);
+ prev ();
+ } else {
+ if (!is_dynamic && value_owned == owned_by_default && accept (TokenType.VOID)) {
+ type = new VoidType (get_src (begin));
+ } else {
+ var sym = parse_symbol_name ();
+ List<DataType> type_arg_list = parse_type_argument_list (false);
+
+ type = new UnresolvedType.from_symbol (sym, get_src (begin));
+ if (type_arg_list != null) {
+ foreach (DataType type_arg in type_arg_list) {
+ type.add_type_argument (type_arg);
+ }
}
}
- }
-
- while (accept (TokenType.STAR)) {
- type = new PointerType (type, get_src (begin));
- }
+
+ while (accept (TokenType.STAR)) {
+ type = new PointerType (type, get_src (begin));
+ }
- if (!(type is PointerType)) {
- type.nullable = accept (TokenType.INTERR);
+ if (!(type is PointerType)) {
+ type.nullable = accept (TokenType.INTERR);
+ }
}
-
+
// array brackets in types are read from right to left,
// this is more logical, especially when nullable arrays
// or pointers are involved
@@ -462,8 +496,7 @@ public class Vala.Parser : CodeVisitor {
} while (accept (TokenType.COMMA));
expect (TokenType.CLOSE_BRACKET);
- // arrays contain strong references by default
- type.value_owned = true;
+ type.value_owned = inner_type_owned;
var array_type = new ArrayType (type, array_rank, get_src (begin));
array_type.nullable = accept (TokenType.INTERR);
@@ -810,6 +843,12 @@ public class Vala.Parser : CodeVisitor {
Expression parse_object_or_array_creation_expression () throws ParseError {
var begin = get_location ();
expect (TokenType.NEW);
+
+ if (is_inner_array_type ()) {
+ rollback (begin);
+ return parse_array_creation_expression ();
+ }
+
var member = parse_member_name ();
if (accept (TokenType.OPEN_PARENS)) {
var expr = parse_object_creation_expression (begin, member);
@@ -851,6 +890,13 @@ public class Vala.Parser : CodeVisitor {
Expression parse_array_creation_expression () throws ParseError {
var begin = get_location ();
expect (TokenType.NEW);
+
+ bool inner_array_type = is_inner_array_type ();
+ if (inner_array_type) {
+ expect (TokenType.OPEN_PARENS);
+ expect (TokenType.UNOWNED);
+ }
+
var member = parse_member_name ();
DataType element_type = UnresolvedType.new_from_expression (member);
bool is_pointer_type = false;
@@ -863,6 +909,14 @@ public class Vala.Parser : CodeVisitor {
element_type.nullable = true;
}
}
+
+ if (inner_array_type) {
+ expect (TokenType.CLOSE_PARENS);
+ element_type.value_owned = false;
+ } else {
+ element_type.value_owned = true;
+ }
+
expect (TokenType.OPEN_BRACKET);
bool size_specified = false;
@@ -998,6 +1052,9 @@ public class Vala.Parser : CodeVisitor {
case TokenType.OPEN_PARENS:
next ();
switch (current ()) {
+ case TokenType.UNOWNED:
+ // inner array type
+ break;
case TokenType.OWNED:
// (owned) foo
next ();
@@ -1008,36 +1065,39 @@ public class Vala.Parser : CodeVisitor {
break;
case TokenType.VOID:
case TokenType.DYNAMIC:
+ case TokenType.OPEN_PARENS:
case TokenType.IDENTIFIER:
- var type = parse_type (true, false);
- if (accept (TokenType.CLOSE_PARENS)) {
- // check follower to decide whether to create cast expression
- switch (current ()) {
- case TokenType.OP_NEG:
- case TokenType.TILDE:
- case TokenType.OPEN_PARENS:
- case TokenType.TRUE:
- case TokenType.FALSE:
- case TokenType.INTEGER_LITERAL:
- case TokenType.REAL_LITERAL:
- case TokenType.CHARACTER_LITERAL:
- case TokenType.STRING_LITERAL:
- case TokenType.TEMPLATE_STRING_LITERAL:
- case TokenType.VERBATIM_STRING_LITERAL:
- case TokenType.REGEX_LITERAL:
- case TokenType.NULL:
- case TokenType.THIS:
- case TokenType.BASE:
- case TokenType.NEW:
- case TokenType.YIELD:
- case TokenType.SIZEOF:
- case TokenType.TYPEOF:
- case TokenType.IDENTIFIER:
- case TokenType.PARAMS:
- var inner = parse_unary_expression ();
- return new CastExpression (inner, type, get_src (begin),
false);
- default:
- break;
+ if (current () != TokenType.OPEN_PARENS || is_inner_array_type ()) {
+ var type = parse_type (true, false);
+ if (accept (TokenType.CLOSE_PARENS)) {
+ // check follower to decide whether to create cast expression
+ switch (current ()) {
+ case TokenType.OP_NEG:
+ case TokenType.TILDE:
+ case TokenType.OPEN_PARENS:
+ case TokenType.TRUE:
+ case TokenType.FALSE:
+ case TokenType.INTEGER_LITERAL:
+ case TokenType.REAL_LITERAL:
+ case TokenType.CHARACTER_LITERAL:
+ case TokenType.STRING_LITERAL:
+ case TokenType.TEMPLATE_STRING_LITERAL:
+ case TokenType.VERBATIM_STRING_LITERAL:
+ case TokenType.REGEX_LITERAL:
+ case TokenType.NULL:
+ case TokenType.THIS:
+ case TokenType.BASE:
+ case TokenType.NEW:
+ case TokenType.YIELD:
+ case TokenType.SIZEOF:
+ case TokenType.TYPEOF:
+ case TokenType.IDENTIFIER:
+ case TokenType.PARAMS:
+ var inner = parse_unary_expression ();
+ return new CastExpression (inner, type, get_src
(begin), false);
+ default:
+ break;
+ }
}
}
break;
@@ -1501,7 +1561,6 @@ public class Vala.Parser : CodeVisitor {
case TokenType.OP_DEC:
case TokenType.BASE:
case TokenType.THIS:
- case TokenType.OPEN_PARENS:
case TokenType.STAR:
case TokenType.NEW:
stmt = parse_expression_statement ();
@@ -1531,6 +1590,10 @@ public class Vala.Parser : CodeVisitor {
}
bool is_expression () throws ParseError {
+ if (current () == TokenType.OPEN_PARENS) {
+ return !is_inner_array_type ();
+ }
+
var begin = get_location ();
// decide between declaration and expression statement
@@ -2169,7 +2232,6 @@ public class Vala.Parser : CodeVisitor {
case TokenType.OP_DEC:
case TokenType.BASE:
case TokenType.THIS:
- case TokenType.OPEN_PARENS:
case TokenType.STAR:
case TokenType.NEW:
// statement
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]