diff options
author | Jürg Billeter <j@bitron.ch> | 2008-11-29 17:25:51 +0000 |
---|---|---|
committer | Jürg Billeter <juergbi@src.gnome.org> | 2008-11-29 17:25:51 +0000 |
commit | 9c112c985e1edafa2602416962702f185a5583a0 (patch) | |
tree | 00a87c40a46d3f07cf15797250d396d965d8006d /vala | |
parent | 44a1c2f3196261abbc0930f84df21fc877afd266 (diff) | |
download | vala-9c112c985e1edafa2602416962702f185a5583a0.tar.gz |
Convert binary conditional expressions into if statements
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
Diffstat (limited to 'vala')
27 files changed, 245 insertions, 13 deletions
diff --git a/vala/valaaddressofexpression.vala b/vala/valaaddressofexpression.vala index 4874a2b0a..be21b9572 100644 --- a/vala/valaaddressofexpression.vala +++ b/vala/valaaddressofexpression.vala @@ -97,4 +97,8 @@ public class Vala.AddressofExpression : Expression { return !error; } + + public override bool in_single_basic_block () { + return inner.in_single_basic_block (); + } } diff --git a/vala/valaarraycreationexpression.vala b/vala/valaarraycreationexpression.vala index 9ef841c54..8e2f891d7 100644 --- a/vala/valaarraycreationexpression.vala +++ b/vala/valaarraycreationexpression.vala @@ -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; + } } diff --git a/vala/valaassignment.vala b/vala/valaassignment.vala index d3ad077f7..026040b30 100644 --- a/vala/valaassignment.vala +++ b/vala/valaassignment.vala @@ -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 { diff --git a/vala/valabaseaccess.vala b/vala/valabaseaccess.vala index 1de0c7a78..7db98c878 100644 --- a/vala/valabaseaccess.vala +++ b/vala/valabaseaccess.vala @@ -88,4 +88,8 @@ public class Vala.BaseAccess : Expression { return !error; } + + public override bool in_single_basic_block () { + return true; + } } diff --git a/vala/valabinaryexpression.vala b/vala/valabinaryexpression.vala index 1ba915d54..024ec9dcb 100644 --- a/vala/valabinaryexpression.vala +++ b/vala/valabinaryexpression.vala @@ -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 { diff --git a/vala/valacastexpression.vala b/vala/valacastexpression.vala index 4f94832ce..598b5a28d 100644 --- a/vala/valacastexpression.vala +++ b/vala/valacastexpression.vala @@ -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 (); + } } diff --git a/vala/valaconditionalexpression.vala b/vala/valaconditionalexpression.vala index f53cd1a15..ff798a6a0 100644 --- a/vala/valaconditionalexpression.vala +++ b/vala/valaconditionalexpression.vala @@ -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; + } } diff --git a/vala/valadostatement.vala b/vala/valadostatement.vala index 8700c883c..443aca541 100644 --- a/vala/valadostatement.vala +++ b/vala/valadostatement.vala @@ -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)) { diff --git a/vala/valaelementaccess.vala b/vala/valaelementaccess.vala index 847518763..e6b4dc8b2 100644 --- a/vala/valaelementaccess.vala +++ b/vala/valaelementaccess.vala @@ -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 (); + } } diff --git a/vala/valaexpression.vala b/vala/valaexpression.vala index 11d43950a..47fb7cdac 100644 --- a/vala/valaexpression.vala +++ b/vala/valaexpression.vala @@ -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 (); } diff --git a/vala/valaforstatement.vala b/vala/valaforstatement.vala index cf02aa726..ebd8de526 100644 --- a/vala/valaforstatement.vala +++ b/vala/valaforstatement.vala @@ -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); } diff --git a/vala/valainitializerlist.vala b/vala/valainitializerlist.vala index 4b10f1607..5284d08bc 100644 --- a/vala/valainitializerlist.vala +++ b/vala/valainitializerlist.vala @@ -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; + } } diff --git a/vala/valalambdaexpression.vala b/vala/valalambdaexpression.vala index 52415a915..20a7fbef9 100644 --- a/vala/valalambdaexpression.vala +++ b/vala/valalambdaexpression.vala @@ -203,4 +203,8 @@ public class Vala.LambdaExpression : Expression { return !error; } + + public override bool in_single_basic_block () { + return true; + } } diff --git a/vala/valaliteral.vala b/vala/valaliteral.vala index 62f17a3af..932f0f58c 100644 --- a/vala/valaliteral.vala +++ b/vala/valaliteral.vala @@ -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; + } } diff --git a/vala/valamemberaccess.vala b/vala/valamemberaccess.vala index 031d66f6f..2c59a6eb7 100644 --- a/vala/valamemberaccess.vala +++ b/vala/valamemberaccess.vala @@ -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 (); + } } diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala index 984318923..477198c92 100644 --- a/vala/valamethodcall.vala +++ b/vala/valamethodcall.vala @@ -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 (); + } } diff --git a/vala/valaobjectcreationexpression.vala b/vala/valaobjectcreationexpression.vala index 9fc43fd10..5d64b05f8 100644 --- a/vala/valaobjectcreationexpression.vala +++ b/vala/valaobjectcreationexpression.vala @@ -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; + } } diff --git a/vala/valaparenthesizedexpression.vala b/vala/valaparenthesizedexpression.vala index 2a29d9332..e1c97d487 100644 --- a/vala/valaparenthesizedexpression.vala +++ b/vala/valaparenthesizedexpression.vala @@ -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 (); + } } diff --git a/vala/valapointerindirection.vala b/vala/valapointerindirection.vala index 84f1b6e6f..f926c7a53 100644 --- a/vala/valapointerindirection.vala +++ b/vala/valapointerindirection.vala @@ -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 (); + } } diff --git a/vala/valapostfixexpression.vala b/vala/valapostfixexpression.vala index 3ff4d6d69..e34365472 100644 --- a/vala/valapostfixexpression.vala +++ b/vala/valapostfixexpression.vala @@ -75,4 +75,8 @@ public class Vala.PostfixExpression : Expression { return !error; } + + public override bool in_single_basic_block () { + return true; + } } diff --git a/vala/valareferencetransferexpression.vala b/vala/valareferencetransferexpression.vala index dcf2e5369..fc83f1a0d 100644 --- a/vala/valareferencetransferexpression.vala +++ b/vala/valareferencetransferexpression.vala @@ -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 (); + } } diff --git a/vala/valasizeofexpression.vala b/vala/valasizeofexpression.vala index 673b16e9c..0000d2ced 100644 --- a/vala/valasizeofexpression.vala +++ b/vala/valasizeofexpression.vala @@ -82,4 +82,8 @@ public class Vala.SizeofExpression : Expression { return !error; } + + public override bool in_single_basic_block () { + return true; + } } diff --git a/vala/valatuple.vala b/vala/valatuple.vala index fc05984e8..16354f607 100644 --- a/vala/valatuple.vala +++ b/vala/valatuple.vala @@ -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; + } } diff --git a/vala/valatypecheck.vala b/vala/valatypecheck.vala index 2dee142f1..dea9708b4 100644 --- a/vala/valatypecheck.vala +++ b/vala/valatypecheck.vala @@ -101,4 +101,8 @@ public class Vala.TypeCheck : Expression { return !error; } + + public override bool in_single_basic_block () { + return expression.in_single_basic_block (); + } } diff --git a/vala/valatypeofexpression.vala b/vala/valatypeofexpression.vala index 9331a8f39..e18be52ae 100644 --- a/vala/valatypeofexpression.vala +++ b/vala/valatypeofexpression.vala @@ -84,4 +84,8 @@ public class Vala.TypeofExpression : Expression { return !error; } + + public override bool in_single_basic_block () { + return true; + } } diff --git a/vala/valaunaryexpression.vala b/vala/valaunaryexpression.vala index 9f478d8e9..16260859e 100644 --- a/vala/valaunaryexpression.vala +++ b/vala/valaunaryexpression.vala @@ -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 { diff --git a/vala/valawhilestatement.vala b/vala/valawhilestatement.vala index 028538c0d..3a595256a 100644 --- a/vala/valawhilestatement.vala +++ b/vala/valawhilestatement.vala @@ -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); |