From: Luca Bruno Date: Wed, 4 Jan 2012 17:38:38 +0000 (+0100) Subject: Move ForeachStatement transformation into the code transformer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5bbb38fa01b3531c5ef0cce82fa0e0fab6b327bc;p=thirdparty%2Fvala.git Move ForeachStatement transformation into the code transformer --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index acbb763ce..def436118 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -2142,7 +2142,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))); } } @@ -2441,7 +2441,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 58e51d99f..5a44ac396 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_array_length_cexpression (stmt.collection); - - // store array length for use by _vala_array_free - ccode.add_assignment (get_variable_cexpression (get_array_length_cname (get_local_cname (collection_backup), 1)), array_len); - - 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, true); diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala index 95cbcaf97..3e7a5ee03 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) { var tuple = (Tuple) left; diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index 84f6a7437..9075a6cbd 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 955b23f66..35282981c 100644 --- a/vala/valacodebuilder.vala +++ b/vala/valacodebuilder.vala @@ -27,19 +27,16 @@ public class Vala.CodeBuilder { public Statement insert_statement; public Block insert_block; public ArrayList statement_stack = new ArrayList (); - public ArrayList check_nodes = new ArrayList (); + public ArrayList decl_nodes = new ArrayList (); public SourceReference source_reference; public CodeBuilder (CodeContext context, Statement insert_statement, SourceReference source_reference) { - current_block = new Block (source_reference); - insert_statement = insert_statement; - 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 +47,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 () { @@ -227,7 +225,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/valacodetransformer.vala b/vala/valacodetransformer.vala index 22d1b1ad5..064165580 100644 --- a/vala/valacodetransformer.vala +++ b/vala/valacodetransformer.vala @@ -365,7 +365,65 @@ public class Vala.CodeTransformer : CodeVisitor { } public override void visit_foreach_statement (ForeachStatement stmt) { - stmt.accept_children (this); + push_builder (new CodeBuilder (context, stmt, stmt.source_reference)); + 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 + b.open_for (null, expression (@"$collection != null"), expression (@"$collection = $collection.next")); + stmt.element_variable.initializer = expression (@"$collection.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 (); + + var parent_block = context.analyzer.get_current_block (stmt); + context.analyzer.replaced_nodes.add (stmt); + parent_block.replace_statement (stmt, new EmptyStatement (stmt.source_reference)); + + stmt.body.checked = false; + b.check (this); + pop_builder (); } public override void visit_break_statement (BreakStatement stmt) { @@ -426,7 +484,7 @@ public class Vala.CodeTransformer : CodeVisitor { var local = new LocalVariable (expr.value_type, expr.get_temp_name (), null, expr.source_reference); var decl = new DeclarationStatement (local, expr.source_reference); - expr.insert_statement (context.analyzer.get_insert_block (expr), decl); + expr.insert_statement (context.analyzer.get_current_block (expr), decl); var temp_access = SemanticAnalyzer.create_temp_access (local, expr.target_type); @@ -439,7 +497,7 @@ public class Vala.CodeTransformer : CodeVisitor { // otherwise there will be scoping issues in the var block = context.analyzer.get_current_block (expr); block.remove_local_variable (local); - context.analyzer.get_insert_block (expr).add_local_variable (local); + context.analyzer.get_current_block (expr).add_local_variable (local); context.analyzer.replaced_nodes.add (expr); old_parent_node.replace_expression (expr, temp_access); @@ -453,7 +511,7 @@ public class Vala.CodeTransformer : CodeVisitor { var local = new LocalVariable (expr.value_type, expr.get_temp_name (), null, expr.source_reference); var decl = new DeclarationStatement (local, expr.source_reference); - expr.insert_statement (context.analyzer.get_insert_block (expr), decl); + expr.insert_statement (context.analyzer.get_current_block (expr), decl); check (decl); var true_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, expr.true_expression.source_reference), expr.true_expression, AssignmentOperator.SIMPLE, expr.true_expression.source_reference), expr.true_expression.source_reference); @@ -465,7 +523,7 @@ public class Vala.CodeTransformer : CodeVisitor { false_block.add_statement (false_stmt); var if_stmt = new IfStatement (expr.condition, true_block, false_block, expr.source_reference); - expr.insert_statement (context.analyzer.get_insert_block (expr), if_stmt); + expr.insert_statement (context.analyzer.get_current_block (expr), if_stmt); check (if_stmt); var ma = new MemberAccess.simple (local.name, expr.source_reference); diff --git a/vala/valaforeachstatement.vala b/vala/valaforeachstatement.vala index ada291ccd..acade94b2 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; set; } + public ForeachIteration foreach_iteration { get; private set; } /** - * Specifies the declarator for the generated collection variable. - */ - public LocalVariable collection_variable { get; set; } - - /** - * Specifies the declarator for the generated iterator variable. + * Specifies the declarator for the generated element variable. */ - public LocalVariable iterator_variable { get; set; } + public LocalVariable element_variable { get; 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); + } 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)); } 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); } 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)) { + 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) { @@ -268,13 +257,7 @@ public class Vala.ForeachStatement : Block { 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 ())); @@ -308,20 +291,10 @@ public class Vala.ForeachStatement : Block { 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)); - } 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; + foreach_iteration = ForeachIteration.NEXT_GET; } - checked = false; - return base.check (context); + return true; } bool analyze_element_type (DataType element_type) { @@ -342,41 +315,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 collection, SourceReference? source_reference = null) { if (source_reference == null) { source_reference = this.source_reference; @@ -386,20 +324,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); } @@ -407,3 +334,13 @@ public class Vala.ForeachStatement : Block { collection.add (element_variable); } } + +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 4f30f5b84..2e8e4efac 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -495,7 +495,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); // don't set initializer earlier as this changes parent_node and parent_statement @@ -507,7 +507,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 3f3388851..e3f178acf 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -232,14 +232,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);