[vala/tintou/ptr-array-foreach] vala: Add foreach statement support for GPtrArray




commit b6860a07eba7b79e70345ebfb6b86c316a2856d4
Author: Corentin Noël <corentin noel collabora com>
Date:   Thu Oct 15 10:35:25 2020 +0200

    vala: Add foreach statement support for GPtrArray
    
    It is now possible to use foreach with a GLib.PtrArray or GLib.GenericArray type

 codegen/valaccodebasemodule.vala        |  5 ++++-
 codegen/valaccodecontrolflowmodule.vala | 32 ++++++++++++++++++++++++++++++++
 tests/basic-types/gptrarray.vala        |  7 +++++++
 vala/valaforeachstatement.vala          |  2 +-
 vala/valasemanticanalyzer.vala          |  4 ++++
 5 files changed, 48 insertions(+), 2 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index b11992e17..09fca17b7 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -337,6 +337,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
        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;
@@ -502,6 +503,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        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");
@@ -3760,7 +3762,8 @@ 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 (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 df31fcef3..15eadcc58 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -308,6 +308,34 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                        stmt.body.emit (this);
 
+                       ccode.close ();
+               } else if (stmt.collection.value_type.compatible (new ObjectType ((Class) gptrarray_type)) || 
stmt.collection.value_type.compatible (new ObjectType ((Class) genericarray_type))) {
+                       // iterating over a 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), 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 ();
                } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
                        // iterating over a GValueArray
@@ -338,6 +366,10 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
                        stmt.body.emit (this);
 
                        ccode.close ();
+               } else {
+                       Report.error (stmt.source_reference, "internal error: unhandled collection type");
+                       stmt.error = true;
+                       return;
                }
 
                foreach (LocalVariable local in stmt.get_local_variables ()) {
diff --git a/tests/basic-types/gptrarray.vala b/tests/basic-types/gptrarray.vala
index 6d8aa2d1a..95737cd38 100644
--- a/tests/basic-types/gptrarray.vala
+++ b/tests/basic-types/gptrarray.vala
@@ -73,6 +73,13 @@ 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 == foo1 || element == foo2 || element == foo3);
+               }
+               assert (loop_size == 3);
+
                assert (foo2 == array.get (1));
                array.set (1, foo4);
                assert (foo4 == array.get (1));
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 383814085..b3703b876 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -176,7 +176,7 @@ 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.gptrarray_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 8242efd35..711d0c1b4 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -163,6 +163,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType gslist_type;
        public DataType garray_type;
        public DataType gvaluearray_type;
+       public DataType gptrarray_type;
+       public DataType genericarray_type;
        public Class gerror_type;
        public DataType list_type;
        public DataType tuple_type;
@@ -228,6 +230,8 @@ 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"));
+                       gptrarray_type = new ObjectType ((Class) glib_ns.scope.lookup ("PtrArray"));
+                       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]