From: Jürg Billeter Date: Sat, 6 Jun 2009 15:04:02 +0000 (+0200) Subject: Convert for loops into simple loops X-Git-Tag: 0.7.4~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fef10859ae29c524cac6a7388759f02e26df160d;p=thirdparty%2Fvala.git Convert for loops into simple loops --- diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index 9b46954fa..8073265e9 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -2232,7 +2232,7 @@ internal class Vala.CCodeBaseModule : CCodeModule { if (stop_at_loop) { if (b.parent_node is Loop || - b.parent_node is ForStatement || b.parent_node is ForeachStatement || + b.parent_node is ForeachStatement || b.parent_node is SwitchStatement) { return; } diff --git a/codegen/valaccodecontrolflowmodule.vala b/codegen/valaccodecontrolflowmodule.vala index 2dc23b14c..b0c84c095 100644 --- a/codegen/valaccodecontrolflowmodule.vala +++ b/codegen/valaccodecontrolflowmodule.vala @@ -227,32 +227,6 @@ internal class Vala.CCodeControlFlowModule : CCodeMethodModule { stmt.ccodenode = new CCodeWhileStatement (new CCodeConstant ("TRUE"), (CCodeStatement) stmt.body.ccodenode); } - public override void visit_for_statement (ForStatement stmt) { - stmt.accept_children (codegen); - - CCodeExpression ccondition = null; - if (stmt.condition != null) { - ccondition = (CCodeExpression) stmt.condition.ccodenode; - } - - var cfor = new CCodeForStatement (ccondition, (CCodeStatement) stmt.body.ccodenode); - stmt.ccodenode = cfor; - - foreach (Expression init_expr in stmt.get_initializer ()) { - cfor.add_initializer ((CCodeExpression) init_expr.ccodenode); - create_temp_decl (stmt, init_expr.temp_vars); - } - - foreach (Expression it_expr in stmt.get_iterator ()) { - cfor.add_iterator ((CCodeExpression) it_expr.ccodenode); - create_temp_decl (stmt, it_expr.temp_vars); - } - - if (stmt.condition != null) { - create_temp_decl (stmt, stmt.condition.temp_vars); - } - } - public override void visit_foreach_statement (ForeachStatement stmt) { stmt.element_variable.active = true; stmt.collection_variable.active = true; diff --git a/codegen/valaccodegenerator.vala b/codegen/valaccodegenerator.vala index 699d59cdf..f66e6dc6b 100644 --- a/codegen/valaccodegenerator.vala +++ b/codegen/valaccodegenerator.vala @@ -193,10 +193,6 @@ public class Vala.CCodeGenerator : CodeGenerator { head.visit_loop (stmt); } - public override void visit_for_statement (ForStatement stmt) { - head.visit_for_statement (stmt); - } - public override void visit_foreach_statement (ForeachStatement stmt) { head.visit_foreach_statement (stmt); } diff --git a/codegen/valaccodemodule.vala b/codegen/valaccodemodule.vala index 9d263e053..1743d2e75 100644 --- a/codegen/valaccodemodule.vala +++ b/codegen/valaccodemodule.vala @@ -172,10 +172,6 @@ public abstract class Vala.CCodeModule { next.visit_loop (stmt); } - public virtual void visit_for_statement (ForStatement stmt) { - next.visit_for_statement (stmt); - } - public virtual void visit_foreach_statement (ForeachStatement stmt) { next.visit_foreach_statement (stmt); } diff --git a/gee/hashmap.vala b/gee/hashmap.vala index 67b08ba91..c152b7b74 100644 --- a/gee/hashmap.vala +++ b/gee/hashmap.vala @@ -153,7 +153,7 @@ public class Gee.HashMap : CollectionObject, Map { for (int i = 0; i < _array_size; i++) { Node node; - Node next; + Node next = null; for (node = (owned) _nodes[i]; node != null; node = (owned) next) { next = (owned) node.next; uint hash_val = node.key_hash % new_array_size; diff --git a/gee/hashset.vala b/gee/hashset.vala index a5a98050c..712fd8d9a 100644 --- a/gee/hashset.vala +++ b/gee/hashset.vala @@ -137,7 +137,7 @@ public class Gee.HashSet : CollectionObject, Iterable, Collection, Set< for (int i = 0; i < _array_size; i++) { Node node; - Node next; + Node next = null; for (node = (owned) _nodes[i]; node != null; node = (owned) next) { next = (owned) node.next; uint hash_val = node.key_hash % new_array_size; diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index cbfb132e1..54f58906a 100644 --- a/vala/valabinaryexpression.vala +++ b/vala/valabinaryexpression.vala @@ -151,9 +151,6 @@ public class Vala.BinaryExpression : Expression { // for example, expressions in method contracts if (analyzer.current_symbol is Block && (operator == BinaryOperator.AND || operator == BinaryOperator.OR)) { - var old_insert_block = analyzer.insert_block; - analyzer.insert_block = prepare_condition_split (analyzer); - // convert conditional expression into if statement // required for flow analysis and exception handling @@ -185,7 +182,6 @@ public class Vala.BinaryExpression : Expression { error = true; return false; } - analyzer.insert_block = old_insert_block; var ma = new MemberAccess.simple (local.name, source_reference); ma.target_type = target_type; diff --git a/vala/valaconditionalexpression.vala b/vala/valaconditionalexpression.vala index 191d0fc0c..f521bc8f0 100644 --- a/vala/valaconditionalexpression.vala +++ b/vala/valaconditionalexpression.vala @@ -1,6 +1,6 @@ /* valaconditionalexpression.vala * - * Copyright (C) 2006-2008 Jürg Billeter + * Copyright (C) 2006-2009 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -111,9 +111,6 @@ public class Vala.ConditionalExpression : Expression { return false; } - var old_insert_block = analyzer.insert_block; - analyzer.insert_block = prepare_condition_split (analyzer); - // convert ternary expression into if statement // required for flow analysis and exception handling @@ -143,7 +140,6 @@ public class Vala.ConditionalExpression : Expression { if (!if_stmt.check (analyzer)) { return false; } - analyzer.insert_block = old_insert_block; true_expression = true_local.initializer; false_expression = false_local.initializer; diff --git a/vala/valaexpression.vala b/vala/valaexpression.vala index de3824f1b..ab73c4d88 100644 --- a/vala/valaexpression.vala +++ b/vala/valaexpression.vala @@ -102,16 +102,6 @@ public abstract class Vala.Expression : CodeNode { } } - public Block prepare_condition_split (SemanticAnalyzer analyzer) { - var for_stmt = parent_statement as ForStatement; - - if (for_stmt != null) { - return for_stmt.prepare_condition_split (analyzer); - } - - return analyzer.insert_block; - } - public void insert_statement (Block block, Statement stmt) { block.insert_before (parent_statement, stmt); } diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index 5d824fa49..cf093e2db 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -691,61 +691,6 @@ public class Vala.FlowAnalyzer : CodeVisitor { jump_stack.remove_at (jump_stack.size - 1); } - public override void visit_for_statement (ForStatement stmt) { - if (unreachable (stmt)) { - return; - } - - // initializer - foreach (Expression init_expr in stmt.get_initializer ()) { - current_block.add_node (init_expr); - handle_errors (init_expr); - } - - var iterator_block = new BasicBlock (); - jump_stack.add (new JumpTarget.continue_target (iterator_block)); - var after_loop_block = new BasicBlock (); - jump_stack.add (new JumpTarget.break_target (after_loop_block)); - - // condition - var condition_block = new BasicBlock (); - current_block.connect (condition_block); - current_block = condition_block; - if (stmt.condition != null) { - current_block.add_node (stmt.condition); - } - - if (stmt.condition != null) { - handle_errors (stmt.condition); - } - - // loop block - current_block = new BasicBlock (); - condition_block.connect (current_block); - stmt.body.accept (this); - - // iterator - // reachable? - if (current_block != null || iterator_block.get_predecessors ().size > 0) { - if (current_block != null) { - current_block.connect (iterator_block); - } - current_block = iterator_block; - foreach (Expression it_expr in stmt.get_iterator ()) { - current_block.add_node (it_expr); - handle_errors (it_expr); - } - current_block.connect (condition_block); - } - - // after loop - condition_block.connect (after_loop_block); - current_block = after_loop_block; - - jump_stack.remove_at (jump_stack.size - 1); - jump_stack.remove_at (jump_stack.size - 1); - } - public override void visit_foreach_statement (ForeachStatement stmt) { if (unreachable (stmt)) { return; diff --git a/vala/valaforstatement.vala b/vala/valaforstatement.vala index bdc048a52..38e79bc25 100644 --- a/vala/valaforstatement.vala +++ b/vala/valaforstatement.vala @@ -1,6 +1,6 @@ /* valaforstatement.vala * - * Copyright (C) 2006-2008 Jürg Billeter + * Copyright (C) 2006-2009 Jürg Billeter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -137,87 +137,49 @@ public class Vala.ForStatement : CodeNode, Statement { body.accept (visitor); } - public override void replace_expression (Expression old_node, Expression new_node) { - if (condition == old_node) { - condition = new_node; - return; - } - - for (int i = 0; i < initializer.size; i++) { - if (initializer[i] == old_node) { - initializer[i] = new_node; - return; - } - } - for (int i = 0; i < iterator.size; i++) { - if (iterator[i] == old_node) { - iterator[i] = new_node; - return; - } - } + bool always_true (Expression condition) { + var literal = condition as BooleanLiteral; + return (literal != null && literal.value); } public override bool check (SemanticAnalyzer analyzer) { - if (checked) { - return !error; - } - - checked = true; - - foreach (Expression init_expr in initializer) { - init_expr.check (analyzer); - } + // convert to simple loop - if (condition != null) { - condition.check (analyzer); - } + var block = new Block (source_reference); - foreach (Expression it_expr in iterator) { - it_expr.check (analyzer); + // initializer + foreach (var init_expr in initializer) { + block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference)); } - - body.check (analyzer); - if (condition != null && condition.error) { - /* if there was an error in the condition, skip this check */ - error = true; - return false; + // do not generate if block if condition is always true + if (condition != null && !always_true (condition)) { + // condition + var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference); + var true_block = new Block (condition.source_reference); + true_block.add_statement (new BreakStatement (condition.source_reference)); + var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference); + body.insert_statement (0, if_stmt); } - if (condition != null && !condition.value_type.compatible (analyzer.bool_type)) { - error = true; - Report.error (condition.source_reference, "Condition must be boolean"); - return false; - } + // iterator + var first_local = new LocalVariable (analyzer.bool_type.copy (), get_temp_name (), new BooleanLiteral (true, source_reference), source_reference); + block.add_statement (new DeclarationStatement (first_local, source_reference)); - if (condition != null) { - add_error_types (condition.get_error_types ()); + var iterator_block = new Block (source_reference); + foreach (var it_expr in iterator) { + iterator_block.add_statement (new ExpressionStatement (it_expr, it_expr.source_reference)); } - add_error_types (body.get_error_types ()); - foreach (Expression exp in get_initializer ()) { - add_error_types (exp.get_error_types ()); - } - foreach (Expression exp in get_iterator ()) { - add_error_types (exp.get_error_types ()); - } - - return !error; - } - - public Block prepare_condition_split (SemanticAnalyzer analyzer) { - // move condition into the loop body to allow split - // in multiple statements + var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, source_reference), source_reference), iterator_block, null, source_reference); + body.insert_statement (0, first_if); + body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, source_reference), new BooleanLiteral (false, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference)); - var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, condition, condition.source_reference); - var true_block = new Block (condition.source_reference); - true_block.add_statement (new BreakStatement (condition.source_reference)); - var if_stmt = new IfStatement (if_condition, true_block, null, condition.source_reference); - body.insert_statement (0, if_stmt); + block.add_statement (new Loop (body, source_reference)); - condition = new BooleanLiteral (true, source_reference); - condition.check (analyzer); + var parent_block = (Block) parent_node; + parent_block.replace_statement (this, block); - return body; + return block.check (analyzer); } } diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 450f187fb..74fb2f843 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -436,9 +436,6 @@ public class Vala.MethodCall : Expression { if (parent_node is LocalVariable || parent_node is ExpressionStatement) { // simple statements, no side effects after method call } else { - var old_insert_block = analyzer.insert_block; - analyzer.insert_block = prepare_condition_split (analyzer); - // store parent_node as we need to replace the expression in the old parent node later on var old_parent_node = parent_node; @@ -464,8 +461,6 @@ public class Vala.MethodCall : Expression { block.remove_local_variable (local); analyzer.insert_block.add_local_variable (local); - analyzer.insert_block = old_insert_block; - old_parent_node.replace_expression (this, temp_access); } } diff --git a/vala/valanullchecker.vala b/vala/valanullchecker.vala index bf9c0dcb3..8566fb72f 100644 --- a/vala/valanullchecker.vala +++ b/vala/valanullchecker.vala @@ -156,12 +156,6 @@ public class Vala.NullChecker : CodeVisitor { stmt.accept_children (this); } - public override void visit_for_statement (ForStatement stmt) { - stmt.accept_children (this); - - check_non_null (stmt.condition); - } - public override void visit_foreach_statement (ForeachStatement stmt) { stmt.accept_children (this);