From: Luca Bruno Date: Tue, 30 Aug 2011 11:42:39 +0000 (+0200) Subject: Move DoStatement transformation into the code transformer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c0bb1af03aaa1506bc319efac38774c94f2fe20;p=thirdparty%2Fvala.git Move DoStatement transformation into the code transformer Fixes https://gitlab.gnome.org/GNOME/vala/issues/27 --- diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala index 9ce39209a..520733239 100644 --- a/codegen/valaccodetransformer.vala +++ b/codegen/valaccodetransformer.vala @@ -81,6 +81,29 @@ public class Vala.CCodeTransformer : CodeTransformer { end_replace_statement (); } + public override void visit_do_statement (DoStatement stmt) { + // convert to simple loop + begin_replace_statement (stmt); + + b.open_loop (); + // do not generate variable and if block if condition is always true + if (!stmt.condition.is_always_true ()) { + var notfirst = b.add_temp_declaration (null, expression ("false")); + b.open_if (expression (notfirst)); + b.open_if (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.source_reference)); + b.add_break (); + b.close (); + b.add_else (); + b.add_assignment (expression (notfirst), expression ("true")); + b.close (); + } + stmt.body.checked = false; + b.add_statement (stmt.body); + b.close (); + + end_replace_statement (); + } + public override void visit_expression (Expression expr) { if (expr in context.analyzer.replaced_nodes) { return; diff --git a/vala/valadostatement.vala b/vala/valadostatement.vala index 80df5849e..23e8982da 100644 --- a/vala/valadostatement.vala +++ b/vala/valadostatement.vala @@ -94,46 +94,25 @@ public class Vala.DoStatement : CodeNode, Statement { checked = true; - // convert to simple loop + condition.target_type = context.analyzer.bool_type.copy (); - // do not generate variable and if block if condition is always true - if (condition.is_always_true ()) { - var loop = new Loop (body, source_reference); + condition.check (context); - unowned Block parent_block = (Block) parent_node; - parent_block.replace_statement (this, loop); - - if (!loop.check (context)) { - error = true; - } - - return !error; + if (condition.error) { + /* if there was an error in the condition, skip this check */ + error = true; + return false; } - var block = new Block (source_reference); - - 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 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); - - var condition_block = new Block (condition.source_reference); - condition_block.add_statement (if_stmt); - - var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, source_reference), source_reference), condition_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)); - - unowned Block parent_block = (Block) parent_node; - parent_block.replace_statement (this, block); + 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 (!block.check (context)) { + if (!body.check (context)) { error = true; + return false; } return !error; diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index acce8e22f..fc167a1ee 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -791,6 +791,57 @@ public class Vala.FlowAnalyzer : CodeVisitor { jump_stack.remove_at (jump_stack.size - 1); } + public override void visit_do_statement (DoStatement stmt) { + if (unreachable (stmt)) { + return; + } + + var body_block = new BasicBlock (); + all_basic_blocks.add (body_block); + current_block.connect (body_block); + current_block = body_block; + + 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)); + + // body + stmt.body.accept (this); + + // end of loop block reachable? + if (current_block != null) { + current_block.connect (loop_block); + } + + // condition + current_block = loop_block; + loop_block.add_node (stmt.condition); + handle_errors (stmt.condition); + + if (!stmt.condition.is_always_false ()) { + loop_block.connect (body_block); + } + + if (!stmt.condition.is_always_true ()) { + loop_block.connect (after_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;