[vala/wip/transform: 8/45] Move ConditionalExpression transformation into the code transformer



commit 80751a081136468a74c8abbd1c9faa13c221c32c
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 3a472af..e8b4227 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -376,4 +376,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 2bbce44..bd6001b 100644
--- a/vala/valaflowanalyzer.vala
+++ b/vala/valaflowanalyzer.vala
@@ -1222,12 +1222,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]