[vala] Add support for iterating over GValueArrays via foreach



commit 3e2f5122592151a81079ccc7e410864c99edfecc
Author: Mark Lee <marklee src gnome org>
Date:   Wed Jul 15 23:33:39 2009 -0700

    Add support for iterating over GValueArrays via foreach
    
    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        |    2 +
 codegen/valaccodecontrolflowmodule.vala |   54 +++++++++++++++++++++++++++++++
 tests/Makefile.am                       |    1 +
 tests/control-flow/foreach.test         |   42 ++++++++++++++++++++++++
 vala/valaforeachstatement.vala          |    2 +
 vala/valasemanticanalyzer.vala          |    4 ++
 6 files changed, 105 insertions(+), 0 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 2ac63ba..3b51d42 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -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");
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index 86a98e3..19a30a0 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -402,6 +402,60 @@ internal class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
 			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);
 		}
 
 		foreach (LocalVariable local in stmt.get_local_variables ()) {
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c5599ab..ad9bae5 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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
index 0000000..de8d128
--- /dev/null
+++ b/tests/control-flow/foreach.test
@@ -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 ();
+}
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 78836c1..c073ab9 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -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);
 		}
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 38380f8..0b6feba 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -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");
 		}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]