[vala/staging] Move ConditionalExpression transformation into the CCodeTransformer



commit 820a11b6190f37eae53fb0e2cbe28f5627ae6796
Author: Luca Bruno <lucabru src gnome org>
Date:   Tue Dec 27 19:07:31 2011 +0100

    Move ConditionalExpression transformation into the CCodeTransformer

 codegen/valaccodetransformer.vala   | 18 +++++++++++++
 vala/valaconditionalexpression.vala | 50 +---------------------------------
 vala/valaflowanalyzer.vala          | 53 +++++++++++++++++++++++++++++++++++--
 3 files changed, 70 insertions(+), 51 deletions(-)
---
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
index 4e31edcda..3a9c77235 100644
--- a/codegen/valaccodetransformer.vala
+++ b/codegen/valaccodetransformer.vala
@@ -166,4 +166,22 @@ public class Vala.CCodeTransformer : CodeTransformer {
 
                base.visit_method_call (expr);
        }
+
+       public override void visit_conditional_expression (ConditionalExpression expr) {
+               // convert to if statement
+               Expression replacement = null;
+               var formal_target_type = copy_type (expr.target_type);
+               var target_type = copy_type (expr.target_type);
+               begin_replace_expression (expr);
+
+               var result = b.add_temp_declaration (expr.value_type);
+               statements (@"if ($(expr.condition)) {
+                                       $result = $(expr.true_expression);
+                                       } else {
+                                       $result = $(expr.false_expression);
+                                       }");
+
+               replacement = return_temp_access (result, expr.value_type, target_type, formal_target_type);
+               end_replace_expression (replacement);
+       }
 }
diff --git a/vala/valaconditionalexpression.vala b/vala/valaconditionalexpression.vala
index b6884f616..16e54064f 100644
--- a/vala/valaconditionalexpression.vala
+++ b/vala/valaconditionalexpression.vala
@@ -151,43 +151,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 +173,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;


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