[vala/wip/transform: 8/52] Move ForStatement transformation into the code transformer



commit aecba26ac5d7e738dd0e2769fb18b2e5249ddda5
Author: Luca Bruno <lucabru src gnome org>
Date:   Wed Aug 31 10:51:08 2011 +0200

    Move ForStatement transformation into the code transformer

 vala/valacodetransformer.vala |   44 +++++++++++++++++++++++++++-
 vala/valaflowanalyzer.vala    |   64 ++++++++++++++++++++++++++++++++++++++++
 vala/valaforstatement.vala    |   65 ++++++++++++++++------------------------
 3 files changed, 133 insertions(+), 40 deletions(-)
---
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index fe06ba5..3a472af 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -244,7 +244,49 @@ public class Vala.CodeTransformer : CodeVisitor {
 	}
 
 	public override void visit_for_statement (ForStatement stmt) {
-		stmt.accept_children (this);
+		// convert to simple loop
+
+		var block = new Block (stmt.source_reference);
+
+		// initializer
+		foreach (var init_expr in stmt.get_initializer ()) {
+			block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference));
+		}
+
+		// do not generate if block if condition is always true
+		if (stmt.condition == null || always_true (stmt.condition)) {
+		} else if (always_false (stmt.condition)) {
+			// do not generate if block if condition is always false
+			stmt.body.insert_statement (0, new BreakStatement (stmt.condition.source_reference));
+		} else {
+			// condition
+			var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.condition.source_reference);
+			var true_block = new Block (stmt.condition.source_reference);
+			true_block.add_statement (new BreakStatement (stmt.condition.source_reference));
+			var if_stmt = new IfStatement (if_condition, true_block, null, stmt.condition.source_reference);
+			stmt.body.insert_statement (0, if_stmt);
+		}
+
+		// iterator
+		var first_local = new LocalVariable (context.analyzer.bool_type.copy (), stmt.get_temp_name (), new BooleanLiteral (true, stmt.source_reference), stmt.source_reference);
+		block.add_statement (new DeclarationStatement (first_local, stmt.source_reference));
+
+		var iterator_block = new Block (stmt.source_reference);
+		foreach (var it_expr in stmt.get_iterator ()) {
+			iterator_block.add_statement (new ExpressionStatement (it_expr, it_expr.source_reference));
+		}
+
+		var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, stmt.source_reference), stmt.source_reference), iterator_block, null, stmt.source_reference);
+		stmt.body.insert_statement (0, first_if);
+		stmt.body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, stmt.source_reference), new BooleanLiteral (false, stmt.source_reference), AssignmentOperator.SIMPLE, stmt.source_reference), stmt.source_reference));
+
+		block.add_statement (new Loop (stmt.body, stmt.source_reference));
+
+		var parent_block = (Block) stmt.parent_node;
+		parent_block.replace_statement (stmt, block);
+
+		stmt.body.checked = false;
+		check (block);
 	}
 
 	public override void visit_foreach_statement (ForeachStatement stmt) {
diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index 0388330..df895f0 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -778,6 +778,70 @@ 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;
+		}
+
+		var outer_block = new BasicBlock ();
+		foreach (var init_expr in stmt.get_initializer ()) {
+			outer_block.add_node (init_expr);
+		}
+
+		var iterator_block = new BasicBlock ();
+		foreach (var it_expr in stmt.get_iterator ()) {
+			iterator_block.add_node (it_expr);
+		}
+
+		var loop_block = new BasicBlock ();
+
+		var after_loop_block = new BasicBlock ();
+
+		jump_stack.add (new JumpTarget.continue_target (iterator_block));
+		jump_stack.add (new JumpTarget.break_target (after_loop_block));
+
+		current_block.connect (outer_block);
+		outer_block.connect (loop_block);
+		current_block = loop_block;
+
+		// condition
+		if (stmt.condition != null) {
+			loop_block.add_node (stmt.condition);
+			handle_errors (stmt.condition);
+
+			if (always_false (stmt.condition)) {
+				mark_unreachable ();
+			} else {
+				current_block = new BasicBlock ();
+				loop_block.connect (current_block);
+			}
+
+			if (!always_true (stmt.condition)) {
+				loop_block.connect (after_loop_block);
+			}
+		}
+
+		// loop block
+		stmt.body.accept (this);
+		// end of loop block reachable?
+		if (current_block != null) {
+			current_block.connect (iterator_block);
+		}
+
+		// after loop block reachable?
+		if (after_loop_block.get_predecessors ().size == 0) {
+			// after loop block not reachable
+			mark_unreachable ();
+		} else {
+			// after loop block reachable
+			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_do_statement (DoStatement stmt) {
 		if (unreachable (stmt)) {
 			return;
diff --git a/vala/valaforstatement.vala b/vala/valaforstatement.vala
index 555dc62..de1e05a 100644
--- a/vala/valaforstatement.vala
+++ b/vala/valaforstatement.vala
@@ -136,58 +136,45 @@ public class Vala.ForStatement : CodeNode, Statement {
 		body.accept (visitor);
 	}
 
-	bool always_true (Expression condition) {
-		var literal = condition as BooleanLiteral;
-		return (literal != null && literal.value);
-	}
-
-	bool always_false (Expression condition) {
-		var literal = condition as BooleanLiteral;
-		return (literal != null && !literal.value);
-	}
-
 	public override bool check (CodeContext context) {
-		// convert to simple loop
+		if (checked) {
+			return !error;
+		}
 
-		var block = new Block (source_reference);
+		checked = true;
 
 		// initializer
 		foreach (var init_expr in initializer) {
-			block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference));
+			if (!init_expr.check (context)) {
+				error = true;
+			}
 		}
 
-		// do not generate if block if condition is always true
-		if (condition == null || always_true (condition)) {
-		} else if (always_false (condition)) {
-			// do not generate if block if condition is always false
-			body.insert_statement (0, new BreakStatement (condition.source_reference));
-		} else {
-			// 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);
+		// condition
+		if (condition != null) {
+			condition.target_type = context.analyzer.bool_type.copy ();
+			if (!condition.check (context)) {
+				error = true;
+			}
+
+			if (condition.value_type == null || !condition.value_type.compatible (context.analyzer.bool_type)) {
+				error = true;
+				Report.error (condition.source_reference, "Condition must be boolean");
+			}
 		}
 
 		// iterator
-		var first_local = new LocalVariable (context.analyzer.bool_type.copy (), get_temp_name (), new BooleanLiteral (true, source_reference), source_reference);
-		block.add_statement (new DeclarationStatement (first_local, source_reference));
-
-		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));
+			if (!it_expr.check (context)) {
+				error = true;
+			}
 		}
 
-		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));
-
-		block.add_statement (new Loop (body, source_reference));
-
-		var parent_block = (Block) parent_node;
-		parent_block.replace_statement (this, block);
+		// body
+		if (!body.check (context)) {
+			error = true;
+		}
 
-		return block.check (context);
+		return !error;
 	}
 }



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