add support for iteration over Gee.Iterable collections
authorJuerg Billeter <j@bitron.ch>
Tue, 24 Jul 2007 15:48:16 +0000 (15:48 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Tue, 24 Jul 2007 15:48:16 +0000 (15:48 +0000)
2007-07-24  Juerg Billeter  <j@bitron.ch>

* vala/valasemanticanalyzer.vala, gobject/valacodegenerator.vala:
  add support for iteration over Gee.Iterable collections

svn path=/trunk/; revision=383

ChangeLog
gobject/valacodegenerator.vala
vala/valasemanticanalyzer.vala

index 485c254..4e2ab7a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2007-07-24  Jürg Billeter  <j@bitron.ch>
 
+       * vala/valasemanticanalyzer.vala, gobject/valacodegenerator.vala:
+         add support for iteration over Gee.Iterable collections
+
+2007-07-24  Jürg Billeter  <j@bitron.ch>
+
        * vala/valamemorymanager.vala: skip memory manager for VAPI files
        * vala/valasemanticanalyzer.vala: remove unnecessary code in
          visit_creation_method
index 5e9cc2a..9cb28d5 100644 (file)
@@ -99,6 +99,8 @@ public class Vala.CodeGenerator : CodeVisitor {
        DataType slist_type;
        TypeReference mutex_type;
        DataType type_module_type;
+       DataType iterable_type;
+       DataType iterator_type;
 
        Method substring_method;
 
@@ -252,6 +254,12 @@ public class Vala.CodeGenerator : CodeVisitor {
                                }
                        }
                }
+
+               var gee_ns = root_symbol.scope.lookup ("Gee");
+               if (gee_ns != null) {
+                       iterable_type = (DataType) gee_ns.scope.lookup ("Iterable");
+                       iterator_type = (DataType) gee_ns.scope.lookup ("Iterator");
+               }
        
                /* we're only interested in non-pkg source files */
                var source_files = context.get_source_files ();
@@ -1381,6 +1389,53 @@ public class Vala.CodeGenerator : CodeVisitor {
 
                        cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
                        cblock.add_statement (cfor);
+               } else if (stmt.collection.static_type.data_type == iterable_type ||
+                          stmt.collection.static_type.data_type.is_subtype_of (iterable_type)) {
+                       var it_name = "%s_it".printf (stmt.variable_name);
+
+                       var citdecl = new CCodeDeclaration (iterator_type.get_cname () + "*");
+                       var it_method = (Method) iterable_type.scope.lookup ("iterator");
+                       var it_ccall = new CCodeFunctionCall (new CCodeIdentifier (it_method.get_cname ()));
+                       it_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), iterable_type));
+                       citdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (it_name, it_ccall));
+                       cblock.add_statement (citdecl);
+                       
+                       var cbody = new CCodeBlock ();
+
+                       var get_method = (Method) iterator_type.scope.lookup ("get");
+                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
+                       get_ccall.add_argument (new CCodeIdentifier (it_name));
+                       CCodeExpression element_expr = get_ccall;
+
+                       /* cast pointer to actual type if appropriate */
+                       if (stmt.type_reference.data_type is Struct) {
+                               var st = (Struct) stmt.type_reference.data_type;
+                               if (st == uint_type.data_type) {
+                                       var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_UINT"));
+                                       cconv.add_argument (element_expr);
+                                       element_expr = cconv;
+                               } else if (st == bool_type.data_type || st.is_integer_type ()) {
+                                       var cconv = new CCodeFunctionCall (new CCodeIdentifier ("GPOINTER_TO_INT"));
+                                       cconv.add_argument (element_expr);
+                                       element_expr = cconv;
+                               }
+                       }
+
+                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
+                       cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr));
+                       cbody.add_statement (cdecl);
+                       
+                       cbody.add_statement (stmt.body.ccodenode);
+                       
+                       var next_method = (Method) iterator_type.scope.lookup ("next");
+                       var next_ccall = new CCodeFunctionCall (new CCodeIdentifier (next_method.get_cname ()));
+                       next_ccall.add_argument (new CCodeIdentifier (it_name));
+
+                       cblock.add_statement (new CCodeWhileStatement (next_ccall, cbody));
+
+                       var it_unref_ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
+                       it_unref_ccall.add_argument (new CCodeIdentifier (it_name));
+                       cblock.add_statement (new CCodeExpressionStatement (it_unref_ccall));
                }
                
                if (memory_management && stmt.collection.static_type.transfers_ownership) {
index ea7b1b2..ba1f815 100644 (file)
@@ -54,6 +54,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        DataType glist_type;
        DataType gslist_type;
        DataType gerror_type;
+       DataType iterable_type;
 
        private int next_lambda_id = 0;
 
@@ -104,6 +105,11 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        gerror_type = (DataType) glib_ns.scope.lookup ("Error");
                }
 
+               var gee_ns = root_symbol.scope.lookup ("Gee");
+               if (gee_ns != null) {
+                       iterable_type = (DataType) gee_ns.scope.lookup ("Iterable");
+               }
+
                current_symbol = root_symbol;
                context.accept (this);
        }
@@ -855,7 +861,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
        public override void visit_end_foreach_statement (ForeachStatement! stmt) {
                var collection_type = stmt.collection.static_type.data_type;
-               if (!(collection_type is Array || collection_type == glist_type || collection_type == gslist_type)) {
+               if (!(collection_type is Array || collection_type == glist_type || collection_type == gslist_type || collection_type == iterable_type || collection_type.is_subtype_of (iterable_type))) {
                        stmt.error = true;
                        Report.error (stmt.source_reference, "Collection not iterable");
                        return;