Commit fef10859 authored by Jürg Billeter's avatar Jürg Billeter

Convert for loops into simple loops

parent a71e6e0d
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -153,7 +153,7 @@ public class Gee.HashMap<K,V> : CollectionObject, Map<K,V> {
for (int i = 0; i < _array_size; i++) {
Node<K,V> node;
Node<K,V> next;
Node<K,V> 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;
......
......@@ -137,7 +137,7 @@ public class Gee.HashSet<G> : CollectionObject, Iterable<G>, Collection<G>, Set<
for (int i = 0; i < _array_size; i++) {
Node<G> node;
Node<G> next;
Node<G> 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;
......
......@@ -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;
......
/* 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;
......
......@@ -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);
}
......
......@@ -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;
......
/* 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);
}
}
......@@ -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);
}
}
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment