[vala/staging] vala: Add foreach statement support for GLib.Sequence



commit 44195a02c9d26453dc698282deb4947425a4b0b1
Author: Princeton Ferro <princetonferro gmail com>
Date:   Mon Jan 24 22:32:01 2022 -0500

    vala: Add foreach statement support for GLib.Sequence
    
    It is now possible to use foreach with a GLib.Sequence

 codegen/valaccodebasemodule.vala                   |   4 +
 codegen/valaccodecontrolflowmodule.vala            |  32 ++++++
 tests/Makefile.am                                  |   1 +
 tests/control-flow/foreach.c-expected              | 107 +++++++++++++++++++++
 tests/control-flow/foreach.vala                    |  36 +++++++
 tests/control-flow/gsequence-foreach-variable.test |   7 ++
 vala/valaforeachstatement.vala                     |   3 +-
 vala/valasemanticanalyzer.vala                     |   2 +
 8 files changed, 191 insertions(+), 1 deletion(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index ccb2fe988..cf0d94682 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -338,6 +338,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
        public Class garray_type;
        public TypeSymbol gbytearray_type;
        public TypeSymbol genericarray_type;
+       public Class gsequence_type;
+       public Class gsequence_iter_type;
        public TypeSymbol gthreadpool_type;
        public DataType gquark_type;
        public Struct gvalue_type;
@@ -512,6 +514,8 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                        garray_type = (Class) glib_ns.scope.lookup ("Array");
                        gbytearray_type = (TypeSymbol) glib_ns.scope.lookup ("ByteArray");
                        genericarray_type = (TypeSymbol) glib_ns.scope.lookup ("GenericArray");
+                       gsequence_type = (Class) glib_ns.scope.lookup ("Sequence");
+                       gsequence_iter_type = (Class) glib_ns.scope.lookup ("SequenceIter");
                        gthreadpool_type = (TypeSymbol) glib_ns.scope.lookup ("ThreadPool");
 
                        gerror = (Class) root_symbol.scope.lookup ("GLib").scope.lookup ("Error");
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index dc278e475..ce57da62f 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -400,6 +400,38 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                        stmt.body.emit (this);
 
+                       ccode.close ();
+               } else if (stmt.collection.value_type.compatible (new ObjectType (gsequence_type))) {
+                       // iterating over a GSequence
+
+                       var iterator_variable = new LocalVariable (new ObjectType (gsequence_iter_type), 
"%s_iter".printf (stmt.variable_name));
+                       visit_local_variable (iterator_variable);
+                       var sequence_iter = get_variable_cname (get_local_cname (iterator_variable));
+
+                       var ccond_is_end = new CCodeFunctionCall (new CCodeIdentifier 
("g_sequence_iter_is_end"));
+                       ccond_is_end.add_argument (get_variable_cexpression (sequence_iter));
+                       var ccond = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, 
ccond_is_end);
+                       var cbegin = new CCodeFunctionCall (new CCodeIdentifier 
("g_sequence_get_begin_iter"));
+                       cbegin.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
+                       var cnext = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_iter_next"));
+                       cnext.add_argument (get_variable_cexpression (sequence_iter));
+
+                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (sequence_iter), 
cbegin),
+                                       ccond,
+                                       new CCodeAssignment (get_variable_cexpression (sequence_iter), 
cnext));
+
+                       var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_get"));
+                       get_item.add_argument (get_variable_cexpression (sequence_iter));
+
+                       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 {
                        Report.error (stmt.source_reference, "internal error: unsupported collection type");
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b56263e8f..2103afa6e 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -279,6 +279,7 @@ TESTS = \
        control-flow/foreach.vala \
        control-flow/garray-foreach-variable.test \
        control-flow/gptrarray-foreach-variable.test \
+       control-flow/gsequence-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/control-flow/foreach.c-expected b/tests/control-flow/foreach.c-expected
index c7d2e6da1..23225a443 100644
--- a/tests/control-flow/foreach.c-expected
+++ b/tests/control-flow/foreach.c-expected
@@ -19,6 +19,7 @@
 #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_sequence_free0(var) ((var == NULL) ? NULL : (var = (g_sequence_free (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);
@@ -35,6 +36,9 @@ static void _vala_GValue_free (GValue* self);
 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_gsequence_owned (GSequence* sequence);
+VALA_EXTERN void test_gsequence_unowned (GSequence* sequence);
+VALA_EXTERN void test_foreach_gsequence (void);
 VALA_EXTERN void test_garray_owned (GArray* array);
 VALA_EXTERN void test_garray_unowned (GArray* array);
 VALA_EXTERN void test_foreach_garray (void);
@@ -264,6 +268,108 @@ test_foreach_genericarray (void)
        G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
 }
 
