public Class gqueue_type;
public Class gvaluearray_type;
public TypeSymbol gstringbuilder_type;
- public TypeSymbol garray_type;
+ public Class garray_type;
public TypeSymbol gbytearray_type;
public TypeSymbol genericarray_type;
public TypeSymbol gthreadpool_type;
gqueue_type = (Class) glib_ns.scope.lookup ("Queue");
gvaluearray_type = (Class) glib_ns.scope.lookup ("ValueArray");
gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
- garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
+ garray_type = (Class) glib_ns.scope.lookup ("Array");
gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
genericarray_type = (TypeSymbol) glib_ns.scope.lookup ("GenericArray");
gthreadpool_type = (TypeSymbol) glib_ns.scope.lookup ("ThreadPool");
stmt.body.emit (this);
+ ccode.close ();
+ } else if (stmt.collection.value_type.compatible (new ObjectType (garray_type))) {
+ // iterating over a GArray
+
+ 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), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "len"));
+
+ 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_array_index"));
+ get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
+ get_item.add_argument (new CCodeIdentifier (get_ccode_name (stmt.type_reference)));
+ get_item.add_argument (get_variable_cexpression (arr_index));
+
+ if (collection_type.get_type_arguments ().size != 1) {
+ Report.error (stmt.source_reference, "internal error: missing generic type argument");
+ stmt.error = true;
+ return;
+ }
+
+ var element_type = collection_type.get_type_arguments ().get (0).copy ();
+ element_type.value_owned = false;
+ var element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, get_item, 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);
+
+ 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
control-flow/for.vala \
control-flow/for-switch-continue.vala \
control-flow/foreach.vala \
+ control-flow/garray-foreach-variable.test \
control-flow/gptrarray-foreach-variable.test \
control-flow/local-clash-with-implicit-this.vala \
control-flow/missing-break.test \
VALA_EXTERN void test_garray (void);
static void _g_object_unref0_ (gpointer var);
static void _vala_Foo_free_function_content_of (gpointer data);
+VALA_EXTERN void test_garray_foreach (void);
VALA_EXTERN void test_int_garray (void);
VALA_EXTERN GArray* create_struct_garray (void);
static void _foo_struct_free0_ (gpointer var);
_g_array_unref0 (array);
}
+void
+test_garray_foreach (void)
+{
+ GArray* array = NULL;
+ GArray* _tmp0_;
+ Foo* foo1 = NULL;
+ Foo* _tmp1_;
+ Foo* foo2 = NULL;
+ Foo* _tmp2_;
+ Foo* foo3 = NULL;
+ Foo* _tmp3_;
+ GArray* _tmp4_;
+ Foo* _tmp5_;
+ Foo* _tmp6_;
+ Foo* _tmp7_;
+ GArray* _tmp8_;
+ Foo* _tmp9_;
+ Foo* _tmp10_;
+ Foo* _tmp11_;
+ GArray* _tmp12_;
+ Foo* _tmp13_;
+ Foo* _tmp14_;
+ Foo* _tmp15_;
+ GArray* _tmp16_;
+ gint loop_size = 0;
+ GArray* _tmp17_;
+ GArray* _tmp26_;
+ Foo* _tmp36_;
+ Foo* _tmp37_;
+ Foo* _tmp38_;
+ _tmp0_ = g_array_new (TRUE, TRUE, sizeof (Foo*));
+ g_array_set_clear_func (_tmp0_, (GDestroyNotify) _vala_Foo_free_function_content_of);
+ array = _tmp0_;
+ _tmp1_ = foo_new ();
+ foo1 = _tmp1_;
+ _tmp2_ = foo_new ();
+ foo2 = _tmp2_;
+ _tmp3_ = foo_new ();
+ foo3 = _tmp3_;
+ _tmp4_ = array;
+ _tmp5_ = foo1;
+ _tmp6_ = _g_object_ref0 (_tmp5_);
+ g_array_append_val (_tmp4_, _tmp6_);
+ _tmp7_ = foo1;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp7_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo1.ref_count == 2");
+ _tmp8_ = array;
+ _tmp9_ = foo2;
+ _tmp10_ = _g_object_ref0 (_tmp9_);
+ g_array_append_val (_tmp8_, _tmp10_);
+ _tmp11_ = foo2;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp11_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo2.ref_count == 2");
+ _tmp12_ = array;
+ _tmp13_ = foo3;
+ _tmp14_ = _g_object_ref0 (_tmp13_);
+ g_array_append_val (_tmp12_, _tmp14_);
+ _tmp15_ = foo3;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp15_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo3.ref_count == 2");
+ _tmp16_ = array;
+ _vala_assert (_tmp16_->len == ((guint) 3), "array.length == 3");
+ loop_size = 0;
+ _tmp17_ = array;
+ {
+ GArray* element_collection = NULL;
+ guint element_index = 0U;
+ element_collection = _tmp17_;
+ for (element_index = 0; element_index < element_collection->len; element_index = element_index + 1) {
+ Foo* element = NULL;
+ element = g_array_index (element_collection, Foo*, element_index);
+ {
+ gint _tmp18_;
+ Foo* _tmp19_;
+ _tmp18_ = loop_size;
+ loop_size = _tmp18_ + 1;
+ _tmp19_ = element;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp19_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "element.ref_count == 2");
+ switch (loop_size) {
+ case 1:
+ {
+ Foo* _tmp20_;
+ Foo* _tmp21_;
+ _tmp20_ = element;
+ _tmp21_ = foo1;
+ _vala_assert (_tmp20_ == _tmp21_, "element == foo1");
+ break;
+ }
+ case 2:
+ {
+ Foo* _tmp22_;
+ Foo* _tmp23_;
+ _tmp22_ = element;
+ _tmp23_ = foo2;
+ _vala_assert (_tmp22_ == _tmp23_, "element == foo2");
+ break;
+ }
+ case 3:
+ {
+ Foo* _tmp24_;
+ Foo* _tmp25_;
+ _tmp24_ = element;
+ _tmp25_ = foo3;
+ _vala_assert (_tmp24_ == _tmp25_, "element == foo3");
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ }
+ _vala_assert (loop_size == 3, "loop_size == 3");
+ loop_size = 0;
+ _tmp26_ = array;
+ {
+ GArray* element_collection = NULL;
+ guint element_index = 0U;
+ element_collection = _tmp26_;
+ for (element_index = 0; element_index < element_collection->len; element_index = element_index + 1) {
+ Foo* _tmp27_;
+ Foo* element = NULL;
+ _tmp27_ = _g_object_ref0 (g_array_index (element_collection, Foo*, element_index));
+ element = _tmp27_;
+ {
+ gint _tmp28_;
+ Foo* _tmp29_;
+ _tmp28_ = loop_size;
+ loop_size = _tmp28_ + 1;
+ _tmp29_ = element;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp29_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 3), "element.ref_count == 3");
+ switch (loop_size) {
+ case 1:
+ {
+ Foo* _tmp30_;
+ Foo* _tmp31_;
+ _tmp30_ = element;
+ _tmp31_ = foo1;
+ _vala_assert (_tmp30_ == _tmp31_, "element == foo1");
+ break;
+ }
+ case 2:
+ {
+ Foo* _tmp32_;
+ Foo* _tmp33_;
+ _tmp32_ = element;
+ _tmp33_ = foo2;
+ _vala_assert (_tmp32_ == _tmp33_, "element == foo2");
+ break;
+ }
+ case 3:
+ {
+ Foo* _tmp34_;
+ Foo* _tmp35_;
+ _tmp34_ = element;
+ _tmp35_ = foo3;
+ _vala_assert (_tmp34_ == _tmp35_, "element == foo3");
+ break;
+ }
+ default:
+ break;
+ }
+ _g_object_unref0 (element);
+ }
+ }
+ }
+ _vala_assert (loop_size == 3, "loop_size == 3");
+ _tmp36_ = foo1;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp36_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo1.ref_count == 2");
+ _tmp37_ = foo2;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp37_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo2.ref_count == 2");
+ _tmp38_ = foo3;
+ _vala_assert (G_TYPE_CHECK_INSTANCE_CAST (_tmp38_, G_TYPE_OBJECT, GObject)->ref_count == ((guint) 2), "foo3.ref_count == 2");
+ _g_object_unref0 (foo3);
+ _g_object_unref0 (foo2);
+ _g_object_unref0 (foo1);
+ _g_array_unref0 (array);
+}
+
void
test_int_garray (void)
{
_vala_main (void)
{
test_garray ();
+ test_garray_foreach ();
test_int_garray ();
test_struct_garray ();
test_object_garray ();
assert (foo.ref_count == 1);
}
+void test_garray_foreach () {
+ var array = new GLib.Array<Foo> ();
+
+ var foo1 = new Foo ();
+ var foo2 = new Foo ();
+ var foo3 = new Foo ();
+
+ array.append_val (foo1);
+ assert (foo1.ref_count == 2);
+ array.append_val (foo2);
+ assert (foo2.ref_count == 2);
+ array.append_val (foo3);
+ assert (foo3.ref_count == 2);
+ assert (array.length == 3);
+
+ int loop_size = 0;
+ foreach (weak Foo element in array) {
+ loop_size++;
+ assert (element.ref_count == 2);
+ switch (loop_size) {
+ case 1: assert (element == foo1); break;
+ case 2: assert (element == foo2); break;
+ case 3: assert (element == foo3); break;
+ }
+ }
+ assert (loop_size == 3);
+
+ loop_size = 0;
+ foreach (Foo element in array) {
+ loop_size++;
+ assert (element.ref_count == 3);
+ switch (loop_size) {
+ case 1: assert (element == foo1); break;
+ case 2: assert (element == foo2); break;
+ case 3: assert (element == foo3); break;
+ }
+ }
+ assert (loop_size == 3);
+ assert (foo1.ref_count == 2);
+ assert (foo2.ref_count == 2);
+ assert (foo3.ref_count == 2);
+}
+
void test_int_garray () {
var array = new GLib.Array<int> ();
// g_array_append_val() is a macro which uses a reference to the value parameter and thus can't use constants.
void main () {
test_garray ();
+ test_garray_foreach ();
test_int_garray ();
test_struct_garray ();
test_object_garray ();
#define _g_value_array_free0(var) ((var == NULL) ? NULL : (var = (g_value_array_free (var), NULL)))
#define __vala_GValue_free0(var) ((var == NULL) ? NULL : (var = (_vala_GValue_free (var), NULL)))
#define _g_ptr_array_unref0(var) ((var == NULL) ? NULL : (var = (g_ptr_array_unref (var), NULL)))
+#define _g_array_unref0(var) ((var == NULL) ? NULL : (var = (g_array_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
VALA_EXTERN void test_generic_array_unowned (GPtrArray* array);
VALA_EXTERN void test_foreach_genericarray (void);
static void __vala_GValue_free0_ (gpointer var);
+VALA_EXTERN void test_garray_owned (GArray* array);
+VALA_EXTERN void test_garray_unowned (GArray* array);
+VALA_EXTERN void test_foreach_garray (void);
+static void _vala_GValue_free_function_content_of (gpointer data);
VALA_EXTERN void test_foreach_multidim_array (void);
VALA_EXTERN void test_foreach_const_array (void);
VALA_EXTERN void test_foreach_slice_array (void);
G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
}
+void
+test_garray_owned (GArray* array)
+{
+ guint i = 0U;
+ g_return_if_fail (array != NULL);
+ i = (guint) 0;
+ {
+ GArray* item_collection = NULL;
+ guint item_index = 0U;
+ item_collection = array;
+ for (item_index = 0; item_index < item_collection->len; item_index = item_index + 1) {
+ GValue* _tmp0_;
+ GValue* item = NULL;
+ _tmp0_ = __g_value_dup0 (g_array_index (item_collection, GValue*, item_index));
+ item = _tmp0_;
+ {
+ guint _tmp1_;
+ _tmp1_ = i;
+ i = _tmp1_ + 1;
+ __vala_GValue_free0 (item);
+ }
+ }
+ }
+ _vala_assert (i == ((guint) 3), "i == 3");
+}
+
+void
+test_garray_unowned (GArray* array)
+{
+ guint i = 0U;
+ g_return_if_fail (array != NULL);
+ i = (guint) 0;
+ {
+ GArray* item_collection = NULL;
+ guint item_index = 0U;
+ item_collection = array;
+ for (item_index = 0; item_index < item_collection->len; item_index = item_index + 1) {
+ GValue* item = NULL;
+ item = g_array_index (item_collection, GValue*, item_index);
+ {
+ guint _tmp0_;
+ _tmp0_ = i;
+ i = _tmp0_ + 1;
+ }
+ }
+ }
+ _vala_assert (i == ((guint) 3), "i == 3");
+}
+
+static void
+_vala_GValue_free_function_content_of (gpointer data)
+{
+ GValue* self;
+ self = *((GValue**) data);
+ __vala_GValue_free0_ (self);
+}
+
+void
+test_foreach_garray (void)
+{
+ GValue value = {0};
+ GArray* array = NULL;
+ GArray* _tmp0_;
+ GValue _tmp1_ = {0};
+ GValue _tmp2_;
+ GValue _tmp3_;
+ GValue* _tmp4_;
+ GValue _tmp5_ = {0};
+ GValue _tmp6_;
+ GValue _tmp7_;
+ GValue* _tmp8_;
+ GValue _tmp9_ = {0};
+ GValue _tmp10_;
+ GValue _tmp11_;
+ GValue* _tmp12_;
+ _tmp0_ = g_array_new (TRUE, TRUE, sizeof (GValue*));
+ g_array_set_clear_func (_tmp0_, (GDestroyNotify) _vala_GValue_free_function_content_of);
+ array = _tmp0_;
+ g_value_init (&_tmp1_, G_TYPE_INT);
+ g_value_set_int (&_tmp1_, 1);
+ G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+ value = _tmp1_;
+ _tmp2_ = value;
+ _tmp3_ = _tmp2_;
+ _tmp4_ = __g_value_dup0 (&_tmp3_);
+ g_array_append_val (array, _tmp4_);
+ g_value_init (&_tmp5_, G_TYPE_DOUBLE);
+ g_value_set_double (&_tmp5_, 2.0);
+ G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+ value = _tmp5_;
+ _tmp6_ = value;
+ _tmp7_ = _tmp6_;
+ _tmp8_ = __g_value_dup0 (&_tmp7_);
+ g_array_append_val (array, _tmp8_);
+ g_value_init (&_tmp9_, G_TYPE_STRING);
+ g_value_set_string (&_tmp9_, "three");
+ G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+ value = _tmp9_;
+ _tmp10_ = value;
+ _tmp11_ = _tmp10_;
+ _tmp12_ = __g_value_dup0 (&_tmp11_);
+ g_array_append_val (array, _tmp12_);
+ test_garray_owned (array);
+ test_garray_unowned (array);
+ _g_array_unref0 (array);
+ G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+}
+
void
test_foreach_multidim_array (void)
{
_vala_main (void)
{
test_foreach_gvaluearray ();
+ test_foreach_garray ();
test_foreach_genericarray ();
test_foreach_const_array ();
test_foreach_multidim_array ();
test_generic_array_unowned (array);
}
+void test_garray_owned (Array<Value?> array) {
+ uint i = 0;
+
+ foreach (Value? item in array) {
+ i++;
+ }
+
+ assert (i == 3);
+}
+
+void test_garray_unowned (Array<Value?> array) {
+ uint i = 0;
+
+ foreach (unowned Value? item in array) {
+ i++;
+ }
+
+ assert (i == 3);
+}
+
+void test_foreach_garray () {
+ Value value;
+ var array = new Array<Value?> ();
+
+ value = 1;
+ array.append_val (value);
+ value = 2.0;
+ array.append_val (value);
+ value = "three";
+ array.append_val (value);
+
+ test_garray_owned (array);
+ test_garray_unowned (array);
+}
+
void test_foreach_multidim_array () {
int[,] foo = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
string result = "";
void main () {
test_foreach_gvaluearray ();
+ test_foreach_garray ();
test_foreach_genericarray ();
test_foreach_const_array ();
test_foreach_multidim_array ();
--- /dev/null
+Invalid Code
+
+void main () {
+ var array = new Array<string> ();
+ foreach (int element in array) {
+ }
+}
return check_without_iterator (context, collection_type, array_type.element_type);
} else if (context.profile == Profile.GOBJECT && (collection_type.compatible (context.analyzer.glist_type)
- || collection_type.compatible (context.analyzer.gslist_type) || collection_type.compatible (context.analyzer.genericarray_type))) {
+ || collection_type.compatible (context.analyzer.gslist_type)
+ || collection_type.compatible (context.analyzer.genericarray_type)
+ || collection_type.compatible (context.analyzer.garray_type))) {
if (collection_type.get_type_arguments ().size != 1) {
error = true;
Report.error (collection.source_reference, "missing type argument for collection");