[vala/wip/transform-ast: 8/24] Move WhileStatement transformation into the code transformer



commit 49eb6145a28fb6cb40a17f4edf533be1ce107a7b
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Aug 30 12:43:41 2011 +0200

    Move WhileStatement transformation into the code transformer

 codegen/valaccodetransformer.vala | 20 +++++++++++++++
 vala/valaflowanalyzer.vala        | 51 +++++++++++++++++++++++++++++++++++++++
 vala/valawhilestatement.vala      | 33 ++++++++++++-------------
 3 files changed, 86 insertions(+), 18 deletions(-)
---
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
index bbc3c84ad..9ce39209a 100644
--- a/codegen/valaccodetransformer.vala
+++ b/codegen/valaccodetransformer.vala
@@ -61,6 +61,26 @@ public class Vala.CCodeTransformer : CodeTransformer {
                local.accept_children (this);
        }
 
+       public override void visit_while_statement (WhileStatement stmt) {
+               // convert to simple loop
+               begin_replace_statement (stmt);
+
+               if (!stmt.condition.is_always_false ()) {
+                       b.open_loop ();
+                       if (!stmt.condition.is_always_true ()) {
+                               var cond = expression (@"!$(stmt.condition)");
+                               b.open_if (cond);
+                               b.add_break ();
+                               b.close ();
+                       }
+                       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/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala
index ea0df7a83..acce8e22f 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -740,6 +740,57 @@ public class Vala.FlowAnalyzer : CodeVisitor {
                jump_stack.remove_at (jump_stack.size - 1);
        }
 
+       public override void visit_while_statement (WhileStatement stmt) {
+               if (unreachable (stmt)) {
+                       return;
+               }
+
+               var loop_block = new BasicBlock ();
+               all_basic_blocks.add (loop_block);
+               jump_stack.add (new JumpTarget.continue_target (loop_block));
+               var after_loop_block = new BasicBlock ();
+               all_basic_blocks.add (after_loop_block);
+               jump_stack.add (new JumpTarget.break_target (after_loop_block));
+
+               current_block.connect (loop_block);
+               current_block = loop_block;
+
+               // condition
+               loop_block.add_node (stmt.condition);
+               handle_errors (stmt.condition);
+
+               if (stmt.condition.is_always_false ()) {
+                       mark_unreachable ();
+               } else {
+                       current_block = new BasicBlock ();
+                       all_basic_blocks.add (current_block);
+                       loop_block.connect (current_block);
+               }
+
+               if (!stmt.condition.is_always_true ()) {
+                       loop_block.connect (after_loop_block);
+               }
+
+               // loop block
+               stmt.body.accept (this);
+               // end of loop block reachable?
+               if (current_block != null) {
+                       current_block.connect (loop_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_foreach_statement (ForeachStatement stmt) {
                if (unreachable (stmt)) {
                        return;
diff --git a/vala/valawhilestatement.vala b/vala/valawhilestatement.vala
index 161252219..75db4b96c 100644
--- a/vala/valawhilestatement.vala
+++ b/vala/valawhilestatement.vala
@@ -94,28 +94,25 @@ public class Vala.WhileStatement : CodeNode, Statement {
 
                checked = true;
 
-               // convert to simple loop
-
-               if (condition.is_always_true ()) {
-                       // do not generate if block if condition is always true
-               } else if (condition.is_always_false ()) {
-                       // do not generate if block if condition is always false
-                       body.insert_statement (0, new BreakStatement (condition.source_reference));
-               } else {
-                       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.target_type = context.analyzer.bool_type.copy ();
+
+               condition.check (context);
 
-               var loop = new Loop (body, source_reference);
+               if (condition.error) {
+                       /* if there was an error in the condition, skip this check */
+                       error = true;
+                       return false;
+               }
 
-               unowned Block parent_block = (Block) parent_node;
-               parent_block.replace_statement (this, loop);
+               if (condition.value_type == null || !condition.value_type.compatible 
(context.analyzer.bool_type)) {
+                       error = true;
+                       Report.error (condition.source_reference, "Condition must be boolean");
+                       return false;
+               }
 
-               if (!loop.check (context)) {
+               if (!body.check (context)) {
                        error = true;
+                       return false;
                }
 
                return !error;


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