[vala/staging] Support non-literal length in fixed-size arrays
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] Support non-literal length in fixed-size arrays
- Date: Sun, 30 Mar 2014 09:29:21 +0000 (UTC)
commit cbac8f57994989f9deb14c7a54def81e3690273b
Author: Simon <simon werbeck gmail com>
Date: Thu Mar 13 22:48:40 2014 +0100
Support non-literal length in fixed-size arrays
Now any constant integer expression can be used as length
for fixed-size arrays.
Fixes bug 638993
ccode/valaccodestruct.vala | 2 +-
ccode/valaccodevariabledeclarator.vala | 37 +++++++++++++++++++++++++++----
codegen/valaccodearraymodule.vala | 8 +++---
codegen/valaccodeassignmentmodule.vala | 2 +-
codegen/valaccodebasemodule.vala | 12 +++++-----
codegen/valaccodestructmodule.vala | 7 +++++-
codegen/valagirwriter.vala | 5 ++-
tests/basic-types/arrays.vala | 4 +++
vala/valaarraytype.vala | 21 +++++++++++++++++-
vala/valacodewriter.vala | 4 ++-
vala/valagenieparser.vala | 11 ++-------
vala/valaparser.vala | 11 ++-------
12 files changed, 86 insertions(+), 38 deletions(-)
---
diff --git a/ccode/valaccodestruct.vala b/ccode/valaccodestruct.vala
index 76f7679..96836ed 100644
--- a/ccode/valaccodestruct.vala
+++ b/ccode/valaccodestruct.vala
@@ -59,7 +59,7 @@ public class Vala.CCodeStruct : CCodeNode {
* @param type_name field type
* @param name member name
*/
- public void add_field (string type_name, string name, string? declarator_suffix = null) {
+ public void add_field (string type_name, string name, CCodeDeclaratorSuffix? declarator_suffix =
null) {
var decl = new CCodeDeclaration (type_name);
decl.add_declarator (new CCodeVariableDeclarator (name, null, declarator_suffix));
add_declaration (decl);
diff --git a/ccode/valaccodevariabledeclarator.vala b/ccode/valaccodevariabledeclarator.vala
index 863ec83..c8dd874 100644
--- a/ccode/valaccodevariabledeclarator.vala
+++ b/ccode/valaccodevariabledeclarator.vala
@@ -39,7 +39,7 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
/**
* The optional declarator suffix.
*/
- public string? declarator_suffix { get; set; }
+ public CCodeDeclaratorSuffix? declarator_suffix { get; set; }
/**
* Initializer only used to zero memory, safe to initialize as part
@@ -47,13 +47,13 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
*/
public bool init0 { get; set; }
- public CCodeVariableDeclarator (string name, CCodeExpression? initializer = null, string?
declarator_suffix = null) {
+ public CCodeVariableDeclarator (string name, CCodeExpression? initializer = null,
CCodeDeclaratorSuffix? declarator_suffix = null) {
this.name = name;
this.initializer = initializer;
this.declarator_suffix = declarator_suffix;
}
- public CCodeVariableDeclarator.zero (string name, CCodeExpression? initializer, string?
declarator_suffix = null) {
+ public CCodeVariableDeclarator.zero (string name, CCodeExpression? initializer,
CCodeDeclaratorSuffix? declarator_suffix = null) {
this.name = name;
this.initializer = initializer;
this.declarator_suffix = declarator_suffix;
@@ -62,8 +62,9 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
public override void write (CCodeWriter writer) {
writer.write_string (name);
+
if (declarator_suffix != null) {
- writer.write_string (declarator_suffix);
+ declarator_suffix.write (writer);
}
if (initializer != null) {
@@ -74,8 +75,9 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
public override void write_declaration (CCodeWriter writer) {
writer.write_string (name);
+
if (declarator_suffix != null) {
- writer.write_string (declarator_suffix);
+ declarator_suffix.write (writer);
}
if (initializer != null && init0) {
@@ -97,3 +99,28 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
}
}
}
+
+public class Vala.CCodeDeclaratorSuffix {
+ public bool array;
+ public CCodeExpression? array_length;
+ public bool deprecated;
+
+ public CCodeDeclaratorSuffix.with_array (CCodeExpression? array_length = null) {
+ this.array_length = array_length;
+ array = true;
+ }
+
+ public void write (CCodeWriter writer) {
+ if (array) {
+ writer.write_string ("[");
+ if (array_length != null) {
+ array_length.write (writer);
+ }
+ writer.write_string ("]");
+ }
+
+ if (deprecated) {
+ writer.write_string (" G_GNUC_DEPRECATED");
+ }
+ }
+}
diff --git a/codegen/valaccodearraymodule.vala b/codegen/valaccodearraymodule.vala
index 7bf6826..8922464 100644
--- a/codegen/valaccodearraymodule.vala
+++ b/codegen/valaccodearraymodule.vala
@@ -117,7 +117,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var array_type = value.value_type as ArrayType;
if (array_type != null && array_type.fixed_length) {
- return new CCodeConstant (array_type.length.to_string ());
+ return get_ccodenode (array_type.length);
}
// dim == -1 => total size over all dimensions
@@ -452,7 +452,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy"));
ccall.add_argument (get_cvalue_ (value));
- ccall.add_argument (new CCodeConstant ("%d".printf (array_type.length)));
+ ccall.add_argument (get_ccodenode (array_type.length));
ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression
(array_type.element_type), "GDestroyNotify"));
return ccall;
@@ -559,7 +559,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
ccode.add_declaration ("int", new CCodeVariableDeclarator ("i"));
ccode.open_for (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant
("0")),
- new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new
CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))),
+ new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new
CCodeIdentifier ("i"), get_ccodenode (array_type.length)),
new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT,
new CCodeIdentifier ("i")));
@@ -573,7 +573,7 @@ public class Vala.CCodeArrayModule : CCodeMethodCallModule {
var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name
(array_type.element_type)));
- dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new
CCodeConstant ("%d".printf (array_type.length)), sizeof_call));
+ dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL,
get_ccodenode (array_type.length), sizeof_call));
ccode.add_expression (dup_call);
}
diff --git a/codegen/valaccodeassignmentmodule.vala b/codegen/valaccodeassignmentmodule.vala
index 67be9c9..76004f7 100644
--- a/codegen/valaccodeassignmentmodule.vala
+++ b/codegen/valaccodeassignmentmodule.vala
@@ -104,7 +104,7 @@ public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
// simple assignments do not work in C
var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name
(array_type.element_type)));
- var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant
("%d".printf (array_type.length)), sizeof_call);
+ var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode
(array_type.length), sizeof_call);
var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
ccopy.add_argument (get_cvalue_ (lvalue));
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index e708545..8e844a6 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -1897,7 +1897,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
if (local.captured) {
generate_type_declaration (local.variable_type, cfile);
- data.add_field (get_ccode_name (local.variable_type), get_local_cname
(local) + get_ccode_declarator_suffix (local.variable_type));
+ data.add_field (get_ccode_name (local.variable_type), get_local_cname
(local), get_ccode_declarator_suffix (local.variable_type));
if (local.variable_type is ArrayType) {
var array_type = (ArrayType) local.variable_type;
@@ -2311,7 +2311,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
}
emit_context.closure_variable_count_map.set (local.name, count + 1);
- closure_struct.add_field (get_ccode_name (local.variable_type),
get_local_cname (local) + get_ccode_declarator_suffix (local.variable_type));
+ closure_struct.add_field (get_ccode_name (local.variable_type),
get_local_cname (local), get_ccode_declarator_suffix (local.variable_type));
} else {
var cvar = new CCodeVariableDeclarator (get_local_cname (local), null,
get_ccode_declarator_suffix (local.variable_type));
@@ -6309,16 +6309,16 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
return blurb;
}
- public static string get_ccode_declarator_suffix (DataType type) {
+ public CCodeDeclaratorSuffix? get_ccode_declarator_suffix (DataType type) {
var array_type = type as ArrayType;
if (array_type != null) {
if (array_type.fixed_length) {
- return "[%d]".printf (array_type.length);
+ return new CCodeDeclaratorSuffix.with_array (get_ccodenode
(array_type.length));
} else if (array_type.inline_allocated) {
- return "[]";
+ return new CCodeDeclaratorSuffix.with_array ();
}
}
- return "";
+ return null;
}
public CCodeConstant get_signal_canonical_constant (Signal sig, string? detail = null) {
diff --git a/codegen/valaccodestructmodule.vala b/codegen/valaccodestructmodule.vala
index 86b1b9b..fe2a7c2 100644
--- a/codegen/valaccodestructmodule.vala
+++ b/codegen/valaccodestructmodule.vala
@@ -75,7 +75,12 @@ public abstract class Vala.CCodeStructModule : CCodeBaseModule {
if (f.binding == MemberBinding.INSTANCE) {
generate_type_declaration (f.variable_type, decl_space);
- instance_struct.add_field (field_ctype, get_ccode_name (f) +
get_ccode_declarator_suffix (f.variable_type), f.deprecated ? " G_GNUC_DEPRECATED" : null);
+ var suffix = get_ccode_declarator_suffix (f.variable_type);
+ if (suffix != null) {
+ suffix.deprecated = f.deprecated;
+ }
+
+ instance_struct.add_field (field_ctype, get_ccode_name (f), suffix);
if (f.variable_type is ArrayType && get_ccode_array_length (f)) {
// create fields to store array dimensions
var array_type = (ArrayType) f.variable_type;
diff --git a/codegen/valagirwriter.vala b/codegen/valagirwriter.vala
index e654509..e38b0ad 100644
--- a/codegen/valagirwriter.vala
+++ b/codegen/valagirwriter.vala
@@ -1262,8 +1262,9 @@ public class Vala.GIRWriter : CodeVisitor {
write_indent ();
buffer.append_printf ("<array");
- if (array_type.fixed_length) {
- buffer.append_printf (" fixed-size=\"%i\"", array_type.length);
+ if (array_type.fixed_length && array_type.length is IntegerLiteral) {
+ var lit = (IntegerLiteral) array_type.length;
+ buffer.append_printf (" fixed-size=\"%i\"", int.parse (lit.value));
} else if (index != -1) {
buffer.append_printf (" length=\"%i\"", index);
}
diff --git a/tests/basic-types/arrays.vala b/tests/basic-types/arrays.vala
index 4a6a006..00a7164 100644
--- a/tests/basic-types/arrays.vala
+++ b/tests/basic-types/arrays.vala
@@ -84,6 +84,7 @@ void test_array_pass () {
assert (b[0] == 42);
}
+const int FOO = 2;
void test_static_array () {
int a[2];
assert (a.length == 2);
@@ -91,6 +92,9 @@ void test_static_array () {
assert (a[1] == 23);
a = { 23, 34 };
assert (a[0] == 23 && a[1] == 34);
+
+ int b[FOO * 1 << 3];
+ assert (b.length == FOO * 1 << 3);
}
void test_reference_transfer () {
diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala
index 852342c..e1bf8d0 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -46,7 +46,15 @@ public class Vala.ArrayType : ReferenceType {
/**
* The length of this fixed-length array.
*/
- public int length { get; set; }
+ public Expression? length {
+ get { return _length; }
+ set {
+ _length = value;
+ if (_length != null) {
+ _length.parent_node = this;
+ }
+ }
+ }
/**
* The rank of this array.
@@ -54,6 +62,7 @@ public class Vala.ArrayType : ReferenceType {
public int rank { get; set; }
private DataType _element_type;
+ private Expression _length;
private ArrayLengthField length_field;
private ArrayResizeMethod resize_method;
@@ -231,6 +240,16 @@ public class Vala.ArrayType : ReferenceType {
error = true;
return false;
}
+
+ if (fixed_length && length != null) {
+ length.check (context);
+
+ if (length.value_type == null || !(length.value_type is IntegerType) ||
!length.is_constant ()) {
+ Report.error (length.source_reference, "Expression of constant integer type
expected");
+ return false;
+ }
+ }
+
return element_type.check (context);
}
diff --git a/vala/valacodewriter.vala b/vala/valacodewriter.vala
index 7f64fa2..0cfa469 100644
--- a/vala/valacodewriter.vala
+++ b/vala/valacodewriter.vala
@@ -1456,7 +1456,9 @@ public class Vala.CodeWriter : CodeVisitor {
private void write_type_suffix (DataType type) {
var array_type = type as ArrayType;
if (array_type != null && array_type.fixed_length) {
- write_string ("[%d]".printf (array_type.length));
+ write_string ("[");
+ array_type.length.accept (this);
+ write_string ("]");
}
}
diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala
index f479905..7abd943 100644
--- a/vala/valagenieparser.vala
+++ b/vala/valagenieparser.vala
@@ -602,21 +602,16 @@ public class Vala.Genie.Parser : CodeVisitor {
// inline-allocated array
if (type != null && accept (TokenType.OPEN_BRACKET)) {
- int array_length = -1;
+ Expression array_length = null;
if (current () != TokenType.CLOSE_BRACKET) {
- if (current () != TokenType.INTEGER_LITERAL) {
- throw new ParseError.SYNTAX (get_error ("expected `]' or integer
literal"));
- }
-
- var length_literal = (IntegerLiteral) parse_literal ();
- array_length = int.parse (length_literal.value);
+ array_length = parse_expression ();
}
expect (TokenType.CLOSE_BRACKET);
var array_type = new ArrayType (type, 1, get_src (begin));
array_type.inline_allocated = true;
- if (array_length > 0) {
+ if (array_length != null) {
array_type.fixed_length = true;
array_type.length = array_length;
}
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index a7ca9c0..3070cc0 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -499,21 +499,16 @@ public class Vala.Parser : CodeVisitor {
// inline-allocated array
if (type != null && accept (TokenType.OPEN_BRACKET)) {
- int array_length = -1;
+ Expression array_length = null;
if (current () != TokenType.CLOSE_BRACKET) {
- if (current () != TokenType.INTEGER_LITERAL) {
- throw new ParseError.SYNTAX (get_error ("expected `]' or integer
literal"));
- }
-
- var length_literal = (IntegerLiteral) parse_literal ();
- array_length = int.parse (length_literal.value);
+ array_length = parse_expression ();
}
expect (TokenType.CLOSE_BRACKET);
var array_type = new ArrayType (type, 1, get_src (begin));
array_type.inline_allocated = true;
- if (array_length > 0) {
+ if (array_length != null) {
array_type.fixed_length = true;
array_type.length = array_length;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]