[vala/staging: 45/45] Allow floating temp variables with CodeBuilder



commit 739efde54ad77742b7fce229047a48ff6462fe65
Author: Luca Bruno <lucabru src gnome org>
Date:   Fri Jan 6 14:11:22 2012 +0100

    Allow floating temp variables with CodeBuilder

 codegen/valaccodetransformer.vala |  171 ++++++++++++++-----------------------
 vala/valacodebuilder.vala         |    3 +-
 2 files changed, 66 insertions(+), 108 deletions(-)
---
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
index 195e954..a1f5859 100644
--- a/codegen/valaccodetransformer.vala
+++ b/codegen/valaccodetransformer.vala
@@ -180,92 +180,65 @@ public class Vala.CCodeTransformer : CodeTransformer {
 
 	public override void visit_do_statement (DoStatement stmt) {
 		// convert to simple loop
+		push_builder (new CodeBuilder (context, stmt, stmt.source_reference));
 
+		b.open_loop ();
 		// do not generate variable and if block if condition is always true
-		if (always_true (stmt.condition)) {
-			var loop = new Loop (stmt.body, stmt.source_reference);
-
-			var parent_block = (Block) stmt.parent_node;
-			context.analyzer.replaced_nodes.add (stmt);
-			parent_block.replace_statement (stmt, loop);
-
-			check (loop);
-			return;
+		if (!always_true (stmt.condition)) {
+			var notfirst = b.add_temp_declaration (null, expression ("false"));
+			b.open_if (expression (notfirst));
+			b.open_if (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.source_reference));
+			b.add_break ();
+			b.close ();
+			b.add_else ();
+			b.add_assignment (expression (notfirst), expression ("true"));
+			b.close ();
 		}
+		b.add_statement (stmt.body);
+		b.close ();
 
-		var block = new Block (stmt.source_reference);
-
-		var first_local = new LocalVariable (context.analyzer.bool_type.copy (), stmt.get_temp_name (), new BooleanLiteral (true, stmt.source_reference), stmt.source_reference);
-		block.add_statement (new DeclarationStatement (first_local, stmt.source_reference));
-
-		var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.condition.source_reference);
-		var true_block = new Block (stmt.condition.source_reference);
-		true_block.add_statement (new BreakStatement (stmt.condition.source_reference));
-		var if_stmt = new IfStatement (if_condition, true_block, null, stmt.condition.source_reference);
-
-		var condition_block = new Block (stmt.condition.source_reference);
-		condition_block.add_statement (if_stmt);
-
-		var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, stmt.source_reference), stmt.source_reference), condition_block, null, stmt.source_reference);
-		stmt.body.insert_statement (0, first_if);
-		var first_assign = new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, stmt.source_reference), new BooleanLiteral (false, stmt.source_reference), AssignmentOperator.SIMPLE, stmt.source_reference), stmt.source_reference);
-		stmt.body.insert_statement (1, first_assign);
-
-		block.add_statement (new Loop (stmt.body, stmt.source_reference));
-
-		var parent_block = (Block) stmt.parent_node;
+		var parent_block = context.analyzer.get_current_block (stmt);
 		context.analyzer.replaced_nodes.add (stmt);
-		parent_block.replace_statement (stmt, block);
+		parent_block.replace_statement (stmt, new EmptyStatement (stmt.source_reference));
 
 		stmt.body.checked = false;
-		check (block);
+		b.check (this);
+		pop_builder ();
 	}
 
 	public override void visit_for_statement (ForStatement stmt) {
 		// convert to simple loop
+		push_builder (new CodeBuilder (context, stmt, stmt.source_reference));
 
 		var block = new Block (stmt.source_reference);
 
 		// initializer
 		foreach (var init_expr in stmt.get_initializer ()) {
-			block.add_statement (new ExpressionStatement (init_expr, init_expr.source_reference));
-		}
-
-		// do not generate if block if condition is always true
-		if (stmt.condition == null || always_true (stmt.condition)) {
-		} else if (always_false (stmt.condition)) {
-			// do not generate if block if condition is always false
-			stmt.body.insert_statement (0, new BreakStatement (stmt.condition.source_reference));
-		} else {
-			// condition
-			var if_condition = new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.condition.source_reference);
-			var true_block = new Block (stmt.condition.source_reference);
-			true_block.add_statement (new BreakStatement (stmt.condition.source_reference));
-			var if_stmt = new IfStatement (if_condition, true_block, null, stmt.condition.source_reference);
-			stmt.body.insert_statement (0, if_stmt);
+			b.add_expression (init_expr);
 		}
 
-		// iterator
-		var first_local = new LocalVariable (context.analyzer.bool_type.copy (), stmt.get_temp_name (), new BooleanLiteral (true, stmt.source_reference), stmt.source_reference);
-		block.add_statement (new DeclarationStatement (first_local, stmt.source_reference));
+		if (stmt.condition == null || !always_false (stmt.condition)) {
+			b.open_loop ();
+			if (stmt.condition != null && !always_true (stmt.condition)) {
+				b.open_if (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.source_reference));
+				b.add_break ();
+				b.close ();
+			}
+			b.add_statement (stmt.body);
 
-		var iterator_block = new Block (stmt.source_reference);
-		foreach (var it_expr in stmt.get_iterator ()) {
-			iterator_block.add_statement (new ExpressionStatement (it_expr, it_expr.source_reference));
+			foreach (var it_expr in stmt.get_iterator ()) {
+				b.add_expression (it_expr);
+			}
+			b.close ();
 		}
 
