[vala] Convert for loops into simple loops



commit fef10859ae29c524cac6a7388759f02e26df160d
Author: Jürg Billeter <j bitron ch>
Date:   Sat Jun 6 17:04:02 2009 +0200

    Convert for loops into simple loops
---
 codegen/valaccodebasemodule.vala        |    2 +-
 codegen/valaccodecontrolflowmodule.vala |   26 --------
 codegen/valaccodegenerator.vala         |    4 -
 codegen/valaccodemodule.vala            |    4 -
 gee/hashmap.vala                        |    2 +-
 gee/hashset.vala                        |    2 +-
 vala/valabinaryexpression.vala          |    4 -
 vala/valaconditionalexpression.vala     |    6 +--
 vala/valaexpression.vala                |   10 ---
 vala/valaflowanalyzer.vala              |   55 -----------------
 vala/valaforstatement.vala              |   98 +++++++++---------------------
 vala/valamethodcall.vala                |    5 --
 vala/valanullchecker.vala               |    6 --
 13 files changed, 34 insertions(+), 190 deletions(-)

diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala
index 9b46954..8073265 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 2dc23b1..b0c84c0 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 699d59c..f66e6dc 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 9d263e0..1743d2e 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 67b08ba..c152b7b 100644
--- a/gee/hashmap.vala
+++ b/gee/hashmap.vala
@@ -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;
diff --git a/gee/hashset.vala b/gee/hashset.vala
index a5a9805..712fd8d 100644
--- a/gee/hashset.vala
+++ b/gee/hashset.vala
@@ -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;
diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala
index cbfb132..54f5890 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 191d0fc..f521bc8 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 de3824f..ab73c4d 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 5d824fa..cf093e2 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 bdc048a..38e79bc 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 450f187..74fb2f8 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 bf9c0dc..8566fb7 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);
 



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