From: Luca Bruno Date: Tue, 27 Dec 2011 18:07:31 +0000 (+0100) Subject: Move ConditionalExpression transformation into the code transformer X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=da4d8ace0e9a74b48b93b86973e44705a94cb0e3;p=thirdparty%2Fvala.git Move ConditionalExpression transformation into the code transformer --- diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala index 1be21bb2e..eaff508b4 100644 --- a/vala/valacodetransformer.vala +++ b/vala/valacodetransformer.vala @@ -371,4 +371,32 @@ public class Vala.CodeTransformer : CodeVisitor { } } } + + public override void visit_conditional_expression (ConditionalExpression expr) { + // convert to if statement + + var local = new LocalVariable (expr.value_type, expr.get_temp_name (), null, expr.source_reference); + var decl = new DeclarationStatement (local, expr.source_reference); + expr.insert_statement (context.analyzer.get_insert_block (expr), decl); + check (decl); + + var true_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, expr.true_expression.source_reference), expr.true_expression, AssignmentOperator.SIMPLE, expr.true_expression.source_reference), expr.true_expression.source_reference); + var true_block = new Block (expr.true_expression.source_reference); + true_block.add_statement (true_stmt); + + var false_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, expr.false_expression.source_reference), expr.false_expression, AssignmentOperator.SIMPLE, expr.false_expression.source_reference), expr.false_expression.source_reference); + var false_block = new Block (expr.false_expression.source_reference); + false_block.add_statement (false_stmt); + + var if_stmt = new IfStatement (expr.condition, true_block, false_block, expr.source_reference); + expr.insert_statement (context.analyzer.get_insert_block (expr), if_stmt); + check (if_stmt); + + var ma = new MemberAccess.simple (local.name, expr.source_reference); + ma.formal_target_type = expr.formal_target_type; + ma.target_type = expr.target_type; + + expr.parent_node.replace_expression (expr, ma); + check (ma); + } } diff --git a/vala/valaconditionalexpression.vala b/vala/valaconditionalexpression.vala index b6884f616..72f42d195 100644 --- a/vala/valaconditionalexpression.vala +++ b/vala/valaconditionalexpression.vala @@ -85,9 +85,11 @@ public class Vala.ConditionalExpression : Expression { } public override void accept (CodeVisitor visitor) { - visitor.visit_conditional_expression (this); + // FIXME: temporary workaround to keep alive the object + var self = this; + visitor.visit_conditional_expression (self); - visitor.visit_expression (this); + visitor.visit_expression (self); } public override void accept_children (CodeVisitor visitor) { @@ -151,43 +153,14 @@ public class Vala.ConditionalExpression : Expression { return false; } - // convert ternary expression into if statement - // required for flow analysis and exception handling - - string temp_name = get_temp_name (); - true_expression.target_type = target_type; false_expression.target_type = target_type; - var local = new LocalVariable (null, temp_name, null, source_reference); - var decl = new DeclarationStatement (local, source_reference); - - var true_local = new LocalVariable (null, temp_name, true_expression, true_expression.source_reference); - var true_block = new Block (true_expression.source_reference); - var true_decl = new DeclarationStatement (true_local, true_expression.source_reference); - true_block.add_statement (true_decl); - - var false_local = new LocalVariable (null, temp_name, false_expression, false_expression.source_reference); - var false_block = new Block (false_expression.source_reference); - var false_decl = new DeclarationStatement (false_local, false_expression.source_reference); - false_block.add_statement (false_decl); - - var if_stmt = new IfStatement (condition, true_block, false_block, source_reference); - - insert_statement (context.analyzer.get_insert_block (this), decl); - insert_statement (context.analyzer.get_insert_block (this), if_stmt); - - if (!if_stmt.check (context) || true_expression.error || false_expression.error) { + if (!condition.check (context) || !true_expression.check (context) || !false_expression.check (context)) { error = true; return false; } - true_expression = true_local.initializer; - false_expression = false_local.initializer; - - true_block.remove_local_variable (true_local); - false_block.remove_local_variable (false_local); - if (false_expression.value_type.compatible (true_expression.value_type)) { value_type = true_expression.value_type.copy (); } else if (true_expression.value_type.compatible (false_expression.value_type)) { @@ -202,28 +175,9 @@ public class Vala.ConditionalExpression : Expression { value_type.floating_reference = false; value_type.check (context); - local.variable_type = value_type; - decl.check (context); - true_expression.target_type = value_type; false_expression.target_type = value_type; - var true_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, true_expression.source_reference), true_expression, AssignmentOperator.SIMPLE, true_expression.source_reference), true_expression.source_reference); - - var false_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, false_expression.source_reference), false_expression, AssignmentOperator.SIMPLE, false_expression.source_reference), false_expression.source_reference); - - true_block.replace_statement (true_decl, true_stmt); - false_block.replace_statement (false_decl, false_stmt); - true_stmt.check (context); - false_stmt.check (context); - - var ma = new MemberAccess.simple (local.name, source_reference); - ma.formal_target_type = formal_target_type; - ma.target_type = target_type; - - parent_node.replace_expression (this, ma); - ma.check (context); - return true; } } diff --git a/vala/valaflowanalyzer.vala b/vala/valaflowanalyzer.vala index a1cbcb24d..b21707e88 100644 --- a/vala/valaflowanalyzer.vala +++ b/vala/valaflowanalyzer.vala @@ -1258,12 +1258,61 @@ public class Vala.FlowAnalyzer : CodeVisitor { } public override void visit_expression (Expression expr) { - // lambda expression is handled separately - if (!(expr is LambdaExpression)) { + // lambda expression and conditional expression are handled separately + // an expression can be unreachable due to a conditional expression + if (!(expr is LambdaExpression) && !(expr is ConditionalExpression) && !unreachable (expr)) { expr.accept_children (this); } } + public override void visit_conditional_expression (ConditionalExpression expr) { + if (unreachable (expr)) { + return; + } + + // condition + current_block.add_node (expr.condition); + handle_errors (expr.condition); + + // true block + var last_block = current_block; + if (always_false (expr.condition)) { + mark_unreachable (); + } else { + current_block = new BasicBlock (); + all_basic_blocks.add (current_block); + last_block.connect (current_block); + } + expr.true_expression.accept (this); + + // false block + var last_true_block = current_block; + if (always_true (expr.condition)) { + mark_unreachable (); + } else { + current_block = new BasicBlock (); + all_basic_blocks.add (current_block); + last_block.connect (current_block); + } + if (expr.false_expression != null) { + expr.false_expression.accept (this); + } + + // after if/else + var last_false_block = current_block; + // reachable? + if (last_true_block != null || last_false_block != null) { + current_block = new BasicBlock (); + all_basic_blocks.add (current_block); + if (last_true_block != null) { + last_true_block.connect (current_block); + } + if (last_false_block != null) { + last_false_block.connect (current_block); + } + } + } + private bool unreachable (CodeNode node) { if (current_block == null) { node.unreachable = true;