]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Don't require libgee for foreach statements
authorJürg Billeter <j@bitron.ch>
Fri, 28 Nov 2008 14:50:49 +0000 (14:50 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 28 Nov 2008 14:50:49 +0000 (14:50 +0000)
2008-11-28  Jürg Billeter  <j@bitron.ch>

* vala/valablock.vala:
* vala/valaforeachstatement.vala:
* vala/valasemanticanalyzer.vala:
* gobject/valaccodebasemodule.vala:
* gobject/valaccodecontrolflowmodule.vala:

Don't require libgee for foreach statements

svn path=/trunk/; revision=2069

ChangeLog
gobject/valaccodebasemodule.vala
gobject/valaccodecontrolflowmodule.vala
vala/valablock.vala
vala/valaforeachstatement.vala
vala/valasemanticanalyzer.vala

index b3be528ab01178e9c55080b36b10ab7c9c45fe05..0b3bd395d34e2fe81fcafecbef666a0598383247 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-11-28  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valablock.vala:
+       * vala/valaforeachstatement.vala:
+       * vala/valasemanticanalyzer.vala:
+       * gobject/valaccodebasemodule.vala:
+       * gobject/valaccodecontrolflowmodule.vala:
+
+       Don't require libgee for foreach statements
+
 2008-11-28  Jürg Billeter  <j@bitron.ch>
 
        * vala/valaclass.vala:
index 99a868114cf95710053be3f61d15646cf80fc0d0..3a26d3570c3ab0fc8e8a1263015074727658e9fc 100644 (file)
@@ -113,8 +113,6 @@ public class Vala.CCodeBaseModule : CCodeModule {
        public DataType gquark_type;
        public Struct mutex_type;
        public TypeSymbol type_module_type;
-       public Interface iterable_type;
-       public Interface iterator_type;
        public Interface collection_type;
        public Interface list_type;
        public Interface map_type;
@@ -553,8 +551,6 @@ public class Vala.CCodeBaseModule : CCodeModule {
 
                var gee_ns = root_symbol.scope.lookup ("Gee");
                if (gee_ns != null) {
-                       iterable_type = (Interface) gee_ns.scope.lookup ("Iterable");
-                       iterator_type = (Interface) gee_ns.scope.lookup ("Iterator");
                        collection_type = (Interface) gee_ns.scope.lookup ("Collection");
                        list_type = (Interface) gee_ns.scope.lookup ("List");
                        map_type = (Interface) gee_ns.scope.lookup ("Map");
index 309c508a596decdd37529b62e1082d19768e13a9..e1b4bafec4840180559a00ef5e7e01fbe3810508 100644 (file)
@@ -453,98 +453,6 @@ public class Vala.CCodeControlFlowModule : CCodeMethodModule {
 
                        cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeMemberAccess.pointer (new CCodeIdentifier (it_name), "next")));
                        cblock.add_statement (cfor);
-               } else if (list_type != null && stmt.collection.value_type.compatible (new ObjectType (list_type))) {
-                       // iterating over a Gee.List, use integer to avoid the cost of an iterator object
-
-                       var it_name = "%s_it".printf (stmt.variable_name);
-
-                       var citdecl = new CCodeDeclaration ("int");
-                       citdecl.add_declarator (new CCodeVariableDeclarator (it_name));
-                       cblock.add_statement (citdecl);
-                       
-                       var cbody = new CCodeBlock ();
-
-                       var get_method = (Method) list_type.scope.lookup ("get");
-                       var get_ccall = new CCodeFunctionCall (new CCodeIdentifier (get_method.get_cname ()));
-                       get_ccall.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), list_type));
-                       get_ccall.add_argument (new CCodeIdentifier (it_name));
-                       CCodeExpression element_expr = get_ccall;
-
-                       var element_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, (GenericType) get_method.return_type, stmt);
-
-                       element_expr = convert_from_generic_pointer (element_expr, element_type);
-                       element_expr = transform_expression (element_expr, element_type, stmt.type_reference);
-
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
-                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-                       cvardecl.line = cblock.line;
-                       cdecl.add_declarator (cvardecl);
-                       cbody.add_statement (cdecl);
-
-                       cbody.add_statement (stmt.body.ccodenode);
-
-                       var list_len = new CCodeFunctionCall (new CCodeIdentifier ("gee_collection_get_size"));
-                       list_len.add_argument (new InstanceCast (new CCodeIdentifier (collection_backup.name), this.collection_type));
-
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, new CCodeIdentifier (it_name), list_len);
-
-                       var cfor = new CCodeForStatement (ccond, cbody);
-                       cfor.add_initializer (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeConstant ("0")));
-                       cfor.add_iterator (new CCodeAssignment (new CCodeIdentifier (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new CCodeIdentifier (it_name), new CCodeConstant ("1"))));
-                       cfor.line = cblock.line;
-                       cblock.add_statement (cfor);
-               } else if (iterable_type != null && stmt.collection.value_type.compatible (new ObjectType (iterable_type))) {
-                       // iterating over a Gee.Iterable, use iterator
-
-                       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));
-                       var citvardecl = new CCodeVariableDeclarator.with_initializer (it_name, it_ccall);
-                       citvardecl.line = cblock.line;
-                       citdecl.add_declarator (citvardecl);
-                       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;
-
-                       Iterator<DataType> type_arg_it = it_method.return_type.get_type_arguments ().iterator ();
-                       type_arg_it.next ();
-                       var it_type = SemanticAnalyzer.get_actual_type (stmt.collection.value_type, (GenericType) type_arg_it.get (), stmt);
-
-                       element_expr = transform_expression (element_expr, it_type, stmt.type_reference);
-
-                       var cfrag = new CCodeFragment ();
-                       append_temp_decl (cfrag, temp_vars);
-                       cbody.add_statement (cfrag);
-                       temp_vars.clear ();
-
-                       var cdecl = new CCodeDeclaration (stmt.type_reference.get_cname ());
-                       var cvardecl = new CCodeVariableDeclarator.with_initializer (stmt.variable_name, element_expr);
-                       cvardecl.line = cblock.line;
-                       cdecl.add_declarator (cvardecl);
-                       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));
-
-                       var cwhile = new CCodeWhileStatement (next_ccall, cbody);
-                       cwhile.line = cblock.line;
-                       cblock.add_statement (cwhile);
                }
 
                foreach (LocalVariable local in stmt.get_local_variables ()) {
index d715b74ccbeec750b8f6369a3ce4c4f273fde7f6..330daa7f0afc187cf471773a4858e311a5cbcf26 100644 (file)
@@ -53,7 +53,11 @@ public class Vala.Block : Symbol, Statement {
        public void add_statement (Statement stmt) {
                statement_list.add (stmt);
        }
-       
+
+       public void insert_statement (int index, Statement stmt) {
+               statement_list.insert (index, stmt);
+       }
+
        /**
         * Returns a copy of the list of statements.
         *
index 04c196590f636b2efe0d1729017d0c5cb3432d15..ed2d68092a4bde27b016c44c402d883ae12081c2 100644 (file)
@@ -71,6 +71,8 @@ public class Vala.ForeachStatement : Block {
                }
        }
 
+       public bool use_iterator { get; private set; }
+
        /**
         * Specifies the declarator for the generated element variable.
         */
@@ -109,10 +111,20 @@ public class Vala.ForeachStatement : Block {
        }
        
        public override void accept (CodeVisitor visitor) {
+               if (use_iterator) {
+                       base.accept (visitor);
+                       return;
+               }
+
                visitor.visit_foreach_statement (this);
        }
 
        public override void accept_children (CodeVisitor visitor) {
+               if (use_iterator) {
+                       base.accept_children (visitor);
+                       return;
+               }
+
                collection.accept (visitor);
                visitor.visit_end_full_expression (collection);
 
@@ -156,65 +168,116 @@ public class Vala.ForeachStatement : Block {
                var collection_type = collection.value_type.copy ();
                collection.target_type = collection_type.copy ();
                
-               DataType element_data_type = null;
-               bool element_owned = false;
-
                if (collection_type.is_array ()) {
                        var array_type = (ArrayType) collection_type;
-                       element_data_type = array_type.element_type;
+
+                       return check_without_iterator (analyzer, collection_type, array_type.element_type);
                } else if (collection_type.compatible (analyzer.glist_type) || collection_type.compatible (analyzer.gslist_type)) {
-                       if (collection_type.get_type_arguments ().size > 0) {
-                               element_data_type = (DataType) collection_type.get_type_arguments ().get (0);
-                       }
-               } else if (analyzer.iterable_type != null && collection_type.compatible (analyzer.iterable_type)) {
-                       element_owned = true;
-
-                       if (analyzer.list_type == null || !collection_type.compatible (new ObjectType (analyzer.list_type))) {
-                               // don't use iterator objects for lists for performance reasons
-                               var foreach_iterator_type = new ObjectType (analyzer.iterator_type);
-                               foreach_iterator_type.value_owned = true;
-                               foreach_iterator_type.add_type_argument (type_reference);
-                               iterator_variable = new LocalVariable (foreach_iterator_type, "%s_it".printf (variable_name));
-
-                               add_local_variable (iterator_variable);
-                               iterator_variable.active = true;
+                       if (collection_type.get_type_arguments ().size != 1) {
+                               error = true;
+                               Report.error (collection.source_reference, "missing type argument for collection");
+                               return false;
                        }
 
-                       var it_method = (Method) analyzer.iterable_type.data_type.scope.lookup ("iterator");
-                       if (it_method.return_type.get_type_arguments ().size > 0) {
-                               var type_arg = it_method.return_type.get_type_arguments ().get (0);
-                               if (type_arg is GenericType) {
-                                       element_data_type = SemanticAnalyzer.get_actual_type (collection_type, (GenericType) type_arg, this);
-                               } else {
-                                       element_data_type = type_arg;
-                               }
-                       }
+                       return check_without_iterator (analyzer, collection_type, collection_type.get_type_arguments ().get (0));
                } else {
+                       return check_with_iterator (analyzer, collection_type);
+               }
+       }
+
+       bool check_with_iterator (SemanticAnalyzer analyzer, DataType collection_type) {
+               use_iterator = true;
+
+               var iterator_method = collection_type.get_member ("iterator") as Method;
+               if (iterator_method == null) {
+                       Report.error (collection.source_reference, "`%s' does not have an `iterator' method".printf (collection_type.to_string ()));
                        error = true;
-                       Report.error (source_reference, "Gee.List not iterable");
                        return false;
                }
-
-               if (element_data_type == null) {
+               if (iterator_method.get_parameters ().size != 0) {
+                       Report.error (collection.source_reference, "`%s' must not have any parameters".printf (iterator_method.get_full_name ()));
+                       error = true;
+                       return false;
+               }
+               var iterator_type = iterator_method.return_type.get_actual_type (collection_type, this);
+               if (iterator_type is VoidType) {
+                       Report.error (collection.source_reference, "`%s' must return an iterator".printf (iterator_method.get_full_name ()));
+                       error = true;
+                       return false;
+               }
+               var next_method = iterator_type.get_member ("next") as Method;
+               if (next_method == null) {
+                       Report.error (collection.source_reference, "`%s' does not have a `next' method".printf (iterator_type.to_string ()));
+                       error = true;
+                       return false;
+               }
+               if (next_method.get_parameters ().size != 0) {
+                       Report.error (collection.source_reference, "`%s' must not have any parameters".printf (next_method.get_full_name ()));
+                       error = true;
+                       return false;
+               }
+               if (!next_method.return_type.compatible (analyzer.bool_type)) {
+                       Report.error (collection.source_reference, "`%s' must return a boolean value".printf (next_method.get_full_name ()));
+                       error = true;
+                       return false;
+               }
+               var get_method = iterator_type.get_member ("get") as Method;
+               if (get_method == null) {
+                       Report.error (collection.source_reference, "`%s' does not have a `get' method".printf (iterator_type.to_string ()));
+                       error = true;
+                       return false;
+               }
+               if (get_method.get_parameters ().size != 0) {
+                       Report.error (collection.source_reference, "`%s' must not have any parameters".printf (get_method.get_full_name ()));
+                       error = true;
+                       return false;
+               }
+               var element_type = get_method.return_type.get_actual_type (iterator_type, this);
+               if (element_type is VoidType) {
+                       Report.error (collection.source_reference, "`%s' must return an element".printf (get_method.get_full_name ()));
                        error = true;
-                       Report.error (collection.source_reference, "missing type argument for collection");
                        return false;
                }
 
                // analyze element type
                if (type_reference == null) {
                        // var type
-                       type_reference = element_data_type.copy ();
-               } else if (!element_data_type.compatible (type_reference)) {
+                       type_reference = element_type.copy ();
+               } else if (!element_type.compatible (type_reference)) {
                        error = true;
-                       Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_data_type.to_string (), type_reference.to_string ()));
+                       Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_type.to_string (), type_reference.to_string ()));
                        return false;
-               } else if (element_data_type.is_disposable () && element_owned && !type_reference.value_owned) {
+               } else if (element_type.is_disposable () && element_type.value_owned && !type_reference.value_owned) {
                        error = true;
                        Report.error (source_reference, "Foreach: Invalid assignment from owned expression to unowned variable");
                        return false;
                }
-               
+
+               var iterator_call = new MethodCall (new MemberAccess (collection, "iterator"));
+               add_statement (new DeclarationStatement (new LocalVariable (iterator_type, "%s_it".printf (variable_name), iterator_call, source_reference), source_reference));
+
+               var next_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("%s_it".printf (variable_name)), "next"));
+               var loop = new WhileStatement (next_call, body);
+               add_statement (loop);
+
+               var get_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("%s_it".printf (variable_name)), "get"));
+               body.insert_statement (0, new DeclarationStatement (new LocalVariable (type_reference, variable_name, get_call, source_reference), source_reference));
+
+               checked = false;
+               return base.check (analyzer);
+       }
+
+       bool check_without_iterator (SemanticAnalyzer analyzer, DataType collection_type, DataType element_type) {
+               // analyze element type
+               if (type_reference == null) {
+                       // var type
+                       type_reference = element_type.copy ();
+               } else if (!element_type.compatible (type_reference)) {
+                       error = true;
+                       Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_type.to_string (), type_reference.to_string ()));
+                       return false;
+               }
+
                analyzer.current_source_file.add_type_dependency (type_reference, SourceFileDependencyType.SOURCE);
 
                element_variable = new LocalVariable (type_reference, variable_name);
@@ -242,7 +305,6 @@ public class Vala.ForeachStatement : Block {
                add_local_variable (collection_variable);
                collection_variable.active = true;
 
-
                add_error_types (collection.get_error_types ());
                add_error_types (body.get_error_types ());
 
index 4b6b7b8e9f56edba43db46193d2d314341c20d04..937e846823d66fb37be27b39b2bb42c705aa976a 100644 (file)
@@ -58,8 +58,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public DataType gslist_type;
        public DataType garray_type;
        public Class gerror_type;
-       public DataType iterable_type;
-       public Interface iterator_type;
        public Interface list_type;
        public Interface collection_type;
        public Interface map_type;
@@ -116,8 +114,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                var gee_ns = root_symbol.scope.lookup ("Gee");
                if (gee_ns != null) {
-                       iterable_type = new ObjectType ((Interface) gee_ns.scope.lookup ("Iterable"));
-                       iterator_type = (Interface) gee_ns.scope.lookup ("Iterator");
                        list_type = (Interface) gee_ns.scope.lookup ("List");
                        collection_type = (Interface) gee_ns.scope.lookup ("Collection");
                        map_type = (Interface) gee_ns.scope.lookup ("Map");