[vala] Arrays: Add experimental support for fixed-length arrays
- From: Jürg Billeter <juergbi src gnome org>
- To: svn-commits-list gnome org
- Subject: [vala] Arrays: Add experimental support for fixed-length arrays
- Date: Fri, 10 Apr 2009 11:05:45 -0400 (EDT)
commit e065e581748863cb7c90fabb2bb39d6671dfbe8f
Author: Jürg Billeter <j bitron ch>
Date: Fri Apr 10 17:02:22 2009 +0200
Arrays: Add experimental support for fixed-length arrays
Local fixed-length arrays are allocated on the stack.
int[3] array = { 1, 2, 3 };
Fixes bug 492481.
---
ccode/valaccodevariabledeclarator.vala | 14 +++-
gobject/valaccodearraymodule.vala | 169 ++++++++++++++++++++++++++++++-
gobject/valaccodeassignmentmodule.vala | 24 ++++-
gobject/valaccodebasemodule.vala | 128 +++++++++++++++--------
gobject/valaccodecontrolflowmodule.vala | 11 ++-
gobject/valaccodestructmodule.vala | 43 ++++++---
vala/valaarraytype.vala | 28 +++++-
vala/valadatatype.vala | 4 +
vala/valaparser.vala | 19 +++-
9 files changed, 370 insertions(+), 70 deletions(-)
diff --git a/ccode/valaccodevariabledeclarator.vala b/ccode/valaccodevariabledeclarator.vala
index c28704d..fdb9dfa 100644
--- a/ccode/valaccodevariabledeclarator.vala
+++ b/ccode/valaccodevariabledeclarator.vala
@@ -36,13 +36,22 @@ public class Vala.CCodeVariableDeclarator : CCodeDeclarator {
*/
public CCodeExpression? initializer { get; set; }
- public CCodeVariableDeclarator (string name, CCodeExpression? initializer = null) {
+ /**
+ * The optional declarator suffix.
+ */
+ public string? declarator_suffix { get; set; }
+
+ public CCodeVariableDeclarator (string name, CCodeExpression? initializer = null, string? declarator_suffix = null) {
this.name = name;
this.initializer = initializer;
+ this.declarator_suffix = declarator_suffix;
}
public override void write (CCodeWriter writer) {
writer.write_string (name);
+ if (declarator_suffix != null) {
+ writer.write_string (declarator_suffix);
+ }
if (initializer != null) {
writer.write_string (" = ");
@@ -52,6 +61,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);
+ }
// initializer lists can't be moved to a separate statement
if (initializer is CCodeInitializerList) {
diff --git a/gobject/valaccodearraymodule.vala b/gobject/valaccodearraymodule.vala
index f1a9ba8..2143f3f 100644
--- a/gobject/valaccodearraymodule.vala
+++ b/gobject/valaccodearraymodule.vala
@@ -46,6 +46,26 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
public override void visit_array_creation_expression (ArrayCreationExpression expr) {
expr.accept_children (codegen);
+ var array_type = expr.target_type as ArrayType;
+ if (array_type != null && array_type.fixed_length) {
+ // no heap allocation for fixed-length arrays
+
+ var ce = new CCodeCommaExpression ();
+ var temp_var = get_temp_variable (array_type, true, expr);
+ var name_cnode = new CCodeIdentifier (temp_var.name);
+ int i = 0;
+
+ temp_vars.insert (0, temp_var);
+
+ append_initializer_list (ce, name_cnode, expr.initializer_list, expr.rank, ref i);
+
+ ce.append_expression (name_cnode);
+
+ expr.ccodenode = ce;
+
+ return;
+ }
+
var gnew = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
gnew.add_argument (new CCodeIdentifier (expr.element_type.get_cname ()));
bool first = true;
@@ -105,9 +125,14 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
}
public override CCodeExpression get_array_length_cexpression (Expression array_expr, int dim = -1) {
+ var array_type = array_expr.value_type as ArrayType;
+
+ if (array_type != null && array_type.fixed_length) {
+ return new CCodeConstant (array_type.length.to_string ());
+ }
+
// dim == -1 => total size over all dimensions
if (dim == -1) {
- var array_type = array_expr.value_type as ArrayType;
if (array_type != null && array_type.rank > 1) {
CCodeExpression cexpr = get_array_length_cexpression (array_expr, 1);
for (dim = 2; dim <= array_type.rank; dim++) {
@@ -370,7 +395,9 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
}
public override void append_vala_array_free () {
- var fun = new CCodeFunction ("_vala_array_free", "void");
+ // _vala_array_destroy only frees elements but not the array itself
+
+ var fun = new CCodeFunction ("_vala_array_destroy", "void");
fun.modifiers = CCodeModifiers.STATIC;
fun.add_parameter (new CCodeFormalParameter ("array", "gpointer"));
fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
@@ -391,6 +418,26 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
fun.block = new CCodeBlock ();
fun.block.add_statement (cif);
+ source_type_member_definition.append (fun);
+
+ // _vala_array_free frees elements and array
+
+ fun = new CCodeFunction ("_vala_array_free", "void");
+ fun.modifiers = CCodeModifiers.STATIC;
+ fun.add_parameter (new CCodeFormalParameter ("array", "gpointer"));
+ fun.add_parameter (new CCodeFormalParameter ("array_length", "gint"));
+ fun.add_parameter (new CCodeFormalParameter ("destroy_func", "GDestroyNotify"));
+ source_declarations.add_type_member_declaration (fun.copy ());
+
+ // call _vala_array_destroy to free the array elements
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy"));
+ ccall.add_argument (new CCodeIdentifier ("array"));
+ ccall.add_argument (new CCodeIdentifier ("array_length"));
+ ccall.add_argument (new CCodeIdentifier ("destroy_func"));
+
+ fun.block = new CCodeBlock ();
+ fun.block.add_statement (new CCodeExpressionStatement (ccall));
+
var carrfree = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
carrfree.add_argument (new CCodeIdentifier ("array"));
fun.block.add_statement (new CCodeExpressionStatement (carrfree));
@@ -480,14 +527,69 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
source_type_member_definition.append (fun);
}
+ public override CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
+ if (expression_type is ArrayType) {
+ var array_type = (ArrayType) expression_type;
+
+ if (!array_type.fixed_length) {
+ return base.get_ref_cexpression (expression_type, cexpr, expr, node);
+ }
+
+ var decl = get_temp_variable (expression_type, false, node);
+ temp_vars.insert (0, decl);
+
+ var ctemp = get_variable_cexpression (decl.name);
+
+ var copy_call = new CCodeFunctionCall (new CCodeIdentifier (generate_array_copy_wrapper (array_type)));
+ copy_call.add_argument (cexpr);
+ copy_call.add_argument (ctemp);
+
+ var ccomma = new CCodeCommaExpression ();
+
+ ccomma.append_expression (copy_call);
+ ccomma.append_expression (ctemp);
+
+ return ccomma;
+ } else {
+ return base.get_ref_cexpression (expression_type, cexpr, expr, node);
+ }
+ }
+
public override CCodeExpression? get_dup_func_expression (DataType type, SourceReference? source_reference) {
if (type is ArrayType) {
- return new CCodeIdentifier (generate_array_dup_wrapper ((ArrayType) type));
+ var array_type = (ArrayType) type;
+ // fixed length arrays use different code
+ // generated by overridden get_ref_cexpression method
+ assert (!array_type.fixed_length);
+ return new CCodeIdentifier (generate_array_dup_wrapper (array_type));
} else {
return base.get_dup_func_expression (type, source_reference);
}
}
+ public override CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
+ if (type is ArrayType) {
+ var array_type = (ArrayType) type;
+
+ if (!array_type.fixed_length) {
+ return base.get_unref_expression (cvar, type, expr);
+ }
+
+ requires_array_free = true;
+
+ var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_destroy"));
+ ccall.add_argument (cvar);
+ ccall.add_argument (new CCodeConstant ("%d".printf (array_type.length)));
+ ccall.add_argument (new CCodeCastExpression (get_destroy_func_expression (array_type.element_type), "GDestroyNotify"));
+
+ return ccall;
+ } else {
+ return base.get_unref_expression (cvar, type, expr);
+ }
+ }
+
string generate_array_dup_wrapper (ArrayType array_type) {
string dup_func = "_vala_array_dup%d".printf (++next_array_dup_id);
@@ -560,6 +662,67 @@ internal class Vala.CCodeArrayModule : CCodeMethodCallModule {
return dup_func;
}
+ string generate_array_copy_wrapper (ArrayType array_type) {
+ string dup_func = "_vala_array_copy%d".printf (++next_array_dup_id);
+
+ if (!add_wrapper (dup_func)) {
+ // wrapper already defined
+ return dup_func;
+ }
+
+ // declaration
+
+ var function = new CCodeFunction (dup_func, "void");
+ function.modifiers = CCodeModifiers.STATIC;
+
+ function.add_parameter (new CCodeFormalParameter ("self", array_type.get_cname () + "*"));
+ function.add_parameter (new CCodeFormalParameter ("dest", array_type.get_cname () + "*"));
+
+ // definition
+
+ var block = new CCodeBlock ();
+
+ if (requires_copy (array_type.element_type)) {
+ var old_temp_vars = temp_vars;
+
+ var idx_decl = new CCodeDeclaration ("int");
+ idx_decl.add_declarator (new CCodeVariableDeclarator ("i"));
+ block.add_statement (idx_decl);
+
+ var loop_body = new CCodeBlock ();
+ loop_body.add_statement (new CCodeExpressionStatement (new CCodeAssignment (new CCodeElementAccess (new CCodeIdentifier ("dest"), new CCodeIdentifier ("i")), get_ref_cexpression (array_type.element_type, new CCodeElementAccess (new CCodeIdentifier ("self"), new CCodeIdentifier ("i")), null, array_type))));
+
+ var cfor = new CCodeForStatement (new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier ("i"), new CCodeConstant ("%d".printf (array_type.length))), loop_body);
+ cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier ("i"), new CCodeConstant ("0")));
+ cfor.add_iterator (new CCodeUnaryExpression (CCodeUnaryOperator.POSTFIX_INCREMENT, new CCodeIdentifier ("i")));
+ block.add_statement (cfor);
+
+ var cfrag = new CCodeFragment ();
+ append_temp_decl (cfrag, temp_vars);
+ block.add_statement (cfrag);
+ temp_vars = old_temp_vars;
+ } else {
+ var dup_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+ dup_call.add_argument (new CCodeIdentifier ("dest"));
+ dup_call.add_argument (new CCodeIdentifier ("self"));
+
+ var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ dup_call.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call));
+
+ block.add_statement (new CCodeExpressionStatement (dup_call));
+ }
+
+ // append to file
+
+ source_declarations.add_type_member_declaration (function.copy ());
+
+ function.block = block;
+ source_type_member_definition.append (function);
+
+ return dup_func;
+ }
+
string generate_array_add_wrapper (ArrayType array_type) {
string add_func = "_vala_array_add%d".printf (++next_array_add_id);
diff --git a/gobject/valaccodeassignmentmodule.vala b/gobject/valaccodeassignmentmodule.vala
index fa64ccc..4470628 100644
--- a/gobject/valaccodeassignmentmodule.vala
+++ b/gobject/valaccodeassignmentmodule.vala
@@ -208,6 +208,23 @@ internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
return codenode;
}
+ CCodeExpression emit_fixed_length_array_assignment (Assignment assignment, ArrayType array_type) {
+ CCodeExpression rhs = (CCodeExpression) assignment.right.ccodenode;
+ CCodeExpression lhs = (CCodeExpression) get_ccodenode (assignment.left);
+
+ // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
+ // simple assignments do not work in C
+ var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call);
+ var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+ ccopy.add_argument (lhs);
+ ccopy.add_argument (rhs);
+ ccopy.add_argument (size);
+
+ return ccopy;
+ }
+
public override void visit_assignment (Assignment assignment) {
assignment.right.accept (codegen);
@@ -219,7 +236,12 @@ internal class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
if (assignment.left.symbol_reference is Property) {
assignment.ccodenode = emit_property_assignment (assignment);
} else {
- assignment.ccodenode = emit_simple_assignment (assignment);
+ var array_type = assignment.left.value_type as ArrayType;
+ if (array_type != null && array_type.fixed_length) {
+ assignment.ccodenode = emit_fixed_length_array_assignment (assignment, array_type);
+ } else {
+ assignment.ccodenode = emit_simple_assignment (assignment);
+ }
}
}
}
diff --git a/gobject/valaccodebasemodule.vala b/gobject/valaccodebasemodule.vala
index e11eece..a4e5506 100644
--- a/gobject/valaccodebasemodule.vala
+++ b/gobject/valaccodebasemodule.vala
@@ -1480,15 +1480,17 @@ internal class Vala.CCodeBaseModule : CCodeModule {
if (local.variable_type is ArrayType) {
// create variables to store array dimensions
var array_type = (ArrayType) local.variable_type;
-
- for (int dim = 1; dim <= array_type.rank; dim++) {
- var len_var = new LocalVariable (int_type.copy (), head.get_array_length_cname (get_variable_cname (local.name), dim));
- temp_vars.insert (0, len_var);
- }
- if (array_type.rank == 1) {
- var size_var = new LocalVariable (int_type.copy (), head.get_array_size_cname (get_variable_cname (local.name)));
- temp_vars.insert (0, size_var);
+ if (!array_type.fixed_length) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ var len_var = new LocalVariable (int_type.copy (), head.get_array_length_cname (get_variable_cname (local.name), dim));
+ temp_vars.insert (0, len_var);
+ }
+
+ if (array_type.rank == 1) {
+ var size_var = new LocalVariable (int_type.copy (), head.get_array_size_cname (get_variable_cname (local.name)));
+ temp_vars.insert (0, size_var);
+ }
}
} else if (local.variable_type is DelegateType) {
var deleg_type = (DelegateType) local.variable_type;
@@ -1507,26 +1509,30 @@ internal class Vala.CCodeBaseModule : CCodeModule {
if (local.variable_type is ArrayType) {
var array_type = (ArrayType) local.variable_type;
- var ccomma = new CCodeCommaExpression ();
+ if (array_type.fixed_length) {
+ rhs = null;
+ } else {
+ var ccomma = new CCodeCommaExpression ();
- var temp_var = get_temp_variable (local.variable_type, true, local);
- temp_vars.insert (0, temp_var);
- ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs));
+ var temp_var = get_temp_variable (local.variable_type, true, local);
+ temp_vars.insert (0, temp_var);
+ ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (temp_var.name), rhs));
- for (int dim = 1; dim <= array_type.rank; dim++) {
- var lhs_array_len = get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), dim));
- var rhs_array_len = head.get_array_length_cexpression (local.initializer, dim);
- ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
- }
- if (array_type.rank == 1) {
- var lhs_array_size = get_variable_cexpression (head.get_array_size_cname (get_variable_cname (local.name)));
- var rhs_array_len = get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), 1));
- ccomma.append_expression (new CCodeAssignment (lhs_array_size, rhs_array_len));
- }
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ var lhs_array_len = get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), dim));
+ var rhs_array_len = head.get_array_length_cexpression (local.initializer, dim);
+ ccomma.append_expression (new CCodeAssignment (lhs_array_len, rhs_array_len));
+ }
+ if (array_type.rank == 1) {
+ var lhs_array_size = get_variable_cexpression (head.get_array_size_cname (get_variable_cname (local.name)));
+ var rhs_array_len = get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), 1));
+ ccomma.append_expression (new CCodeAssignment (lhs_array_size, rhs_array_len));
+ }
- ccomma.append_expression (get_variable_cexpression (temp_var.name));
+ ccomma.append_expression (get_variable_cexpression (temp_var.name));
- rhs = ccomma;
+ rhs = ccomma;
+ }
} else if (local.variable_type is DelegateType) {
var deleg_type = (DelegateType) local.variable_type;
var d = deleg_type.delegate_symbol;
@@ -1553,15 +1559,19 @@ internal class Vala.CCodeBaseModule : CCodeModule {
// initialize array length variables
var array_type = (ArrayType) local.variable_type;
- var ccomma = new CCodeCommaExpression ();
+ if (array_type.fixed_length) {
+ rhs = null;
+ } else {
+ var ccomma = new CCodeCommaExpression ();
- for (int dim = 1; dim <= array_type.rank; dim++) {
- ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), dim)), new CCodeConstant ("0")));
- }
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ ccomma.append_expression (new CCodeAssignment (get_variable_cexpression (head.get_array_length_cname (get_variable_cname (local.name), dim)), new CCodeConstant ("0")));
+ }
- ccomma.append_expression (rhs);
+ ccomma.append_expression (rhs);
- rhs = ccomma;
+ rhs = ccomma;
+ }
}
}
@@ -1573,13 +1583,13 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
if (current_method != null && current_method.coroutine) {
- closure_struct.add_field (local.variable_type.get_cname (), get_variable_cname (local.name));
+ closure_struct.add_field (local.variable_type.get_cname (), get_variable_cname (local.name) + local.variable_type.get_cdeclarator_suffix ());
if (local.initializer != null) {
cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), get_variable_cname (local.name)), rhs)));
}
} else {
- var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs);
+ var cvar = new CCodeVariableDeclarator (get_variable_cname (local.name), rhs, local.variable_type.get_cdeclarator_suffix ());
var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
cdecl.add_declarator (cvar);
@@ -1592,6 +1602,24 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
+ if (local.initializer != null && local.variable_type is ArrayType) {
+ var array_type = (ArrayType) local.variable_type;
+
+ if (array_type.fixed_length) {
+ // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
+ // simple assignments do not work in C
+ var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call);
+
+ var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+ ccopy.add_argument (get_variable_cexpression (local.name));
+ ccopy.add_argument ((CCodeExpression) local.initializer.ccodenode);
+ ccopy.add_argument (size);
+ cfrag.append (new CCodeExpressionStatement (ccopy));
+ }
+ }
+
if (local.initializer != null && local.initializer.tree_can_fail) {
head.add_simple_check (local.initializer, cfrag);
}
@@ -1883,7 +1911,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
return destroy_func;
}
- public CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
+ public virtual CCodeExpression get_unref_expression (CCodeExpression cvar, DataType type, Expression expr) {
var ccall = new CCodeFunctionCall (get_destroy_func_expression (type));
if (type is ValueType && !type.nullable) {
@@ -1938,8 +1966,8 @@ internal class Vala.CCodeBaseModule : CCodeModule {
if (array_type.element_type.data_type == null || array_type.element_type.data_type.is_reference_type ()) {
requires_array_free = true;
- bool first = true;
CCodeExpression csizeexpr = null;
+ bool first = true;
for (int dim = 1; dim <= array_type.rank; dim++) {
if (first) {
csizeexpr = head.get_array_length_cexpression (expr, dim);
@@ -2029,27 +2057,29 @@ internal class Vala.CCodeBaseModule : CCodeModule {
} else {
var cdecl = new CCodeDeclaration (local.variable_type.get_cname ());
- var vardecl = new CCodeVariableDeclarator (local.name);
+ var vardecl = new CCodeVariableDeclarator (local.name, null, local.variable_type.get_cdeclarator_suffix ());
// sets #line
local.ccodenode = vardecl;
cdecl.add_declarator (vardecl);
var st = local.variable_type.data_type as Struct;
+ var array_type = local.variable_type as ArrayType;
if (local.name.has_prefix ("*")) {
// do not dereference unintialized variable
// initialization is not needed for these special
// pointer temp variables
// used to avoid side-effects in assignments
- } else if (local.variable_type.is_reference_type_or_type_parameter ()) {
- vardecl.initializer = new CCodeConstant ("NULL");
- } else if (st != null && !st.is_simple_type ()) {
+ } else if ((st != null && !st.is_simple_type ()) ||
+ (array_type != null && array_type.fixed_length)) {
// 0-initialize struct with struct initializer { 0 }
// necessary as they will be passed by reference
var clist = new CCodeInitializerList ();
clist.append (new CCodeConstant ("0"));
vardecl.initializer = clist;
+ } else if (local.variable_type.is_reference_type_or_type_parameter ()) {
+ vardecl.initializer = new CCodeConstant ("NULL");
}
cfrag.append (cdecl);
@@ -2530,6 +2560,11 @@ internal class Vala.CCodeBaseModule : CCodeModule {
return false;
}
+ var array_type = type as ArrayType;
+ if (array_type != null && array_type.fixed_length) {
+ return requires_destroy (array_type.element_type);
+ }
+
var cl = type.data_type as Class;
if (cl != null && cl.is_reference_counting ()
&& cl.get_unref_function () == "") {
@@ -2555,7 +2590,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
}
- public CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
+ public virtual CCodeExpression? get_ref_cexpression (DataType expression_type, CCodeExpression cexpr, Expression? expr, CodeNode node) {
if (expression_type is ValueType && !expression_type.nullable) {
// normal value type, no null check
// (copy (&expr, &temp), temp)
@@ -3678,17 +3713,20 @@ internal class Vala.CCodeBaseModule : CCodeModule {
}
public CCodeExpression? default_value_for_type (DataType type, bool initializer_expression) {
- if ((type.data_type != null && type.data_type.is_reference_type ())
- || type is PointerType || type is ArrayType || type is DelegateType) {
- return new CCodeConstant ("NULL");
- } else if (type.data_type != null && type.data_type.get_default_value () != null) {
- return new CCodeConstant (type.data_type.get_default_value ());
- } else if (type.data_type is Struct && initializer_expression) {
+ var array_type = type as ArrayType;
+ if (initializer_expression && (type.data_type is Struct ||
+ (array_type != null && array_type.fixed_length))) {
// 0-initialize struct with struct initializer { 0 }
// only allowed as initializer expression in C
var clist = new CCodeInitializerList ();
clist.append (new CCodeConstant ("0"));
return clist;
+ } else if ((type.data_type != null && type.data_type.is_reference_type ())
+ || type is PointerType || type is DelegateType
+ || (array_type != null && !array_type.fixed_length)) {
+ return new CCodeConstant ("NULL");
+ } else if (type.data_type != null && type.data_type.get_default_value () != null) {
+ return new CCodeConstant (type.data_type.get_default_value ());
} else if (type.type_parameter != null) {
return new CCodeConstant ("NULL");
} else if (type is ErrorType) {
diff --git a/gobject/valaccodecontrolflowmodule.vala b/gobject/valaccodecontrolflowmodule.vala
index a9348d9..fda6f46 100644
--- a/gobject/valaccodecontrolflowmodule.vala
+++ b/gobject/valaccodecontrolflowmodule.vala
@@ -1,6 +1,7 @@
/* valaccodecontrolflowmodule.vala
*
- * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2009 Jürg Billeter
+ * Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -282,6 +283,12 @@ internal class Vala.CCodeControlFlowModule : CCodeMethodModule {
var collection_backup = stmt.collection_variable;
var collection_type = collection_backup.variable_type.copy ();
+ var array_type = collection_type as ArrayType;
+ if (array_type != null) {
+ // avoid assignment issues
+ array_type.fixed_length = false;
+ }
+
if (current_method != null && current_method.coroutine) {
closure_struct.add_field (collection_type.get_cname (), collection_backup.name);
cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (collection_backup.name), (CCodeExpression) stmt.collection.ccodenode)));
@@ -301,7 +308,7 @@ internal class Vala.CCodeControlFlowModule : CCodeMethodModule {
}
if (stmt.collection.value_type is ArrayType) {
- var array_type = (ArrayType) stmt.collection.value_type;
+ array_type = (ArrayType) stmt.collection.value_type;
var array_len = head.get_array_length_cexpression (stmt.collection);
diff --git a/gobject/valaccodestructmodule.vala b/gobject/valaccodestructmodule.vala
index bbc2c94..b45578c 100644
--- a/gobject/valaccodestructmodule.vala
+++ b/gobject/valaccodestructmodule.vala
@@ -45,18 +45,21 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
if (f.binding == MemberBinding.INSTANCE) {
generate_type_declaration (f.field_type, decl_space);
- instance_struct.add_field (field_ctype, f.get_cname ());
+ instance_struct.add_field (field_ctype, f.get_cname () + f.field_type.get_cdeclarator_suffix ());
if (f.field_type is ArrayType && !f.no_array_length) {
// create fields to store array dimensions
var array_type = (ArrayType) f.field_type;
- var len_type = int_type.copy ();
- for (int dim = 1; dim <= array_type.rank; dim++) {
- instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
- }
+ if (!array_type.fixed_length) {
+ var len_type = int_type.copy ();
+
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ instance_struct.add_field (len_type.get_cname (), head.get_array_length_cname (f.name, dim));
+ }
- if (array_type.rank == 1 && f.is_internal_symbol ()) {
- instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+ if (array_type.rank == 1 && f.is_internal_symbol ()) {
+ instance_struct.add_field (len_type.get_cname (), head.get_array_size_cname (f.name));
+ }
}
} else if (f.field_type is DelegateType) {
var delegate_type = (DelegateType) f.field_type;
@@ -201,14 +204,28 @@ internal class Vala.CCodeStructModule : CCodeBaseModule {
copy = get_ref_cexpression (f.field_type, copy, ma, f);
}
var dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), f.name);
- cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (dest, copy)));
var array_type = f.field_type as ArrayType;
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- var len_src = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), get_array_length_cname (f.name, dim));
- var len_dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), get_array_length_cname (f.name, dim));
- cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (len_dest, len_src)));
+ if (array_type != null && array_type.fixed_length) {
+ // fixed-length (stack-allocated) arrays
+ var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
+ sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
+ var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call);
+
+ var array_copy_call = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
+ array_copy_call.add_argument (dest);
+ array_copy_call.add_argument (copy);
+ array_copy_call.add_argument (size);
+ cblock.add_statement (new CCodeExpressionStatement (array_copy_call));
+ } else {
+ cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (dest, copy)));
+
+ if (array_type != null) {
+ for (int dim = 1; dim <= array_type.rank; dim++) {
+ var len_src = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), get_array_length_cname (f.name, dim));
+ var len_dest = new CCodeMemberAccess.pointer (new CCodeIdentifier ("dest"), get_array_length_cname (f.name, dim));
+ cblock.add_statement (new CCodeExpressionStatement (new CCodeAssignment (len_dest, len_src)));
+ }
}
}
}
diff --git a/vala/valaarraytype.vala b/vala/valaarraytype.vala
index 1534c6d..4711555 100644
--- a/vala/valaarraytype.vala
+++ b/vala/valaarraytype.vala
@@ -37,6 +37,13 @@ public class Vala.ArrayType : ReferenceType {
}
}
+ public bool fixed_length { get; set; }
+
+ /**
+ * The length of this fixed-length array.
+ */
+ public int length { get; set; }
+
/**
* The rank of this array.
*/
@@ -127,13 +134,30 @@ public class Vala.ArrayType : ReferenceType {
result.value_owned = value_owned;
result.nullable = nullable;
result.floating_reference = floating_reference;
-
+
+ if (fixed_length) {
+ result.fixed_length = true;
+ result.length = length;
+ }
+
return result;
}
public override string? get_cname () {
// FIXME add support for [Immutable] or [Const] attribute to support arrays to const data
- return element_type.get_cname () + "*";
+ if (fixed_length) {
+ return element_type.get_cname ();
+ } else {
+ return element_type.get_cname () + "*";
+ }
+ }
+
+ public override string get_cdeclarator_suffix () {
+ if (fixed_length) {
+ return "[%d]".printf (length);
+ } else {
+ return "";
+ }
}
public override bool is_array () {
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index 68199e8..45af866 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -118,6 +118,10 @@ public abstract class Vala.DataType : CodeNode {
return null;
}
+ public virtual string get_cdeclarator_suffix () {
+ return "";
+ }
+
/**
* Returns the name and qualifiers of this type as it is used in C code
* in a const declaration.
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index ee9e696..ab11ad1 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -422,13 +422,18 @@ public class Vala.Parser : CodeVisitor {
// this is more logical, especially when nullable arrays
// or pointers are involved
while (accept (TokenType.OPEN_BRACKET)) {
+ int array_length = -1;
int array_rank = 0;
do {
array_rank++;
// support for stack-allocated arrays
// also required for decision between expression and declaration statement
if (current () != TokenType.COMMA && current () != TokenType.CLOSE_BRACKET) {
- parse_expression ();
+ var length_expression = parse_expression ();
+ var length_literal = length_expression as IntegerLiteral;
+ if (length_literal != null) {
+ array_length = length_literal.value.to_int ();
+ }
}
}
while (accept (TokenType.COMMA));
@@ -437,8 +442,16 @@ public class Vala.Parser : CodeVisitor {
// arrays contain strong references by default
type.value_owned = true;
- type = new ArrayType (type, array_rank, get_src (begin));
- type.nullable = accept (TokenType.INTERR);
+ var array_type = new ArrayType (type, array_rank, get_src (begin));
+ array_type.nullable = accept (TokenType.INTERR);
+
+ if (array_rank == 1 && array_length > 0) {
+ // fixed length (stack-allocated) array
+ array_type.fixed_length = true;
+ array_type.length = array_length;
+ }
+
+ type = array_type;
}
if (accept (TokenType.OP_NEG)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]