public override void visit_foreach_statement(ForeachStatement stmt) { ccode.open_block(); var collection_backup = stmt.collection_variable; var collection_type = collection_backup.variable_type; var array_type = collection_type as ArrayType; if (array_type != null) { // avoid assignment issues array_type.inline_allocated = false; array_type.fixed_length = false; } visit_local_variable(collection_backup); ccode.add_assignment(get_variable_cexpression(get_local_cname(collection_backup)), get_cvalue(stmt.collection)); if (stmt.tree_can_fail && stmt.collection.tree_can_fail) { // exception handling add_simple_check(stmt.collection); } if (stmt.collection.value_type is ArrayType) { array_type = (ArrayType)stmt.collection.value_type; var array_len = get_array_length_cexpression(stmt.collection); // store array length for use by _vala_array_free ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(collection_backup), 1)), array_len); var iterator_variable = new LocalVariable(int_type.copy(), stmt.variable_name + "_it"); visit_local_variable(iterator_variable); var it_name = get_local_cname(iterator_variable); var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(it_name), array_len); ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), new CCodeConstant("0")), ccond, new CCodeAssignment(get_variable_cexpression(it_name), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(it_name), new CCodeConstant("1")))); CCodeExpression element_expr = new CCodeElementAccess(get_variable_cexpression(get_local_cname(collection_backup)), get_variable_cexpression(it_name)); var element_type = array_type.element_type.copy(); element_type.value_owned = false; element_expr = get_cvalue_(transform_value(new GLibValue(element_type, element_expr, true), stmt.type_reference, stmt)); visit_local_variable(stmt.element_variable); ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr); // set array length for stacked arrays if (stmt.type_reference is ArrayType) { var inner_array_type = (ArrayType)stmt.type_reference; for (int dim = 1; dim <= inner_array_type.rank; dim++) { ccode.add_assignment(get_variable_cexpression(get_array_length_cname(get_local_cname(stmt.element_variable), dim)), new CCodeConstant("-1")); } } stmt.body.emit(this); ccode.close(); } else if (stmt.collection.value_type.compatible(new ObjectType(glist_type)) || stmt.collection.value_type.compatible(new ObjectType(gslist_type))) { // iterating over a GList or GSList var iterator_variable = new LocalVariable(collection_type.copy(), stmt.variable_name + "_it"); visit_local_variable(iterator_variable); var it_name = get_local_cname(iterator_variable); var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, get_variable_cexpression(it_name), new CCodeConstant("NULL")); ccode.open_for(new CCodeAssignment(get_variable_cexpression(it_name), get_variable_cexpression(get_local_cname(collection_backup))), ccond, new CCodeAssignment(get_variable_cexpression(it_name), CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "next"))); CCodeExpression element_expr = CCodeMemberAccess.pointer(get_variable_cexpression(it_name), "data"); if (collection_type.get_type_arguments().Count != 1) { Report.error(stmt.source_reference, "internal error: missing generic type argument"); stmt.error = true; return; } var element_data_type = collection_type.get_type_arguments()[0].copy(); element_data_type.value_owned = false; element_expr = convert_from_generic_pointer(element_expr, element_data_type); element_expr = get_cvalue_(transform_value(new GLibValue(element_data_type, element_expr), stmt.type_reference, stmt)); visit_local_variable(stmt.element_variable); ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr); stmt.body.emit(this); ccode.close(); } else if (stmt.collection.value_type.compatible(new ObjectType(gvaluearray_type))) { // iterating over a GValueArray var iterator_variable = new LocalVariable(uint_type.copy(), "%s_index".printf(stmt.variable_name)); visit_local_variable(iterator_variable); var arr_index = get_variable_cname(get_local_cname(iterator_variable)); var ccond = new CCodeBinaryExpression(CCodeBinaryOperator.LESS_THAN, get_variable_cexpression(arr_index), CCodeMemberAccess.pointer(get_variable_cexpression(get_local_cname(collection_backup)), "n_values")); ccode.open_for(new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeConstant("0")), ccond, new CCodeAssignment(get_variable_cexpression(arr_index), new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, get_variable_cexpression(arr_index), new CCodeConstant("1")))); var get_item = new CCodeFunctionCall(new CCodeIdentifier("g_value_array_get_nth")); get_item.add_argument(get_variable_cexpression(get_local_cname(collection_backup))); 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_cvalue_(copy_value(new GLibValue(stmt.type_reference, element_expr), new StructValueType(gvalue_type))); } visit_local_variable(stmt.element_variable); ccode.add_assignment(get_variable_cexpression(get_local_cname(stmt.element_variable)), element_expr); stmt.body.emit(this); ccode.close(); } foreach (LocalVariable local in stmt.get_local_variables()) { if (requires_destroy(local.variable_type)) { ccode.add_expression(destroy_local(local)); } } ccode.close(); }