[vala/wip/transform: 9/99] Move ConditionalExpression transformation into the code transformer
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 9/99] Move ConditionalExpression transformation into the code transformer
- Date: Sun, 9 Feb 2014 22:39:03 +0000 (UTC)
commit ffd6c5a46552d8d259d722359411698314a1e935
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 0d1a945..7ea39e4 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) {
@@ -100,6 +102,18 @@ public class Vala.ConditionalExpression : Expression {
return condition.is_pure () && true_expression.is_pure () && false_expression.is_pure ();
}
+ 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;
@@ -113,43 +127,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)) {
@@ -162,28 +147,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]