[vala/staging] vala: Add foreach statement support for GLib.Sequence
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] vala: Add foreach statement support for GLib.Sequence
- Date: Tue, 25 Jan 2022 11:26:03 +0000 (UTC)
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]