]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Add support for iterating over GValueArrays via foreach
authorMark Lee <marklee@src.gnome.org>
Thu, 16 Jul 2009 06:33:39 +0000 (23:33 -0700)
committerJürg Billeter <j@bitron.ch>
Tue, 28 Jul 2009 14:03:33 +0000 (16:03 +0200)
Implements working support for using ValueArrays in foreach statements. Both
owned and unowned Value element types are implemented, including a testcase.

Example:

void print_array (ValueArray array) {
  foreach (Value value in array) {
    message ("Value: %s", value.strdup_contents ());
  }
}

Fixes bug 588742.

codegen/valaccodebasemodule.vala
codegen/valaccodecontrolflowmodule.vala
tests/Makefile.am
tests/control-flow/foreach.test [new file with mode: 0644]
vala/valaforeachstatement.vala
vala/valasemanticanalyzer.vala

index 2ac63ba47bcc4b6c29bfbdb4d92fe421a1fe8b54..3b51d42897f8280008c818818b13915a7fded41a 100644 (file)
@@ -107,6 +107,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
        public ErrorType gerror_type;
        public Class glist_type;
        public Class gslist_type;
+       public Class gvaluearray_type;
        public TypeSymbol gstringbuilder_type;
        public TypeSymbol garray_type;
        public TypeSymbol gbytearray_type;
@@ -245,6 +246,7 @@ internal class Vala.CCodeBaseModule : CCodeModule {
                        gerror_type = new ErrorType (null, null);
                        glist_type = (Class) glib_ns.scope.lookup ("List");
                        gslist_type = (Class) glib_ns.scope.lookup ("SList");
+                       gvaluearray_type = (Class) glib_ns.scope.lookup ("ValueArray");
                        gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
                        garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
                        gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
index 86a98e3db71b2b588ce12e917a6d4254ded6c2d6..19a30a0587b020160c097e919b091dd4aa909534 100644 (file)
@@ -401,6 +401,60 @@ internal class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (collection_backup.name)));
 
                        cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
+                       cblock.add_statement (cfor);
+               } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
+                       // iterating over a GValueArray
+
+                       var arr_index = "%s_index".printf (stmt.variable_name);
+
+                       if (current_method != null && current_method.coroutine) {
+                               closure_struct.add_field (uint_type.get_cname (), arr_index);
+                       } else {
+                               var citdecl = new CCodeDeclaration (uint_type.get_cname ());
+                               var citvardecl = new CCodeVariableDeclarator (arr_index);
+                               citvardecl.line = cblock.line;
+                               citdecl.add_declarator (citvardecl);
+                               cblock.add_statement (citdecl);
+                       }
+
+                       var cbody = new CCodeBlock ();
+
+                       var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth"));
+                       get_item.add_argument (get_variable_cexpression (collection_backup.name));
+                       get_item.add_argument (get_variable_cexpression (arr_index));
+
+                       CCodeExpression element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_item);
+
+                       if (stmt.type_reference.value_owned) {
+                               element_expr = get_ref_cexpression (stmt.type_reference, element_expr, null, new StructValueType (gvalue_type));
+                       }
+
+                       cfrag = new CCodeFragment ();
+                       append_temp_decl (cfrag, temp_vars);
+                       cbody.add_statement (cfrag);
+                       temp_vars.clear ();
+
+                       if (current_method != null && current_method.coroutine) {
+                               closure_struct.add_field (stmt.type_reference.get_cname (), stmt.variable_name);
+                               cbody.add_statement (new CCodeExpressionStatement (new CCodeAssignment (get_variable_cexpression (stmt.variable_name), element_expr)));
+                       } else {
+                               var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                               var cvardecl = new CCodeVariableDeclarator (stmt.variable_name, element_expr);
+                               cvardecl.line = cblock.line;
+                               cdecl.add_declarator (cvardecl);
+                               cbody.add_statement (cdecl);
+                       }
+
+                       cbody.add_statement (stmt.body.ccodenode);
+
+                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (collection_backup.name), "n_values"));
+
+                       var cfor = new CCodeForStatement (ccond, cbody);
+
+                       cfor.add_initializer (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")));
+
+                       cfor.add_iterator (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
+
                        cblock.add_statement (cfor);
                }
 
index c5599ab3acdf55342f657579449f8a47c5324701..ad9bae5c1bc35be01262815711d55ed4389c87e4 100644 (file)
@@ -25,6 +25,7 @@ TESTS = \
        control-flow/break.test \
        control-flow/expressions-conditional.test \
        control-flow/for.test \
+       control-flow/foreach.test \
        control-flow/switch.test \
        control-flow/sideeffects.test \
        enums/enums.test \
diff --git a/tests/control-flow/foreach.test b/tests/control-flow/foreach.test
new file mode 100644 (file)
index 0000000..de8d128
--- /dev/null
@@ -0,0 +1,42 @@
+
+Program: test
+
+
+void test_owned (ValueArray array) {
+       uint i = 0;
+
+       foreach (Value item in array) {
+               i++;
+       }
+
+       assert (i == 3);
+}
+
+void test_unowned (ValueArray array) {
+       uint i = 0;
+
+       foreach (unowned Value item in array) {
+               i++;
+       }
+
+       assert (i == 3);
+}
+
+void test_foreach_gvaluearray () {
+       Value value;
+       ValueArray array = new ValueArray (3);
+
+       value = 1;
+       array.append (value);
+       value = 2.0;
+       array.append (value);
+       value = "three";
+       array.append (value);
+
+       test_owned (array);
+       test_unowned (array);
+}
+
+void main () {
+       test_foreach_gvaluearray ();
+}
index 78836c13680a1536cabf5d1037453775ebfc2528..c073ab9089811ad3e59d4e81e224483a0022f6bf 100644 (file)
@@ -180,6 +180,8 @@ public class Vala.ForeachStatement : Block {
                        }
 
                        return check_without_iterator (analyzer, collection_type, collection_type.get_type_arguments ().get (0));
+               } else if (collection_type.compatible (analyzer.gvaluearray_type)) {
+                       return check_without_iterator (analyzer, collection_type, analyzer.gvalue_type);
                } else {
                        return check_with_iterator (analyzer, collection_type);
                }
index 38380f8a6bdaea44d4f03923aeb463cf2119572f..0b6febaa9f7779d8a3eafec8637b95593925062c 100644 (file)
@@ -56,9 +56,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType double_type;
        public DataType type_type;
        public Class object_type;
+       public StructValueType gvalue_type;
        public DataType glist_type;
        public DataType gslist_type;
        public DataType garray_type;
+       public DataType gvaluearray_type;
        public Class gerror_type;
 
        public int next_lambda_id = 0;
@@ -111,10 +113,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                        object_type = (Class) glib_ns.scope.lookup ("Object");
                        type_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Type"));
+                       gvalue_type = new StructValueType ((Struct) glib_ns.scope.lookup ("Value"));
 
                        glist_type = new ObjectType ((Class) glib_ns.scope.lookup ("List"));
                        gslist_type = new ObjectType ((Class) glib_ns.scope.lookup ("SList"));
                        garray_type = new ObjectType ((Class) glib_ns.scope.lookup ("Array"));
+                       gvaluearray_type = new ObjectType ((Class) glib_ns.scope.lookup ("ValueArray"));
 
                        gerror_type = (Class) glib_ns.scope.lookup ("Error");
                }