summaryrefslogtreecommitdiff
path: root/vala
diff options
context:
space:
mode:
authorJürg Billeter <j@bitron.ch>2008-11-29 17:25:51 +0000
committerJürg Billeter <juergbi@src.gnome.org>2008-11-29 17:25:51 +0000
commit9c112c985e1edafa2602416962702f185a5583a0 (patch)
tree00a87c40a46d3f07cf15797250d396d965d8006d /vala
parent44a1c2f3196261abbc0930f84df21fc877afd266 (diff)
downloadvala-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')
-rw-r--r--vala/valaaddressofexpression.vala4
-rw-r--r--vala/valaarraycreationexpression.vala9
-rw-r--r--vala/valaassignment.vala4
-rw-r--r--vala/valabaseaccess.vala4
-rw-r--r--vala/valabinaryexpression.vala57
-rw-r--r--vala/valacastexpression.vala4
-rw-r--r--vala/valaconditionalexpression.vala17
-rw-r--r--vala/valadostatement.vala37
-rw-r--r--vala/valaelementaccess.vala9
-rw-r--r--vala/valaexpression.vala6
-rw-r--r--vala/valaforstatement.vala14
-rw-r--r--vala/valainitializerlist.vala9
-rw-r--r--vala/valalambdaexpression.vala4
-rw-r--r--vala/valaliteral.vala4
-rw-r--r--vala/valamemberaccess.vala4
-rw-r--r--vala/valamethodcall.vala9
-rw-r--r--vala/valaobjectcreationexpression.vala9
-rw-r--r--vala/valaparenthesizedexpression.vala4
-rw-r--r--vala/valapointerindirection.vala4
-rw-r--r--vala/valapostfixexpression.vala4
-rw-r--r--vala/valareferencetransferexpression.vala4
-rw-r--r--vala/valasizeofexpression.vala4
-rw-r--r--vala/valatuple.vala9
-rw-r--r--vala/valatypecheck.vala4
-rw-r--r--vala/valatypeofexpression.vala4
-rw-r--r--vala/valaunaryexpression.vala4
-rw-r--r--vala/valawhilestatement.vala13
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);