]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Move ConditionalExpression transformation into the CCodeTransformer
authorLuca Bruno <lucabru@src.gnome.org>
Tue, 27 Dec 2011 18:07:31 +0000 (19:07 +0100)
committerRico Tzschichholz <ricotz@ubuntu.com>
Fri, 19 Apr 2019 13:25:24 +0000 (15:25 +0200)
codegen/valaccodetransformer.vala
vala/valaconditionalexpression.vala
vala/valaflowanalyzer.vala

index 4e31edcdab7577d5a9f463a8f137df1b1d5cdc33..3a9c772356dc02de289ba1d8a576c28cb570d744 100644 (file)
@@ -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);
+       }
 }
index b6884f616ac1943384385120ad14c610d4e70448..16e54064f2fcc069a6b1c7bf123953c3d4898f8c 100644 (file)
@@ -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;
        }
 }
index a0ad0b6159cd35202d83e34dd475b53a593183f1..8ebb5422b60439bde1d5327edfa8053acc9b8ccd 100644 (file)
@@ -1258,8 +1258,9 @@ 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);
                }
        }
@@ -1272,6 +1273,54 @@ public class Vala.FlowAnalyzer : CodeVisitor {
                handle_errors (expr);
        }
 
+       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;