]> git.ipfire.org Git - thirdparty/vala.git/commitdiff
Convert binary conditional expressions into if statements
authorJürg Billeter <j@bitron.ch>
Sat, 29 Nov 2008 17:25:51 +0000 (17:25 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Sat, 29 Nov 2008 17:25:51 +0000 (17:25 +0000)
2008-11-29  Jürg Billeter  <j@bitron.ch>

* vala/valaaddressofexpression.vala:
* vala/valaarraycreationexpression.vala:
* vala/valaassignment.vala:
* vala/valabaseaccess.vala:
* vala/valabinaryexpression.vala:
* vala/valacastexpression.vala:
* vala/valaconditionalexpression.vala:
* vala/valadostatement.vala:
* vala/valaelementaccess.vala:
* vala/valaexpression.vala:
* vala/valaforstatement.vala:
* vala/valainitializerlist.vala:
* vala/valalambdaexpression.vala:
* vala/valaliteral.vala:
* vala/valamemberaccess.vala:
* vala/valamethodcall.vala:
* vala/valaobjectcreationexpression.vala:
* vala/valaparenthesizedexpression.vala:
* vala/valapointerindirection.vala:
* vala/valapostfixexpression.vala:
* vala/valareferencetransferexpression.vala:
* vala/valasizeofexpression.vala:
* vala/valatuple.vala:
* vala/valatypecheck.vala:
* vala/valatypeofexpression.vala:
* vala/valaunaryexpression.vala:
* vala/valawhilestatement.vala:

Convert binary conditional expressions into if statements

svn path=/trunk/; revision=2085

28 files changed:
ChangeLog
vala/valaaddressofexpression.vala
vala/valaarraycreationexpression.vala
vala/valaassignment.vala
vala/valabaseaccess.vala
vala/valabinaryexpression.vala
vala/valacastexpression.vala
vala/valaconditionalexpression.vala
vala/valadostatement.vala
vala/valaelementaccess.vala
vala/valaexpression.vala
vala/valaforstatement.vala
vala/valainitializerlist.vala
vala/valalambdaexpression.vala
vala/valaliteral.vala
vala/valamemberaccess.vala
vala/valamethodcall.vala
vala/valaobjectcreationexpression.vala
vala/valaparenthesizedexpression.vala
vala/valapointerindirection.vala
vala/valapostfixexpression.vala
vala/valareferencetransferexpression.vala
vala/valasizeofexpression.vala
vala/valatuple.vala
vala/valatypecheck.vala
vala/valatypeofexpression.vala
vala/valaunaryexpression.vala
vala/valawhilestatement.vala

index e820029b7c75d6001cda8d4046f8387a1579073a..291be4b642ec00b03d7e869c09d470aa9a93301f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2008-11-29  Jürg Billeter  <j@bitron.ch>
+
+       * vala/valaaddressofexpression.vala:
+       * vala/valaarraycreationexpression.vala:
+       * vala/valaassignment.vala:
+       * vala/valabaseaccess.vala:
+       * vala/valabinaryexpression.vala:
+       * vala/valacastexpression.vala:
+       * vala/valaconditionalexpression.vala:
+       * vala/valadostatement.vala:
+       * vala/valaelementaccess.vala:
+       * vala/valaexpression.vala:
+       * vala/valaforstatement.vala:
+       * vala/valainitializerlist.vala:
+       * vala/valalambdaexpression.vala:
+       * vala/valaliteral.vala:
+       * vala/valamemberaccess.vala:
+       * vala/valamethodcall.vala:
+       * vala/valaobjectcreationexpression.vala:
+       * vala/valaparenthesizedexpression.vala:
+       * vala/valapointerindirection.vala:
+       * vala/valapostfixexpression.vala:
+       * vala/valareferencetransferexpression.vala:
+       * vala/valasizeofexpression.vala:
+       * vala/valatuple.vala:
+       * vala/valatypecheck.vala:
+       * vala/valatypeofexpression.vala:
+       * vala/valaunaryexpression.vala:
+       * vala/valawhilestatement.vala:
+
+       Convert binary conditional expressions into if statements
+
 2008-11-29  Jürg Billeter  <j@bitron.ch>
 
        * vala/valaflowanalyzer.vala:
index 4874a2b0a89dcb3c58fff0de2e8d4a494ee45493..be21b9572011b9b7454da58e3d18e89713b3fc6f 100644 (file)
@@ -97,4 +97,8 @@ public class Vala.AddressofExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
index 9ef841c549c37623d47f8d1c9a26a564d47bbf58..8e2f891d7d57bc9df14b105bcf41e79a4f22e181 100644 (file)
@@ -220,4 +220,13 @@ public class Vala.ArrayCreationExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression size in sizes) {
+                       if (!size.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return true;
+       }
 }
