]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Arrays: Add experimental support for fixed-length arrays
authorJürg Billeter <j@bitron.ch>
Fri, 10 Apr 2009 15:02:22 +0000 (17:02 +0200)
committerJürg Billeter <j@bitron.ch>
Fri, 10 Apr 2009 15:04:48 +0000 (17:04 +0200)
Local fixed-length arrays are allocated on the stack.

    int[3] array = { 1, 2, 3 };

Fixes bug 492481.

ccode/valaccodevariabledeclarator.vala
gobject/valaccodearraymodule.vala
gobject/valaccodeassignmentmodule.vala
gobject/valaccodebasemodule.vala
gobject/valaccodecontrolflowmodule.vala
gobject/valaccodestructmodule.vala
vala/valaarraytype.vala
vala/valadatatype.vala
vala/valaparser.vala

index c28704d2054a79ec758f2aa9db080ef5fdee1a83..fdb9dfab86bc71961c7dd2d795ed6e32b1a73e78 100644 (file)
@@ -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) {
index f1a9ba8b1c201803f63c9dcd68bc166b36eff600..2143f3f255fa8b91e25fed0e58b3206e8def83ab 100644 (file)
@@ -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);
 
index fa64ccc2161d32f955dd6ec0dca17a4608425a50..44706288de7cecd5ffb55f47b0e3738773f7fb27 100644 (file)
@@ -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);
+                       }
                }
        }
 }
index e11eece0d7d9f7fab1d9852eb0526457675bba83..a4e5506bb959d1836005a3d994fe418616b0cef5 100644 (file)
@@ -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) {
index a9348d9c5016150c6276107fe527870e26ba59ca..fda6f462324eaf5076f5bac6b686512c4d2b1e2f 100644 (file)
@@ -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);
 
index bbc2c945614bed00c5a2a1d44013eb6341d0d499..b45578cdfedc951808641ba1cb145adce1ab23de 100644 (file)
@@ -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)));
+                                               }
                                        }
                                }
                        }
index 1534c6ddff0e7ce7cf64cf807ba6d8e21eae9d19..4711555625183ce5786c758276d1ee21451a371a 100644 (file)
@@ -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 () {
index 68199e86d31c82fa12e1b1d9b4055871f27bef2a..45af866065cdd47b1b70553f355f1b8646e03443 100644 (file)
@@ -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.
index ee9e696efc5eb1d0cb98a8a439dff64227476bf8..ab11ad142b7fe994cf1f7333ba7882233f595477 100644 (file)
@@ -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)) {