-		var first_if = new IfStatement (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, new MemberAccess.simple (first_local.name, stmt.source_reference), stmt.source_reference), iterator_block, null, stmt.source_reference);
-		stmt.body.insert_statement (0, first_if);
-		stmt.body.insert_statement (1, new ExpressionStatement (new Assignment (new MemberAccess.simple (first_local.name, stmt.source_reference), new BooleanLiteral (false, stmt.source_reference), AssignmentOperator.SIMPLE, stmt.source_reference), stmt.source_reference));
-
-		block.add_statement (new Loop (stmt.body, stmt.source_reference));
-
-		var parent_block = (Block) stmt.parent_node;
+		var parent_block = context.analyzer.get_current_block (stmt);
 		context.analyzer.replaced_nodes.add (stmt);
-		parent_block.replace_statement (stmt, block);
+		parent_block.replace_statement (stmt, new EmptyStatement (stmt.source_reference));
 
 		stmt.body.checked = false;
-		check (block);
+		b.check (this);
+		pop_builder ();
 	}
 
 	public override void visit_foreach_statement (ForeachStatement stmt) {
@@ -386,62 +359,46 @@ public class Vala.CCodeTransformer : CodeTransformer {
 			} else {
 				// store parent_node as we need to replace the expression in the old parent node later on
 				var old_parent_node = expr.parent_node;
+				var formal_target_type = expr.target_type != null ? expr.target_type.copy () : null;
+				var target_type = expr.target_type != null ? expr.target_type.copy () : null;
+				push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
 
-				var local = new LocalVariable (expr.value_type, expr.get_temp_name (), null, expr.source_reference);
-				// use floating variable to avoid unnecessary (and sometimes impossible) copies
-				local.floating = true;
-				var decl = new DeclarationStatement (local, expr.source_reference);
-
-				expr.insert_statement (context.analyzer.get_current_block (expr), decl);
-
-				Expression temp_access = new MemberAccess.simple (local.name, expr.source_reference);
-				temp_access.target_type = expr.target_type;
-
-				// don't set initializer earlier as this changes parent_node and parent_statement
-				local.initializer = expr;
-				check (decl);
-
-				// move temp variable to insert block to ensure
-				// variable is in the same block as the declarat
-				// otherwise there will be scoping issues in the
-				var block = context.analyzer.get_current_block (expr);
-				block.remove_local_variable (local);
-				context.analyzer.get_current_block (expr).add_local_variable (local);
+				var replacement = expression (b.add_temp_declaration (expr.value_type, expr, true));
 
+				replacement.target_type = target_type;
+				replacement.formal_target_type = formal_target_type;
 				context.analyzer.replaced_nodes.add (expr);
-				old_parent_node.replace_expression (expr, temp_access);
-				check (temp_access);
+				old_parent_node.replace_expression (expr, replacement);
+				b.check (this);
+				pop_builder ();
+				check (replacement);
 			}
 		}
 	}
 
 	public override void visit_conditional_expression (ConditionalExpression expr) {
 		// convert to if statement
+		Expression replacement = null;
+		var old_parent_node = expr.parent_node;
+		var formal_target_type = expr.target_type != null ? expr.target_type.copy () : null;
+		var target_type = expr.target_type != null ? expr.target_type.copy () : null;
+		push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
 
-		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_current_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_current_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;
+		var result = b.add_temp_declaration (expr.value_type);
+		b.open_if (expr.condition);
+		b.add_assignment (expression (result), expr.true_expression);
+		b.add_else ();
+		b.add_assignment (expression (result), expr.false_expression);
+		b.close ();
 
+		replacement = expression (result);
+		replacement.target_type = target_type;
+		replacement.formal_target_type = formal_target_type;
 		context.analyzer.replaced_nodes.add (expr);
-		expr.parent_node.replace_expression (expr, ma);
-		check (ma);
+		old_parent_node.replace_expression (expr, replacement);
+		b.check (this);
+		pop_builder ();
+		check (replacement);
 	}
 
 	public override void visit_binary_expression (BinaryExpression expr) {
@@ -504,7 +461,7 @@ public class Vala.CCodeTransformer : CodeTransformer {
 				var target_type = expr.target_type != null ? expr.target_type.copy () : null;
 				push_builder (new CodeBuilder (context, expr.parent_statement, expr.source_reference));
 
-				var replacement = expression (b.add_temp_declaration (expr.value_type, expr));
+				var replacement = expression (b.add_temp_declaration (expr.value_type, expr, true));
 
 				replacement.target_type = target_type;
 				context.analyzer.replaced_nodes.add (expr);
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index 1b8bcdf..4b43f96 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -231,8 +231,9 @@ public class Vala.CodeBuilder {
 		add_statement (new ContinueStatement (source_reference));
 	}
 
-	public string add_temp_declaration (DataType? type, Expression? initializer = null) {
+	public string add_temp_declaration (DataType? type, Expression? initializer = null, bool floating = false) {
 		var local = new LocalVariable (type, CodeNode.get_temp_name (), initializer, source_reference);
+		local.floating = floating;
 		var stmt = new DeclarationStatement (local, source_reference);
 		insert_block.insert_before (insert_statement, stmt);
 		decl_nodes.add (stmt);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]