[vala/staging] Move ForeachStatement transformation into the code transformer



commit 63c4de0fa74aca2cefcab0a6530990ea6a4317b9
Author: Luca Bruno <lucabru src gnome org>
Date:   Wed Jan 4 18:38:38 2012 +0100

    Move ForeachStatement transformation into the code transformer

 codegen/valaccodebasemodule.vala        |   4 +-
 codegen/valaccodecontrolflowmodule.vala | 131 -------------------------
 codegen/valaccodetransformer.vala       |  61 ++++++++++++
 vala/valaassignment.vala                |   2 +-
 vala/valabinaryexpression.vala          |   2 +-
 vala/valacodebuilder.vala               |  17 ++--
 vala/valaflowanalyzer.vala              |   2 +
 vala/valaforeachstatement.vala          | 169 +++++++++++---------------------
 vala/valaobjectcreationexpression.vala  |   4 +-
 vala/valasemanticanalyzer.vala          |   8 --
 10 files changed, 132 insertions(+), 268 deletions(-)
---
diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 677285d51..c7066f96c 100644
--- a/codegen/valaccodebasemodule.vala
+++ b/codegen/valaccodebasemodule.vala
@@ -2184,7 +2184,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                                }
                        } else if (b.parent_symbol is ForeachStatement) {
                                var stmt = (ForeachStatement) b.parent_symbol;
-                               if (!stmt.use_iterator && stmt.element_variable.captured) {
+                               if (stmt.element_variable.captured) {
                                        ccode.add_assignment (new CCodeMemberAccess.pointer 
(get_variable_cexpression ("_data%d_".printf (block_id)), get_local_cname (stmt.element_variable)), 
get_variable_cexpression (get_local_cname (stmt.element_variable)));
                                }
                        }
@@ -2510,7 +2510,7 @@ public abstract class Vala.CCodeBaseModule : CodeGenerator {
                var block = local.parent_symbol;
                if (block != null) {
                        var stmt = block.parent_symbol as ForeachStatement;
-                       if (stmt != null && !stmt.use_iterator && stmt.element_variable == local) {
+                       if (stmt != null && stmt.element_variable == local) {
                                return true;
                        }
                }
diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala
index df31fcef3..d5afd6ccc 100644
--- a/codegen/valaccodecontrolflowmodule.vala
+++ b/codegen/valaccodecontrolflowmodule.vala
@@ -218,137 +218,6 @@ public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
                ccode.close ();
        }
 
-       public override void visit_foreach_statement (ForeachStatement stmt) {
-               ccode.open_block ();
-
-               var collection_backup = stmt.collection_variable;
-               var collection_type = collection_backup.variable_type;
-
-               var array_type = collection_type as ArrayType;
-               if (array_type != null) {
-                       // avoid assignment issues
-                       array_type.inline_allocated = false;
-                       array_type.fixed_length = false;
-               }
-
-               visit_local_variable (collection_backup);
-               ccode.add_assignment (get_variable_cexpression (get_local_cname (collection_backup)), 
get_cvalue (stmt.collection));
-
-               if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
-                       // exception handling
-                       add_simple_check (stmt.collection);
-               }
-
-               if (stmt.collection.value_type is ArrayType) {
-                       array_type = (ArrayType) stmt.collection.value_type;
-
-                       var array_len = get_variable_cexpression (get_array_length_cname (get_local_cname 
(collection_backup), 1));
-
-                       // store array length for use by _vala_array_free
-                       ccode.add_assignment (array_len, get_array_length_cexpression (stmt.collection));
-
-                       var iterator_variable = new LocalVariable (array_type.length_type.copy (), 
stmt.variable_name + "_it");
-                       visit_local_variable (iterator_variable);
-                       var it_name = get_local_cname (iterator_variable);
-
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, 
get_variable_cexpression (it_name), array_len);
-
-                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), new 
CCodeConstant ("0")),
-                                          ccond,
-                                          new CCodeAssignment (get_variable_cexpression (it_name), new 
CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant 
("1"))));
-
-                       CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression 
(get_local_cname (collection_backup)), get_variable_cexpression (it_name));
-
-                       var element_type = array_type.element_type.copy ();
-                       element_type.value_owned = false;
-                       element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, 
element_expr, 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);
-
-                       // set array length for stacked arrays
-                       if (stmt.type_reference is ArrayType) {
-                               var inner_array_type = (ArrayType) stmt.type_reference;
-                               for (int dim = 1; dim <= inner_array_type.rank; dim++) {
-                                       ccode.add_assignment (get_variable_cexpression 
(get_array_length_cname (get_local_cname (stmt.element_variable), dim)), new CCodeConstant ("-1"));
-                               }
-                       }
-
-                       stmt.body.emit (this);
-
-                       ccode.close ();
-               } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || 
stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
-                       // iterating over a GList or GSList
-
-                       var iterator_variable = new LocalVariable (collection_type.copy (), 
stmt.variable_name + "_it");
-                       visit_local_variable (iterator_variable);
-                       var it_name = get_local_cname (iterator_variable);
-
-                       var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, 
get_variable_cexpression (it_name), new CCodeConstant ("NULL"));
-
-                       ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), 
get_variable_cexpression (get_local_cname (collection_backup))),
-                                                       ccond,
-                                                       new CCodeAssignment (get_variable_cexpression 
(it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
-
-                       CCodeExpression element_expr = new CCodeMemberAccess.pointer 
(get_variable_cexpression (it_name), "data");
-
-                       if (collection_type.get_type_arguments ().size != 1) {
-                               Report.error (stmt.source_reference, "internal error: missing generic type 
argument");
-                               stmt.error = true;
-                               return;
-                       }
-
-                       var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
-                       element_data_type.value_owned = false;
-                       element_expr = convert_from_generic_pointer (element_expr, element_data_type);
-                       element_expr = get_cvalue_ (transform_value (new GLibValue (element_data_type, 
element_expr), 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 if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
-                       // iterating over a GValueArray
-
-                       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)), "n_values"));
-
-                       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_value_array_get_nth"));
-                       get_item.add_argument (get_variable_cexpression (get_local_cname 
(collection_backup)));
-                       get_item.add_argument (get_variable_cexpression (arr_index));
-
-                       CCodeExpression element_expr = new CCodeUnaryExpression 
(CCodeUnaryOperator.POINTER_INDIRECTION, 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 ();
-               }
-
-               foreach (LocalVariable local in stmt.get_local_variables ()) {
-                       if (requires_destroy (local.variable_type)) {
-                               ccode.add_expression (destroy_local (local));
-                       }
-               }
-
-               ccode.close ();
-       }
-
        public override void visit_break_statement (BreakStatement stmt) {
                append_local_free (current_symbol, stmt);
 
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
index 5afe0289e..c89190e4a 100644
--- a/codegen/valaccodetransformer.vala
+++ b/codegen/valaccodetransformer.vala
@@ -136,6 +136,67 @@ public class Vala.CCodeTransformer : CodeTransformer {
                end_replace_statement ();
        }
 
+       public override void visit_foreach_statement (ForeachStatement stmt) {
+               begin_replace_statement (stmt);
+
+               var collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection);
+
+               stmt.body.remove_local_variable (stmt.element_variable);
+               stmt.element_variable.checked = false;
+               var decl = new DeclarationStatement (stmt.element_variable, 
stmt.element_variable.source_reference);
+
+               switch (stmt.foreach_iteration) {
+               case ForeachIteration.ARRAY:
+               case ForeachIteration.GVALUE_ARRAY:
+                       // array or GValueArray
+                       var array = collection;
+                       if (stmt.foreach_iteration == ForeachIteration.GVALUE_ARRAY) {
+                               array = collection+".values";
+                       }
+                       var i = b.add_temp_declaration (null, expression ("0"));
+                       b.open_for (null, expression (@"$i < $array.length"), expression (@"$i++"));
+                       stmt.element_variable.initializer = expression (@"$array[$i]");
+                       break;
+               case ForeachIteration.GLIST:
+                       // GList or GSList
+                       var iter_type = stmt.collection.value_type.copy ();
+                       iter_type.value_owned = false;
+                       var iter = b.add_temp_declaration (iter_type, expression (collection));
+                       b.open_for (null, expression (@"$iter != null"), expression (@"$iter = $iter.next"));
+                       stmt.element_variable.initializer = expression (@"$iter.data");
+                       break;
+               case ForeachIteration.INDEX:
+                       // get()+size
+                       var size = b.add_temp_declaration (null, expression (@"$collection.size"));
+                       var i = b.add_temp_declaration (null, expression ("0"));
+                       b.open_for (null, expression (@"$i < $size"), expression (@"$i++"));
+                       stmt.element_variable.initializer = expression (@"$collection.get ($i)");
+                       break;
+               case ForeachIteration.NEXT_VALUE:
+                       // iterator+next_value()
+                       var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
+                       var temp = b.add_temp_declaration (stmt.type_reference);
+                       b.open_while (expression (@"($temp = $iterator.next_value ()) != null"));
+                       stmt.element_variable.initializer = expression (temp);
+                       break;
+               case ForeachIteration.NEXT_GET:
+                       // iterator+next()+get()
+                       var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
+                       b.open_while (expression (@"$iterator.next ()"));
+                       stmt.element_variable.initializer = expression (@"$iterator.get ()");
+                       break;
+               default:
+                       assert_not_reached ();
+               }
+
+               stmt.body.insert_statement (0, decl);
+               b.add_statement (stmt.body);
+               b.close ();
+
+               stmt.body.checked = false;
+               end_replace_statement ();
+       }
+
        public override void visit_expression (Expression expr) {
                if (expr in context.analyzer.replaced_nodes) {
                        return;
diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala
index 4c1f4bfdf..298ace9a1 100644
--- a/vala/valaassignment.vala
+++ b/vala/valaassignment.vala
@@ -117,7 +117,7 @@ public class Vala.Assignment : Expression {
 
                checked = true;
 
-               var insert_block = context.analyzer.get_insert_block (this);
+               var insert_block = context.analyzer.get_current_block (this);
 
                if (left is Tuple && operator == AssignmentOperator.SIMPLE && parent_node is 
ExpressionStatement) {
                        unowned Tuple tuple = (Tuple) left;
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index 7f24a4bda..331aa0d55 100644
--- a/vala/valabinaryexpression.vala
+++ b/vala/valabinaryexpression.vala
@@ -140,7 +140,7 @@ public class Vala.BinaryExpression : Expression {
 
                checked = true;
 
-               var insert_block = context.analyzer.get_insert_block (this);
+               var insert_block = context.analyzer.get_current_block (this);
 
                // some expressions are not in a block,
                // for example, expressions in method contracts
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index cedac79f1..4a86650ea 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -29,17 +29,15 @@ public class Vala.CodeBuilder {
        Statement insert_statement;
        Block insert_block;
        ArrayList<Statement> statement_stack = new ArrayList<Statement> ();
-       ArrayList<CodeNode> check_nodes = new ArrayList<CodeNode> ();
+       ArrayList<CodeNode> decl_nodes = new ArrayList<CodeNode> ();
 
        public CodeBuilder (CodeContext context, Statement insert_statement, SourceReference 
source_reference) {
-               current_block = new Block (source_reference);
-               insert_block = context.analyzer.get_insert_block (insert_statement);
                this.source_reference = source_reference;
 
-               var statement_block = context.analyzer.get_current_block (insert_statement);
-               statement_block.insert_before (insert_statement, current_block);
-               insert_statement = current_block;
-               check_nodes.add (current_block);
+               current_block = new Block (source_reference);
+               insert_block = context.analyzer.get_current_block (insert_statement);
+               insert_block.insert_before (insert_statement, current_block);
+               this.insert_statement = current_block;
        }
 
        public CodeBuilder.for_subroutine (Subroutine m) {
@@ -50,9 +48,10 @@ public class Vala.CodeBuilder {
        }
 
        public void check (CodeTransformer transformer) {
-               foreach (var node in check_nodes) {
+               foreach (var node in decl_nodes) {
                        transformer.check (node);
                }
+               transformer.check (current_block);
        }
 
        public void open_block () {
@@ -247,7 +246,7 @@ public class Vala.CodeBuilder {
                var local = new LocalVariable (type, CodeNode.get_temp_name (), initializer, 
source_reference);
                var stmt = new DeclarationStatement (local, source_reference);
                insert_block.insert_before (insert_statement, stmt);
-               check_nodes.insert (0, stmt);
+               decl_nodes.add (stmt);
                return local.name;
        }
 
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index df19e412c..ad6ef8ad6 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -801,12 +801,14 @@ public class Vala.FlowAnalyzer : CodeVisitor {
                all_basic_blocks.add (outer_block);
                foreach (var init_expr in stmt.get_initializer ()) {
                        outer_block.add_node (init_expr);
+                       handle_errors (init_expr);
                }
 
                var iterator_block = new BasicBlock ();
                all_basic_blocks.add (iterator_block);
                foreach (var it_expr in stmt.get_iterator ()) {
                        iterator_block.add_node (it_expr);
+                       handle_errors (it_expr);
                }
 
                var loop_block = new BasicBlock ();
diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala
index d53f816fb..920f7d61f 100644
--- a/vala/valaforeachstatement.vala
+++ b/vala/valaforeachstatement.vala
@@ -25,7 +25,7 @@
  * Represents a foreach statement in the source code. Foreach statements iterate
  * over the elements of a collection.
  */
-public class Vala.ForeachStatement : Block {
+public class Vala.ForeachStatement : CodeNode, Statement {
        /**
         * Specifies the element type.
         */
@@ -70,22 +70,15 @@ public class Vala.ForeachStatement : Block {
                }
        }
 
-       public bool use_iterator { get; private set; }
-
        /**
-        * Specifies the declarator for the generated element variable.
+        * Specifies the approach used for the iteration.
         */
-       public LocalVariable element_variable { get; private set; }
+       public ForeachIteration foreach_iteration { get; private set; }
 
        /**
-        * Specifies the declarator for the generated collection variable.
-        */
-       public LocalVariable collection_variable { get; private set; }
-
-       /**
-        * Specifies the declarator for the generated iterator variable.
+        * Specifies the declarator for the generated element variable.
         */
-       public LocalVariable iterator_variable { get; private set; }
+       public LocalVariable element_variable { get; private set; }
 
        private Expression _collection;
        private Block _body;
@@ -103,28 +96,18 @@ public class Vala.ForeachStatement : Block {
         * @return                  newly created foreach statement
         */
        public ForeachStatement (DataType? type_reference, string variable_name, Expression collection, Block 
body, SourceReference source_reference) {
-               base (source_reference);
                this.variable_name = variable_name;
                this.collection = collection;
                this.body = body;
                this.type_reference = type_reference;
+               this.source_reference = source_reference;
        }
 
        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);
 
@@ -154,8 +137,6 @@ public class Vala.ForeachStatement : Block {
 
                checked = true;
 
-               owner = context.analyzer.get_current_symbol (parent_node).scope;
-
                // analyze collection expression first, used for type inference
                if (!collection.check (context)) {
                        // ignore inner error
@@ -176,20 +157,34 @@ public class Vala.ForeachStatement : Block {
                        // can't use inline-allocated array for temporary variable
                        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))) {
+                       foreach_iteration = ForeachIteration.ARRAY;
+                       error = !analyze_element_type (array_type.element_type, false);
+               } else if (context.profile == Profile.GOBJECT && collection_type.compatible 
(context.analyzer.glist_type) || collection_type.compatible (context.analyzer.gslist_type)) {
                        if (collection_type.get_type_arguments ().size != 1) {
                                error = true;
                                Report.error (collection.source_reference, "missing type argument for 
collection");
                                return false;
                        }
 
-                       return check_without_iterator (context, collection_type, 
collection_type.get_type_arguments ().get (0));
+                       foreach_iteration = ForeachIteration.GLIST;
+                       error = !analyze_element_type (collection_type.get_type_arguments ().get (0), false);
                } else if (context.profile == Profile.GOBJECT && collection_type.compatible 
(context.analyzer.gvaluearray_type)) {
-                       return check_without_iterator (context, collection_type, 
context.analyzer.gvalue_type);
+                       foreach_iteration = ForeachIteration.GVALUE_ARRAY;
+                       error = !analyze_element_type (context.analyzer.gvalue_type, false);
                } else {
-                       return check_with_iterator (context, collection_type);
+                       error = !check_with_iterator (context, collection_type);
                }
+
+               element_variable = new LocalVariable (type_reference, variable_name, null, source_reference);
+               element_variable.checked = true;
+               element_variable.active = true;
+               body.add_local_variable (element_variable);
+               if (!body.check (context)) {
+                       error = true;
+               }
+               element_variable.active = false;
+
+               return !error;
        }
 
        bool check_with_index (CodeContext context, DataType collection_type) {
@@ -200,30 +195,27 @@ public class Vala.ForeachStatement : Block {
                if (get_method.get_parameters ().size != 1) {
                        return false;
                }
-               var size_property = collection_type.get_member ("size") as Property;
-               if (size_property == null) {
+               var element_type = get_method.return_type.get_actual_type (collection.value_type, null, this);
+               if (element_type is VoidType) {
+                       Report.error (collection.source_reference, "`%s' must return an element".printf 
(get_method.get_full_name ()));
+                       error = true;
                        return false;
                }
 
-               add_statement (new DeclarationStatement (new LocalVariable (null, "_%s_list".printf 
(variable_name), collection, source_reference), source_reference));
-               add_statement (new DeclarationStatement (new LocalVariable (null, "_%s_size".printf 
(variable_name), new MemberAccess (new MemberAccess.simple ("_%s_list".printf (variable_name), 
source_reference), "size", source_reference), source_reference), source_reference));
-               add_statement (new DeclarationStatement (new LocalVariable (null, "_%s_index".printf 
(variable_name), new UnaryExpression (UnaryOperator.MINUS, new IntegerLiteral ("1", source_reference), 
source_reference), source_reference), source_reference));
-               var next = new UnaryExpression (UnaryOperator.INCREMENT, new MemberAccess.simple 
("_%s_index".printf (variable_name), source_reference), source_reference);
-               var conditional = new BinaryExpression (BinaryOperator.LESS_THAN, next, new 
MemberAccess.simple ("_%s_size".printf (variable_name), source_reference), source_reference);
-               var loop = new WhileStatement (conditional, body, source_reference);
-               add_statement (loop);
+               if (!analyze_element_type (element_type, element_type.value_owned)) {
+                       return false;
+               }
 
-               var get_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_list".printf 
(variable_name), source_reference), "get", source_reference), source_reference);
-               get_call.add_argument (new MemberAccess.simple ("_%s_index".printf (variable_name), 
source_reference));
-               body.insert_statement (0, new DeclarationStatement (new LocalVariable (type_reference, 
variable_name, get_call, source_reference), source_reference));
+               var size_property = collection_type.get_member ("size") as Property;
+               if (size_property == null) {
+                       return false;
+               }
 
-               checked = false;
-               return base.check (context);
+               foreach_iteration = ForeachIteration.INDEX;
+               return true;
        }
 
        bool check_with_iterator (CodeContext context, DataType collection_type) {
-               use_iterator = true;
-
                if (check_with_index (context, collection_type)) {
                        return true;
                }
@@ -246,9 +238,6 @@ public class Vala.ForeachStatement : Block {
                        return false;
                }
 
-               var iterator_call = new MethodCall (new MemberAccess (collection, "iterator", 
source_reference), source_reference);
-               add_statement (new DeclarationStatement (new LocalVariable (iterator_type, "_%s_it".printf 
(variable_name), iterator_call, source_reference), source_reference));
-
                var next_value_method = iterator_type.get_member ("next_value") as Method;
                var next_method = iterator_type.get_member ("next") as Method;
                if (next_value_method != null) {
@@ -264,17 +253,11 @@ public class Vala.ForeachStatement : Block {
                                return false;
                        }
 
-                       if (!analyze_element_type (element_type)) {
+                       if (!analyze_element_type (element_type, element_type.value_owned)) {
                                return false;
                        }
 
-                       add_statement (new DeclarationStatement (new LocalVariable (type_reference, 
variable_name, null, source_reference), source_reference));
-
-                       var next_value_call = new MethodCall (new MemberAccess (new MemberAccess.simple 
("_%s_it".printf (variable_name), source_reference), "next_value", source_reference), source_reference);
-                       var assignment = new Assignment (new MemberAccess (null, variable_name, 
source_reference), next_value_call, AssignmentOperator.SIMPLE, source_reference);
-                       var conditional = new BinaryExpression (BinaryOperator.INEQUALITY, assignment, new 
NullLiteral (source_reference), source_reference);
-                       var loop = new WhileStatement (conditional, body, source_reference);
-                       add_statement (loop);
+                       foreach_iteration = ForeachIteration.NEXT_VALUE;
                } else if (next_method != null) {
                        if (next_method.get_parameters ().size != 0) {
                                Report.error (collection.source_reference, "`%s' must not have any 
parameters".printf (next_method.get_full_name ()));
@@ -304,27 +287,21 @@ public class Vala.ForeachStatement : Block {
                                return false;
                        }
 
-                       if (!analyze_element_type (element_type)) {
+                       if (!analyze_element_type (element_type, element_type.value_owned)) {
                                return false;
                        }
 
-                       var next_call = new MethodCall (new MemberAccess (new MemberAccess.simple 
("_%s_it".printf (variable_name), source_reference), "next", source_reference), source_reference);
-                       var loop = new WhileStatement (next_call, body, source_reference);
-                       add_statement (loop);
-
-                       var get_call = new MethodCall (new MemberAccess (new MemberAccess.simple 
("_%s_it".printf (variable_name), source_reference), "get", source_reference), source_reference);
-                       body.insert_statement (0, new DeclarationStatement (new LocalVariable 
(type_reference, variable_name, get_call, source_reference), source_reference));
+                       foreach_iteration = ForeachIteration.NEXT_GET;
                } else {
                        Report.error (collection.source_reference, "`%s' does not have a `next_value' or 
`next' method".printf (iterator_type.to_string ()));
                        error = true;
                        return false;
                }
 
-               checked = false;
-               return base.check (context);
+               return true;
        }
 
-       bool analyze_element_type (DataType element_type) {
+       bool analyze_element_type (DataType element_type, bool get_owned) {
                // analyze element type
                if (type_reference == null) {
                        // var type
@@ -333,7 +310,7 @@ public class Vala.ForeachStatement : Block {
                        error = true;
                        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_type.is_disposable () && element_type.value_owned && 
!type_reference.value_owned) {
+               } else if (get_owned && 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;
@@ -342,41 +319,6 @@ public class Vala.ForeachStatement : Block {
                return true;
        }
 
-       bool check_without_iterator (CodeContext context, 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;
-               }
-
-               element_variable = new LocalVariable (type_reference, variable_name, null, source_reference);
-
-               body.add_local_variable (element_variable);
-               element_variable.active = true;
-               element_variable.checked = true;
-
-               // call add_local_variable to check for shadowed variable
-               add_local_variable (element_variable);
-               remove_local_variable (element_variable);
-
-               body.check (context);
-
-               foreach (LocalVariable local in get_local_variables ()) {
-                       local.active = false;
-               }
-
-               collection_variable = new LocalVariable (collection_type.copy (), "%s_collection".printf 
(variable_name));
-
-               add_local_variable (collection_variable);
-               collection_variable.active = true;
-
-               return !error;
-       }
-
        public override void get_error_types (Collection<DataType> collection, SourceReference? 
source_reference = null) {
                if (source_reference == null) {
                        source_reference = this.source_reference;
@@ -386,20 +328,9 @@ public class Vala.ForeachStatement : Block {
        }
 
        public override void emit (CodeGenerator codegen) {
-               if (use_iterator) {
-                       base.emit (codegen);
-                       return;
-               }
-
                collection.emit (codegen);
                codegen.visit_end_full_expression (collection);
 
-               element_variable.active = true;
-               collection_variable.active = true;
-               if (iterator_variable != null) {
-                       iterator_variable.active = true;
-               }
-
                codegen.visit_foreach_statement (this);
        }
 
@@ -409,3 +340,13 @@ public class Vala.ForeachStatement : Block {
                }
        }
 }
+
+public enum Vala.ForeachIteration {
+       NONE,
+       ARRAY,
+       GVALUE_ARRAY,
+       GLIST,
+       INDEX,
+       NEXT_VALUE,
+       NEXT_GET
+}
diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala
index 6cb791d93..12641d1d8 100644
--- a/vala/valaobjectcreationexpression.vala
+++ b/vala/valaobjectcreationexpression.vala
@@ -514,7 +514,7 @@ public class Vala.ObjectCreationExpression : Expression {
                                var local = new LocalVariable (value_type.copy (), get_temp_name (), null, 
source_reference);
                                var decl = new DeclarationStatement (local, source_reference);
 
-                               insert_statement (context.analyzer.get_insert_block (this), decl);
+                               insert_statement (context.analyzer.get_current_block (this), decl);
 
                                var temp_access = SemanticAnalyzer.create_temp_access (local, target_type);
                                temp_access.formal_target_type = formal_target_type;
@@ -528,7 +528,7 @@ public class Vala.ObjectCreationExpression : Expression {
                                // otherwise there will be scoping issues in the generated code
                                var block = context.analyzer.get_current_block (this);
                                block.remove_local_variable (local);
-                               context.analyzer.get_insert_block (this).add_local_variable (local);
+                               context.analyzer.get_current_block (this).add_local_variable (local);
 
                                old_parent_node.replace_expression (this, temp_access);
                                temp_access.check (context);
diff --git a/vala/valasemanticanalyzer.vala b/vala/valasemanticanalyzer.vala
index a50079d19..174f8b992 100644
--- a/vala/valasemanticanalyzer.vala
+++ b/vala/valasemanticanalyzer.vala
@@ -269,14 +269,6 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                return (Block) node;
        }
 
-       public unowned Block? get_insert_block (CodeNode node) {
-               unowned Block? block = get_current_block (node);
-               if (block is ForeachStatement) {
-                       block = block.parent_symbol as Block;
-               }
-               return block;
-       }
-
        // check whether type is at least as accessible as the specified symbol
        public bool is_type_accessible (Symbol sym, DataType type) {
                return type.is_accessible (sym);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]