[vala/wip/transform: 50/139] Move ConditionalExpression transformation into the code transformer



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

    Move ConditionalExpression transformation into the code transformer

 vala/valacodetransformer.vala       |   28 ++++++++++++++
 vala/valaconditionalexpression.vala |   68 +++++++++--------------------------
 vala/valaflowanalyzer.vala          |   50 ++++++++++++++++++++++++-
 3 files changed, 93 insertions(+), 53 deletions(-)
---
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 893bb18..19ef10a 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 4a3d139..af1dbf7 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) {
@@ -104,6 +106,18 @@ public class Vala.ConditionalExpression : Expression {
                return condition.is_accessible (sym) && true_expression.is_accessible (sym) && 
false_expression.is_accessible (sym);
        }
 
+       public override void get_defined_variables (Collection<Variable> collection) {
+               condition.get_defined_variables (collection);
+               true_expression.get_defined_variables (collection);
+               false_expression.get_defined_variables (collection);
+       }
+
+       public override void get_used_variables (Collection<Variable> collection) {
+               condition.get_used_variables (collection);
+               true_expression.get_used_variables (collection);
+               false_expression.get_used_variables (collection);
+       }
+
        public override bool check (CodeContext context) {
                if (checked) {
                        return !error;
@@ -117,43 +131,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)) {
@@ -166,28 +151,9 @@ public class Vala.ConditionalExpression : Expression {
 
                value_type.value_owned = (true_expression.value_type.value_owned || 
false_expression.value_type.value_owned);
 
-               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 e616a8c..373586a 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -1191,12 +1191,58 @@ 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 ();
+                       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 ();
+                       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 ();
+                       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]