[vala/tintou/ptr-array-foreach: 338/338] vala: Add foreach statement support for GLib.GenericArray
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/tintou/ptr-array-foreach: 338/338] vala: Add foreach statement support for GLib.GenericArray
- Date: Mon, 3 May 2021 06:17:35 +0000 (UTC)
commit d7c75c0053b2d8de40bf7a6aae80ae66218df3c3
Author: Corentin Noël <corentin noel collabora com>
Date: Thu Oct 15 10:35:25 2020 +0200
vala: Add foreach statement support for GLib.GenericArray
It is now possible to use foreach with a GLib.GenericArray type
codegen/valaccodebasemodule.vala | 6 +--
codegen/valaccodecontrolflowmodule.vala | 29 +++++++++++++
tests/Makefile.am | 1 +
tests/basic-types/gptrarray.vala | 48 ++++++++++++++++++++++
tests/control-flow/foreach.vala | 36 ++++++++++++++++
tests/control-flow/gptrarray-foreach-variable.test | 7 ++++
vala/valaforeachstatement.vala | 3 +-
vala/valasemanticanalyzer.vala | 2 +
8 files changed, 128 insertions(+), 4 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 34963707d..4f1d8051d 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -337,7 +337,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
public TypeSymbol gstringbuilder_type;
public TypeSymbol garray_type;
public TypeSymbol gbytearray_type;
- public TypeSymbol gptrarray_type;
+ public TypeSymbol genericarray_type;
public TypeSymbol gthreadpool_type;
public DataType gquark_type;
public Struct gvalue_type;
@@ -510,7 +510,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
gstringbuilder_type = (TypeSymbol) glib_ns.scope.lookup ("StringBuilder");
garray_type = (TypeSymbol) glib_ns.scope.lookup ("Array");
gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
- gptrarray_type = (TypeSymbol) glib_ns.scope.lookup ("PtrArray");
+ genericarray_type = (TypeSymbol) glib_ns.scope.lookup ("GenericArray");
gthreadpool_type = (TypeSymbol) glib_ns.scope.lookup ("ThreadPool");
gerror = (Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Error");
@@ -3793,7 +3793,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
(type.type_symbol.is_subtype_of (gstringbuilder_type)
|| type.type_symbol.is_subtype_of (garray_type)
|| type.type_symbol.is_subtype_of (gbytearray_type)
- || type.type_symbol.is_subtype_of (gptrarray_type))) {
+ || type.type_symbol.is_subtype_of (genericarray_type))) {
ccall.add_argument (new CCodeConstant ("TRUE"));
} else if (context.profile == Profile.GOBJECT
&& type.type_symbol == gthreadpool_type) {
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index 5cca19707..bbc530247 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -308,6 +308,35 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
stmt.body.emit (this);
+ ccode.close ();
+ } else if (stmt.collection.value_type.compatible (new ObjectType ((Class)
genericarray_type))) {
+ // iterating over a GenericArray / GPtrArray
+
+ 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_ptr_array_index"));
+ get_item.add_argument (get_variable_cexpression (get_local_cname
(collection_backup)));
+ get_item.add_argument (get_variable_cexpression (arr_index));
+
+ CCodeExpression element_expr = get_item;
+
+ if (stmt.type_reference.value_owned) {
+ element_expr = get_cvalue_ (copy_value (new GLibValue (stmt.type_reference,
element_expr), stmt.element_variable));
+ }
+
+ 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
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 64e7101cf..281531d22 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -257,6 +257,7 @@ TESTS = \
control-flow/for.vala \
control-flow/for-switch-continue.vala \
control-flow/foreach.vala \
+ control-flow/gptrarray-foreach-variable.test \
control-flow/local-clash-with-implicit-this.vala \
control-flow/missing-break.test \
control-flow/missing-return.test \
diff --git a/tests/basic-types/gptrarray.vala b/tests/basic-types/gptrarray.vala
index 6d8aa2d1a..1b5d6c622 100644
--- a/tests/basic-types/gptrarray.vala
+++ b/tests/basic-types/gptrarray.vala
@@ -26,6 +26,30 @@ void main () {
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 (foo2 == array.get (1));
array.set (1, foo4);
assert (foo4 == array.get (1));
@@ -73,6 +97,30 @@ void main () {
assert (foo3.ref_count == 1);
assert (array.length == 3);
+ int loop_size = 0;
+ foreach (weak Foo element in array) {
+ loop_size++;
+ assert (element.ref_count == 1);
+ 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 == 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);
+
assert (foo2 == array.get (1));
array.set (1, foo4);
assert (foo4 == array.get (1));
diff --git a/tests/control-flow/foreach.vala b/tests/control-flow/foreach.vala
index 6a36453fd..052e03d3c 100644
--- a/tests/control-flow/foreach.vala
+++ b/tests/control-flow/foreach.vala
@@ -33,6 +33,41 @@ void test_foreach_gvaluearray () {
test_unowned (array);
}
+void test_generic_array_owned (GenericArray<Value?> array) {
+ uint i = 0;
+
+ foreach (Value? item in array) {
+ i++;
+ }
+
+ assert (i == 3);
+}
+
+void test_generic_array_unowned (GenericArray<Value?> array) {
+ uint i = 0;
+
+ foreach (unowned Value? item in array) {
+ i++;
+ }
+
+ assert (i == 3);
+}
+
+void test_foreach_genericarray () {
+ Value value;
+ var array = new GenericArray<Value?> ();
+
+ value = 1;
+ array.add (value);
+ value = 2.0;
+ array.add (value);
+ value = "three";
+ array.add (value);
+
+ test_generic_array_owned (array);
+ test_generic_array_unowned (array);
+}
+
void test_foreach_multidim_array () {
int[,] foo = { { 1, 2 }, { 3, 4 }, { 5, 6 } };
string result = "";
@@ -70,6 +105,7 @@ void test_foreach_slice_array () {
void main () {
test_foreach_gvaluearray ();
+ test_foreach_genericarray ();
test_foreach_const_array ();
test_foreach_multidim_array ();
test_foreach_slice_array ();
diff --git a/tests/control-flow/gptrarray-foreach-variable.test
b/tests/control-flow/gptrarray-foreach-variable.test
new file mode 100644
index 000000000..3cef84805
--- /dev/null
+++ b/tests/control-flow/gptrarray-foreach-variable.test
@@ -0,0 +1,7 @@
+Invalid Code
+
+void main () {
+ var array = new GenericArray<string> ();
+ foreach (int element in array) {
+ }
+}
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 0af0b52ba..d18de773e 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -180,7 +180,8 @@ public class Vala.ForeachStatement : Block {
array_type.inline_allocated = false;
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))) {
+ } 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))) {
if (collection_type.get_type_arguments ().size != 1) {
error = true;
Report.error (collection.source_reference, "missing type argument for
collection");
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index 378c301bd..fa101b6c8 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -163,6 +163,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
public DataType gslist_type;
public DataType garray_type;
public DataType gvaluearray_type;
+ public DataType genericarray_type;
public Class gerror_type;
public DataType list_type;
public DataType tuple_type;
@@ -228,6 +229,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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"));
+ genericarray_type = new ObjectType ((Class) glib_ns.scope.lookup ("GenericArray"));
gerror_type = (Class) glib_ns.scope.lookup ("Error");
regex_type = new ObjectType ((Class) root_symbol.scope.lookup ("GLib").scope.lookup
("Regex"));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]