+void
+test_gsequence_owned (GSequence* sequence)
+{
+       guint i = 0U;
+       g_return_if_fail (sequence != NULL);
+       i = (guint) 0;
+       {
+               GSequence* item_collection = NULL;
+               GSequenceIter* item_iter = NULL;
+               item_collection = sequence;
+               for (item_iter = g_sequence_get_begin_iter (item_collection); !g_sequence_iter_is_end 
(item_iter); item_iter = g_sequence_iter_next (item_iter)) {
+                       GValue* _tmp0_;
+                       GValue* item = NULL;
+                       _tmp0_ = __g_value_dup0 (g_sequence_get (item_iter));
+                       item = _tmp0_;
+                       {
+                               guint _tmp1_;
+                               _tmp1_ = i;
+                               i = _tmp1_ + 1;
+                               __vala_GValue_free0 (item);
+                       }
+               }
+       }
+       _vala_assert (i == ((guint) 3), "i == 3");
+}
+
+void
+test_gsequence_unowned (GSequence* sequence)
+{
+       guint i = 0U;
+       g_return_if_fail (sequence != NULL);
+       i = (guint) 0;
+       {
+               GSequence* item_collection = NULL;
+               GSequenceIter* item_iter = NULL;
+               item_collection = sequence;
+               for (item_iter = g_sequence_get_begin_iter (item_collection); !g_sequence_iter_is_end 
(item_iter); item_iter = g_sequence_iter_next (item_iter)) {
+                       GValue* item = NULL;
+                       item = g_sequence_get (item_iter);
+                       {
+                               guint _tmp0_;
+                               _tmp0_ = i;
+                               i = _tmp0_ + 1;
+                       }
+               }
+       }
+       _vala_assert (i == ((guint) 3), "i == 3");
+}
+
+void
+test_foreach_gsequence (void)
+{
+       GValue value = {0};
+       GSequence* sequence = NULL;
+       GSequence* _tmp0_;
+       GValue _tmp1_ = {0};
+       GValue _tmp2_;
+       GValue _tmp3_;
+       GValue* _tmp4_;
+       GSequenceIter* _tmp5_;
+       GValue _tmp6_ = {0};
+       GValue _tmp7_;
+       GValue _tmp8_;
+       GValue* _tmp9_;
+       GSequenceIter* _tmp10_;
+       GValue _tmp11_ = {0};
+       GValue _tmp12_;
+       GValue _tmp13_;
+       GValue* _tmp14_;
+       GSequenceIter* _tmp15_;
+       _tmp0_ = g_sequence_new (__vala_GValue_free0_);
+       sequence = _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_);
+       _tmp5_ = g_sequence_append (sequence, _tmp4_);
+       g_value_init (&_tmp6_, G_TYPE_DOUBLE);
+       g_value_set_double (&_tmp6_, 2.0);
+       G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+       value = _tmp6_;
+       _tmp7_ = value;
+       _tmp8_ = _tmp7_;
+       _tmp9_ = __g_value_dup0 (&_tmp8_);
+       _tmp10_ = g_sequence_append (sequence, _tmp9_);
+       g_value_init (&_tmp11_, G_TYPE_STRING);
+       g_value_set_string (&_tmp11_, "three");
+       G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+       value = _tmp11_;
+       _tmp12_ = value;
+       _tmp13_ = _tmp12_;
+       _tmp14_ = __g_value_dup0 (&_tmp13_);
+       _tmp15_ = g_sequence_append (sequence, _tmp14_);
+       test_gsequence_owned (sequence);
+       test_gsequence_unowned (sequence);
+       _g_sequence_free0 (sequence);
+       G_IS_VALUE (&value) ? (g_value_unset (&value), NULL) : NULL;
+}
+
 void
 test_garray_owned (GArray* array)
 {
@@ -569,6 +675,7 @@ _vala_main (void)
        test_foreach_gvaluearray ();
        test_foreach_garray ();
        test_foreach_genericarray ();
+       test_foreach_gsequence ();
        test_foreach_const_array ();
        test_foreach_multidim_array ();
        test_foreach_slice_array ();
diff --git a/tests/control-flow/foreach.vala b/tests/control-flow/foreach.vala
index a0a01a865..8689a18ad 100644
--- a/tests/control-flow/foreach.vala
+++ b/tests/control-flow/foreach.vala
@@ -68,6 +68,41 @@ void test_foreach_genericarray () {
        test_generic_array_unowned (array);
 }
 
+void test_gsequence_owned (Sequence<Value?> sequence) {
+       uint i = 0;
+
+       foreach (Value? item in sequence) {
+               i++;
+       }
+
+       assert (i == 3);
+}
+
+void test_gsequence_unowned (Sequence<Value?> sequence) {
+       uint i = 0;
+
+       foreach (unowned Value? item in sequence) {
+               i++;
+       }
+
+       assert (i == 3);
+}
+
+void test_foreach_gsequence () {
+       Value value;
+       var sequence = new Sequence<Value?> ();
+
+       value = 1;
+       sequence.append (value);
+       value = 2.0;
+       sequence.append (value);
+       value = "three";
+       sequence.append (value);
+
+       test_gsequence_owned (sequence);
+       test_gsequence_unowned (sequence);
+}
+
 void test_garray_owned (Array<Value?> array) {
        uint i = 0;
 
@@ -142,6 +177,7 @@ void main () {
        test_foreach_gvaluearray ();
        test_foreach_garray ();
        test_foreach_genericarray ();
+       test_foreach_gsequence ();
        test_foreach_const_array ();
        test_foreach_multidim_array ();
        test_foreach_slice_array ();
diff --git a/tests/control-flow/gsequence-foreach-variable.test 
b/tests/control-flow/gsequence-foreach-variable.test
new file mode 100644
index 000000000..305c40a61
--- /dev/null
+++ b/tests/control-flow/gsequence-foreach-variable.test
@@ -0,0 +1,7 @@
+Invalid Code
+
+void main () {
+       var sequence = new Sequence<string> ();
+       foreach (int element in sequence) {
+       }
+}
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index 4daddcb84..f491c037f 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -183,7 +183,8 @@ public class Vala.ForeachStatement : Block {
                } 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.garray_type))) {
+                   || collection_type.compatible (context.analyzer.garray_type)
+                   || collection_type.compatible (context.analyzer.gsequence_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 b49a8299d..80e54d9c1 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -164,6 +164,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType garray_type;
        public DataType gvaluearray_type;
        public DataType genericarray_type;
+       public DataType gsequence_type;
        public Class gerror_type;
        public DataType list_type;
        public DataType tuple_type;
@@ -230,6 +231,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        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"));
+                       gsequence_type = new ObjectType ((Class) glib_ns.scope.lookup ("Sequence"));
 
                        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]