index d3ad077f70412b4c7ab6037f633349ef94a12373..026040b30b0a9363dd35437da0f20c5a1bb5dca9 100644 (file)
@@ -400,6 +400,10 @@ public class Vala.Assignment : Expression {
                }
                right.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               return left.in_single_basic_block () && right.in_single_basic_block ();
+       }
 }
        
 public enum Vala.AssignmentOperator {
index 1de0c7a7849928383edc627f8717d9e6644bdfda..7db98c878b930bbee82eaeecaff49406ba24942e 100644 (file)
@@ -88,4 +88,8 @@ public class Vala.BaseAccess : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index 1ba915d54ff1a801efeb636f1b4b93242650a86b..024ec9dcb52ec1f7ce9cc0592758f70a2155e87d 100644 (file)
@@ -145,6 +145,47 @@ public class Vala.BinaryExpression : Expression {
 
                checked = true;
 
+               if (operator == BinaryOperator.AND || operator == BinaryOperator.OR) {
+                       // convert conditional expression into if statement
+                       // required for flow analysis and exception handling
+
+                       var local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), null, source_reference);
+                       var decl = new DeclarationStatement (local, source_reference);
+                       decl.check (analyzer);
+
+                       var right_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, right.source_reference), right, AssignmentOperator.SIMPLE, right.source_reference), right.source_reference);
+
+                       var stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, left.source_reference), new BooleanLiteral ((operator == BinaryOperator.OR), left.source_reference), AssignmentOperator.SIMPLE, left.source_reference), left.source_reference);
+
+                       var true_block = new Block (source_reference);
+                       var false_block = new Block (source_reference);
+
+                       if (operator == BinaryOperator.AND) {
+                               true_block.add_statement (right_stmt);
+                               false_block.add_statement (stmt);
+                       } else {
+                               true_block.add_statement (stmt);
+                               false_block.add_statement (right_stmt);
+                       }
+
+                       var if_stmt = new IfStatement (left, true_block, false_block, source_reference);
+
+                       insert_statement ((Block) analyzer.current_symbol, decl);
+                       insert_statement ((Block) analyzer.current_symbol, if_stmt);
+
+                       if (!if_stmt.check (analyzer)) {
+                               return false;
+                       }
+
+                       var ma = new MemberAccess.simple (local.name, source_reference);
+                       ma.target_type = target_type;
+                       ma.check (analyzer);
+
+                       parent_node.replace_expression (this, ma);
+
+                       return true;
+               }
+
                if (!left.check (analyzer) || !right.check (analyzer)) {
                        /* if there were any errors in inner expressions, skip type check */
                        error = true;
@@ -260,14 +301,6 @@ public class Vala.BinaryExpression : Expression {
                        // integer type or flags type
 
                        value_type = left.value_type;
-               } else if (operator == BinaryOperator.AND
-                          || operator == BinaryOperator.OR) {
-                       if (!left.value_type.compatible (analyzer.bool_type) || !right.value_type.compatible (analyzer.bool_type)) {
-                               error = true;
-                               Report.error (source_reference, "Operands must be boolean");
-                       }
-
-                       value_type = analyzer.bool_type;
                } else if (operator == BinaryOperator.IN) {
                        if (left.value_type.compatible (analyzer.int_type)
                            && right.value_type.compatible (analyzer.int_type)) {
@@ -315,6 +348,14 @@ public class Vala.BinaryExpression : Expression {
                left.get_used_variables (collection);
                right.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               if (operator == BinaryOperator.AND
+                   || operator == BinaryOperator.OR) {
+                       return false;
+               }
+               return left.in_single_basic_block () && right.in_single_basic_block ();
+       }
 }
 
 public enum Vala.BinaryOperator {
index 4f94832ce54ef6dd59f3e0e7dda7e78e2bf8bc47..598b5a28db344ac49bc283f4a4bb47fdf01e9c4b 100644 (file)
@@ -131,4 +131,8 @@ public class Vala.CastExpression : Expression {
        public override void get_used_variables (Collection<LocalVariable> collection) {
                inner.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
index f53cd1a155063563aaf694e80898cabf9c169c64..ff798a6a03fe8fbbee9fb6b8a3b58da85b87db57 100644 (file)
@@ -113,6 +113,9 @@ public class Vala.ConditionalExpression : Expression {
                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);
@@ -124,6 +127,10 @@ public class Vala.ConditionalExpression : Expression {
                false_block.add_statement (false_decl);
 
                var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
+
+               insert_statement ((Block) analyzer.current_symbol, decl);
+               insert_statement ((Block) analyzer.current_symbol, if_stmt);
+
                if (!if_stmt.check (analyzer)) {
                        return false;
                }
@@ -146,8 +153,7 @@ public class Vala.ConditionalExpression : Expression {
 
                value_type.value_owned = (true_expression.value_type.value_owned || false_expression.value_type.value_owned);
 
-               var local = new LocalVariable (value_type, temp_name, null, source_reference);
-               var decl = new DeclarationStatement (local, source_reference);
+               local.variable_type = value_type;
                decl.check (analyzer);
 
                true_expression.target_type = value_type;
@@ -162,9 +168,6 @@ public class Vala.ConditionalExpression : Expression {
                true_block.replace_statement (true_decl, true_stmt);
                false_block.replace_statement (false_decl, false_stmt);
 
-               insert_statement ((Block) analyzer.current_symbol, decl);
-               insert_statement ((Block) analyzer.current_symbol, if_stmt);
-
                var ma = new MemberAccess.simple (local.name, source_reference);
                ma.target_type = target_type;
                ma.check (analyzer);
@@ -173,4 +176,8 @@ public class Vala.ConditionalExpression : Expression {
 
                return true;
        }
+
+       public override bool in_single_basic_block () {
+               return false;
+       }
 }
index 8700c883c09771909f9f412443e3b6b4f34d9625..443aca541624094836b92cee83f83e8219014a74 100644 (file)
@@ -94,6 +94,43 @@ public class Vala.DoStatement : CodeNode, Statement {
 
                checked = true;
 
+               if (!condition.in_single_basic_block ()) {
+                       /* move condition into the loop body to allow split
+                        * in multiple statements
+                        *
+                        * first = false;
+                        * do {
+                        *     if (first) {
+                        *         if (!condition) {
+                        *             break;
+                        *         }
+                        *     }
+                        *     first = true;
+                        *     ...
+                        * } while (true);
+                        */
+
+                       var first_local = new LocalVariable (new ValueType (analyzer.bool_type.data_type), get_temp_name (), new BooleanLiteral (false, source_reference), source_reference);
+                       var first_decl = new DeclarationStatement (first_local, source_reference);
+                       first_decl.check (analyzer);
+                       var block = (Block) analyzer.current_symbol;
+                       block.insert_before (this, first_decl);
+
+                       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 MemberAccess.simple (first_local.name, 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 (true, source_reference), AssignmentOperator.SIMPLE, source_reference), source_reference));
+
+                       condition = new BooleanLiteral (true, source_reference);
+               }
+
                body.check (analyzer);
 
                if (!condition.check (analyzer)) {
index 8475187637f8769b865a1d2e8173159855190c25..e6b4dc8b2119c14ef4b4928d1babe69755d29f59 100644 (file)
@@ -222,4 +222,13 @@ public class Vala.ElementAccess : Expression {
                        index.get_used_variables (collection);
                }
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression index in indices) {
+                       if (!index.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return container.in_single_basic_block ();
+       }
 }
index 11d43950a5b416127ce26a902e9dd0b270683a43..47fb7cdac145aa2226362f53446f4df7e2c95c6b 100644 (file)
@@ -105,4 +105,10 @@ public abstract class Vala.Expression : CodeNode {
        public void insert_statement (Block block, Statement stmt) {
                block.insert_before (parent_statement, stmt);
        }
+
+       /**
+        * Returns whether this expression is guaranteed to be part of a
+        * single basic block in the control flow graph.
+        */
+       public abstract bool in_single_basic_block ();
 }
index cf02aa726b3054b0e5bf14d60f93596f387ff6a7..ebd8de526747296ab09521d534e83e1e121f2f0e 100644 (file)
@@ -164,6 +164,20 @@ public class Vala.ForStatement : CodeNode, Statement {
 
                checked = true;
 
+
+               if (condition != null && !condition.in_single_basic_block ()) {
+                       // move condition into the loop body to allow split
+                       // in multiple statements
+
+                       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);
+                       body.insert_statement (0, if_stmt);
+
+                       condition = new BooleanLiteral (true, source_reference);
+               }
+
                foreach (Expression init_expr in initializer) {
                        init_expr.check (analyzer);
                }
index 4b10f160734e58fc111003bb6727cd4e086396a0..5284d08bcc6d8aa4f1d00c6c15e2541b0629518a 100644 (file)
@@ -170,4 +170,13 @@ public class Vala.InitializerList : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression initializer in initializers) {
+                       if (!initializer.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return true;
+       }
 }
index 52415a91591d209e88fb3408d4106b821d405f19..20a7fbef9706df1bd0071a7d0953e05aa4fe901e 100644 (file)
@@ -203,4 +203,8 @@ public class Vala.LambdaExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index 62f17a3af5aee0c9080b70afe21fbec6f57f677f..932f0f58c0453f2479d23ce4e4b7787c668f718f 100644 (file)
@@ -33,4 +33,8 @@ public abstract class Vala.Literal : Expression {
        public override bool is_pure () {
                return true;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index 031d66f6f383fafc3ddb77a2726b6b73cafd342a..2c59a6eb749454fa1923ac27b02928c2f80c1219 100644 (file)
@@ -551,4 +551,8 @@ public class Vala.MemberAccess : Expression {
                        collection.add (local);
                }
        }
+
+       public override bool in_single_basic_block () {
+               return inner == null || inner.in_single_basic_block ();
+       }
 }
index 984318923e8908ef31ad27f1631d3212236d2f1f..477198c921c2774f0a7eb6e4ae9b4ef5cfdb22ee 100644 (file)
@@ -422,4 +422,13 @@ public class Vala.MethodCall : Expression {
                        arg.get_used_variables (collection);
                }
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression arg in argument_list) {
+                       if (!arg.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return call.in_single_basic_block ();
+       }
 }
index 9fc43fd10ab4556f113eb40786fdafd85b70b3f8..5d64b05f81c4cf02926b9fea94472acc543ecce1 100644 (file)
@@ -372,4 +372,13 @@ public class Vala.ObjectCreationExpression : Expression {
                        arg.get_used_variables (collection);
                }
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression arg in argument_list) {
+                       if (!arg.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return true;
+       }
 }
index 2a29d933273a481037c73699f0a0437f4be234a2..e1c97d487039fc2039c7f8c1cb932c391324fde6 100644 (file)
@@ -112,4 +112,8 @@ public class Vala.ParenthesizedExpression : Expression {
        public override void get_used_variables (Collection<LocalVariable> collection) {
                inner.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
index 84f1b6e6f81915fa0fc7b78022895684a0f8cab7..f926c7a53773ff7ab12273ab9e594ca0cfae5467 100644 (file)
@@ -109,4 +109,8 @@ public class Vala.PointerIndirection : Expression {
        public override void get_used_variables (Collection<LocalVariable> collection) {
                inner.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
index 3ff4d6d69d59e9adaa79e209108d141ff4278780..e34365472348f0f8943665768aea49da05161818 100644 (file)
@@ -75,4 +75,8 @@ public class Vala.PostfixExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index dcf2e5369e7306f1aff9836de788bf72ca551573..fc83f1a0d71839b5465a579873629013647d58a5 100644 (file)
@@ -115,4 +115,8 @@ public class Vala.ReferenceTransferExpression : Expression {
        public override void get_used_variables (Collection<LocalVariable> collection) {
                inner.get_used_variables (collection);
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
index 673b16e9cef3943bfc97590829afd3997136c472..0000d2ced7fd5d7644c2614b730a4d2d7a4902bc 100644 (file)
@@ -82,4 +82,8 @@ public class Vala.SizeofExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index fc05984e8e0ef7645f9de3f436633755d791d184..16354f6075d02d5972670d134f822619d745ca67 100644 (file)
@@ -43,5 +43,14 @@ public class Vala.Tuple : Expression {
        public override bool is_pure () {
                return false;
        }
+
+       public override bool in_single_basic_block () {
+               foreach (Expression expr in expression_list) {
+                       if (!expr.in_single_basic_block ()) {
+                               return false;
+                       }
+               }
+               return true;
+       }
 }
 
index 2dee142f174a086a9c4134d6beb2270864b8c2a5..dea9708b468f23b130233fd974795c2ad069dbbe 100644 (file)
@@ -101,4 +101,8 @@ public class Vala.TypeCheck : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return expression.in_single_basic_block ();
+       }
 }
index 9331a8f399597cb51efff4b519abb8d5e3b12964..e18be52ae905e681d141f20a53097e0b8f7fa305 100644 (file)
@@ -84,4 +84,8 @@ public class Vala.TypeofExpression : Expression {
 
                return !error;
        }
+
+       public override bool in_single_basic_block () {
+               return true;
+       }
 }
index 9f478d8e94113d3856145b35816b08c9bf9d84cd..16260859ec8209586646eb0719f0b403cb9fe369 100644 (file)
@@ -241,6 +241,10 @@ public class Vala.UnaryExpression : Expression {
                        inner.get_used_variables (collection);
                }
        }
+
+       public override bool in_single_basic_block () {
+               return inner.in_single_basic_block ();
+       }
 }
 
 public enum Vala.UnaryOperator {
index 028538c0d01f7885223b37bc1ab6003f14f7b001..3a595256ab308a18c6af3fbe61732f693ac0a2be 100644 (file)
@@ -94,6 +94,19 @@ public class Vala.WhileStatement : CodeNode, Statement {
 
                checked = true;
 
+               if (!condition.in_single_basic_block ()) {
+                       // move condition into the loop body to allow split
+                       // in multiple statements
+
+                       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);
+                       body.insert_statement (0, if_stmt);
+
+                       condition = new BooleanLiteral (true, source_reference);
+               }
+
                condition.check (analyzer);
                
                body.check (analyzer);