From: Luca Bruno Date: Wed, 4 Jan 2012 17:38:38 +0000 (+0100) Subject: Move ForeachStatement transformation into the CCodeTransformer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9ef62fad8916ff69472ba3c0fb059ef5f485d4b8;p=thirdparty%2Fvala.git Move ForeachStatement transformation into the CCodeTransformer --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 2a6056ae8..84b3872d8 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -2144,7 +2144,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))); } } @@ -2443,7 +2443,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/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala index 3a9c77235..476a538c0 100644 --- a/codegen/valaccodetransformer.vala +++ b/codegen/valaccodetransformer.vala @@ -136,6 +136,86 @@ public class Vala.CCodeTransformer : CodeTransformer { end_replace_statement (); } + public override void visit_foreach_statement (ForeachStatement stmt) { + begin_replace_statement (stmt); + + 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: + var array_type = (ArrayType) stmt.collection.value_type.copy (); + array_type.fixed_length = false; + array_type.inline_allocated = false; + string collection; + string length; + // multidimensonal array + if (array_type.rank > 1) { + length = @"$(stmt.collection).length[0]"; + var dim = 1; + while (dim < array_type.rank) { + length += @" * $(stmt.collection).length[$dim]"; + dim++; + } + collection = b.add_temp_declaration (new ArrayType (array_type.element_type, 1, null), expression (@"($(array_type.element_type)[]) ($(stmt.collection))")); + } else { + collection = b.add_temp_declaration (array_type, stmt.collection); + length = @"$collection.length"; + } + var i = b.add_temp_declaration (array_type.length_type, expression ("0")); + b.open_for (null, expression (@"$i < $length"), expression (@"$i++")); + stmt.element_variable.initializer = expression (@"$collection[$i]"); + break; + case ForeachIteration.GVALUE_ARRAY: + // GValueArray + var collection = b.add_temp_declaration (null, expression (@"$(stmt.collection).values")); + var i = b.add_temp_declaration (null, expression ("0")); + b.open_for (null, expression (@"$i < $collection.length"), expression (@"$i++")); + stmt.element_variable.initializer = expression (@"$collection[$i]"); + break; + case ForeachIteration.GLIST: + // GList or GSList + var collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection); + var iter = b.add_temp_declaration (copy_type (stmt.collection.value_type, false, true), 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 collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection); + 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 collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection); + var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()")); + var temp = b.add_temp_declaration (copy_type (stmt.type_reference, null, true)); + b.open_while (expression (@"($temp = $iterator.next_value ()) != null")); + stmt.element_variable.initializer = expression (@"(!) $temp"); + break; + case ForeachIteration.NEXT_GET: + // iterator + next() + get() + var collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection); + 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 52ef6ae3b..710edba8b 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 42d291ecd..d6d0444d0 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_stack = new ArrayList (); - ArrayList check_nodes = new ArrayList (); + ArrayList decl_nodes = new ArrayList (); 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/valaforeachstatement.vala b/vala/valaforeachstatement.vala index ada291ccd..e341eeda7 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, 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,17 @@ 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)); - } 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) { + bool analyze_element_type (DataType element_type, bool get_owned) { // analyze element type if (type_reference == null) { // var type @@ -333,7 +306,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 +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 86ab41a36..1739e9030 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -504,7 +504,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 @@ -516,7 +516,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 03281b499..9e81b8396 100644 --- a/vala/valasemanticanalyzer.vala +++ b/vala/valasemanticanalyzer.vala @@ -240,14 +240,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);