[vala/wip/transform: 37/45] Split CodeTrasformer into CCodeTransformer



commit d4a69dadf2d5d717bf279356ca114d0afc734aa1
Author: Luca Bruno <lucabru src gnome org>
Date:   Wed Jan 4 19:38:09 2012 +0100

    Split CodeTrasformer into CCodeTransformer

 codegen/Makefile.am                  |    1 +
 codegen/valaccodetransformer.vala    |  448 ++++++++++++++++++++++++++++++++++
 codegen/valagvarianttransformer.vala |    2 +-
 vala/valacodetransformer.vala        |  422 --------------------------------
 4 files changed, 450 insertions(+), 423 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index 2c6324f..c5a3226 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -26,6 +26,7 @@ libvala_la_VALASOURCES = \
 	valaccodemethodcallmodule.vala \
 	valaccodemethodmodule.vala \
 	valaccodestructmodule.vala \
+	valaccodetransformer.vala \
 	valaclassregisterfunction.vala \
 	valactype.vala \
 	valadovaarraymodule.vala \
diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala
new file mode 100644
index 0000000..cdd512d
--- /dev/null
+++ b/codegen/valaccodetransformer.vala
@@ -0,0 +1,448 @@
+/* valaccodetransformer.vala
+ *
+ * Copyright (C) 2011  Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+ *
+ * Author:
+ * 	Luca Bruno <lucabru src gnome org>
+ */
+
+/**
+ * Code visitor for simplyfing the code tree for the C codegen.
+ */
+public class Vala.CCodeTransformer : CodeTransformer {
+	public override void visit_source_file (SourceFile source_file) {
+		source_file.accept_children (this);
+	}
+
+	public override void visit_namespace (Namespace ns) {
+		ns.accept_children (this);
+	}
+
+	public override void visit_class (Class cl) {
+		cl.accept_children (this);
+	}
+
+	public override void visit_struct (Struct st) {
+		st.accept_children (this);
+	}
+
+	public override void visit_interface (Interface iface) {
+		iface.accept_children (this);
+	}
+
+	public override void visit_enum (Enum en) {
+		en.accept_children (this);
+	}
+
+	public override void visit_enum_value (EnumValue ev) {
+		ev.accept_children (this);
+	}
+
+	public override void visit_error_domain (ErrorDomain edomain) {
+		edomain.accept_children (this);
+	}
+
+	public override void visit_error_code (ErrorCode ecode) {
+		ecode.accept_children (this);
+	}
+
+	public override void visit_delegate (Delegate d) {
+		d.accept_children (this);
+	}
+
+	public override void visit_constant (Constant c) {
+		c.accept_children (this);
+	}
+
+	public override void visit_field (Field f) {
+		f.accept_children (this);
+	}
+
+	public override void visit_method (Method m) {
+		m.accept_children (this);
+	}
+
+	public override void visit_creation_method (CreationMethod m) {
+		m.accept_children (this);
+	}
+
+	public override void visit_formal_parameter (Parameter p) {
+		p.accept_children (this);
+	}
+
+	public override void visit_property (Property prop) {
+		prop.accept_children (this);
+	}
+
+	public override void visit_property_accessor (PropertyAccessor acc) {
+		acc.accept_children (this);
+	}
+
+	public override void visit_signal (Signal sig) {
+		sig.accept_children (this);
+	}
+
+	public override void visit_constructor (Constructor c) {
+		c.accept_children (this);
+	}
+
+	public override void visit_destructor (Destructor d) {
+		d.accept_children (this);
+	}
+
+	public override void visit_block (Block b) {
+		b.accept_children (this);
+	}
+
+	public override void visit_declaration_statement (DeclarationStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_local_variable (LocalVariable local) {
+		local.accept_children (this);
+	}
+
+	public override void visit_initializer_list (InitializerList list) {
+		list.accept_children (this);
+	}
+
+	public override void visit_expression_statement (ExpressionStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_if_statement (IfStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_switch_statement (SwitchStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_switch_section (SwitchSection section) {
+		section.accept_children (this);
+	}
+
+	public override void visit_switch_label (SwitchLabel label) {
+		label.accept_children (this);
+	}
+
+	bool always_true (Expression condition) {
+		var literal = condition as BooleanLiteral;
+		return (literal != null && literal.value);
+	}
+
+	bool always_false (Expression condition) {
+		var literal = condition as BooleanLiteral;
+		return (literal != null && !literal.value);
+	}
+
+	public override void visit_loop (Loop loop) {
+		loop.accept_children (this);
+	}
+
+	public override void visit_while_statement (WhileStatement stmt) {
+		// convert to simple loop
+
+		if (always_true (stmt.condition)) {
+			// do not generate if block if condition is always true
+		} 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 {
+			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);
+		}
+
+		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);
+
+		stmt.body.checked = false;
+		check (loop);
+	}
+
+	public override void visit_do_statement (DoStatement stmt) {
+		// convert to simple 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;
+		}
+
+		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;
+		context.analyzer.replaced_nodes.add (stmt);
+		parent_block.replace_statement (stmt, block);
+
+		stmt.body.checked = false;
+		check (block);
+	}
+
+	public override void visit_for_statement (ForStatement stmt) {
+		// convert to simple loop
+
+		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);
+		}
+
+		// 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));
+
+		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));
+		}
+
+		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;
+		context.analyzer.replaced_nodes.add (stmt);
+		parent_block.replace_statement (stmt, block);
+
+		stmt.body.checked = false;
+		check (block);
+	}
+
+	public override void visit_foreach_statement (ForeachStatement stmt) {
+		push_builder (new CodeBuilder (context, stmt, stmt.source_reference));
+		var collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection);
+
+		stmt.body.remove_local_variable (stmt.element_variable);
+		stmt.element_variable.checked = false;
+		var decl = new DeclarationStatement (stmt.element_variable, stmt.element_variable.source_reference);
+
+		switch (stmt.foreach_iteration) {
+		case ForeachIteration.ARRAY:
+		case ForeachIteration.GVALUE_ARRAY:
+			// array or GValueArray
+			var array = collection;
+			if (stmt.foreach_iteration == ForeachIteration.GVALUE_ARRAY) {
+				array = collection+".values";
+			}
+			var i = b.add_temp_declaration (null, expression ("0"));
+			b.open_for (null, expression (@"$i < $array.length"), expression (@"$i++"));
+			stmt.element_variable.initializer = expression (@"$array[$i]");
+			break;
+		case ForeachIteration.GLIST:
+			// GList or GSList
+			b.open_for (null, expression (@"$collection != null"), expression (@"$collection = $collection.next"));
+			stmt.element_variable.initializer = expression (@"$collection.data");
+			break;
+		case ForeachIteration.INDEX:
+			// get()+size
+			var size = b.add_temp_declaration (null, expression ("$collection.size"));
+			var i = b.add_temp_declaration (null, expression ("0"));
+			b.open_for (null, expression (@"$i < $size"), expression (@"$i++"));
+			stmt.element_variable.initializer = expression (@"$collection.get ($i)");
+			break;
+		case ForeachIteration.NEXT_VALUE:
+			// iterator+next_value()
+			var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
+			var temp = b.add_temp_declaration (stmt.type_reference);
+			b.open_while (expression (@"($temp = $iterator.next_value ()) != null"));
+			stmt.element_variable.initializer = expression (temp);
+			break;
+		case ForeachIteration.NEXT_GET:
+			// iterator+next()+get()
+			var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
+			b.open_while (expression (@"$iterator.next ()"));
+			stmt.element_variable.initializer = expression (@"$iterator.get ()");
+			break;
+		default:
+			assert_not_reached ();
+		}
+
+		stmt.body.insert_statement (0, decl);
+		b.add_statement (stmt.body);
+		b.close ();
+
+		var parent_block = context.analyzer.get_current_block (stmt);
+		context.analyzer.replaced_nodes.add (stmt);
+		parent_block.replace_statement (stmt, new EmptyStatement (stmt.source_reference));
+
+		stmt.body.checked = false;
+		b.check (this);
+		pop_builder ();
+	}
+
+	public override void visit_break_statement (BreakStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_continue_statement (ContinueStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_return_statement (ReturnStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_yield_statement (YieldStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_throw_statement (ThrowStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_try_statement (TryStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_catch_clause (CatchClause clause) {
+		clause.accept_children (this);
+	}
+
+	public override void visit_lock_statement (LockStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_unlock_statement (UnlockStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_delete_statement (DeleteStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_expression (Expression expr) {
+		expr.accept_children (this);
+	}
+
+	public override void visit_method_call (MethodCall expr) {
+		if (expr.tree_can_fail) {
+			if (expr.parent_node is LocalVariable || expr.parent_node is ExpressionStatement) {
+				// simple statements, no side effects after method call
+			} else if (!(context.analyzer.get_current_symbol (expr) is Block)) {
+				if (context.profile != Profile.DOVA) {
+					// can't handle errors in field initializers
+					Report.error (expr.source_reference, "Field initializers must not throw errors");
+				}
+			} 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 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);
+
+				context.analyzer.replaced_nodes.add (expr);
+				old_parent_node.replace_expression (expr, temp_access);
+				check (temp_access);
+			}
+		}
+	}
+
+	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_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;
+
+		context.analyzer.replaced_nodes.add (expr);
+		expr.parent_node.replace_expression (expr, ma);
+		check (ma);
+	}
+}
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index e1259e6..26a521a 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -23,7 +23,7 @@
 /**
  * Code visitor for transforming the code tree related to GVariant.
  */
-public class Vala.GVariantTransformer : CodeTransformer {
+public class Vala.GVariantTransformer : CCodeTransformer {
 	struct BasicTypeInfo {
 		public unowned string signature;
 		public unowned string type_name;
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 09331db..02728fa 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -117,426 +117,4 @@ public class Vala.CodeTransformer : CodeVisitor {
 		}
 		node.accept (this);
 	}
-
-	public override void visit_source_file (SourceFile source_file) {
-		source_file.accept_children (this);
-	}
-
-	public override void visit_namespace (Namespace ns) {
-		ns.accept_children (this);
-	}
-
-	public override void visit_class (Class cl) {
-		cl.accept_children (this);
-	}
-
-	public override void visit_struct (Struct st) {
-		st.accept_children (this);
-	}
-
-	public override void visit_interface (Interface iface) {
-		iface.accept_children (this);
-	}
-
-	public override void visit_enum (Enum en) {
-		en.accept_children (this);
-	}
-
-	public override void visit_enum_value (EnumValue ev) {
-		ev.accept_children (this);
-	}
-
-	public override void visit_error_domain (ErrorDomain edomain) {
-		edomain.accept_children (this);
-	}
-
-	public override void visit_error_code (ErrorCode ecode) {
-		ecode.accept_children (this);
-	}
-
-	public override void visit_delegate (Delegate d) {
-		d.accept_children (this);
-	}
-
-	public override void visit_constant (Constant c) {
-		c.accept_children (this);
-	}
-
-	public override void visit_field (Field f) {
-		f.accept_children (this);
-	}
-
-	public override void visit_method (Method m) {
-		m.accept_children (this);
-	}
-
-	public override void visit_creation_method (CreationMethod m) {
-		m.accept_children (this);
-	}
-
-	public override void visit_formal_parameter (Parameter p) {
-		p.accept_children (this);
-	}
-
-	public override void visit_property (Property prop) {
-		prop.accept_children (this);
-	}
-
-	public override void visit_property_accessor (PropertyAccessor acc) {
-		acc.accept_children (this);
-	}
-
-	public override void visit_signal (Signal sig) {
-		sig.accept_children (this);
-	}
-
-	public override void visit_constructor (Constructor c) {
-		c.accept_children (this);
-	}
-
-	public override void visit_destructor (Destructor d) {
-		d.accept_children (this);
-	}
-
-	public override void visit_block (Block b) {
-		b.accept_children (this);
-	}
-
-	public override void visit_declaration_statement (DeclarationStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_local_variable (LocalVariable local) {
-		local.accept_children (this);
-	}
-
-	public override void visit_initializer_list (InitializerList list) {
-		list.accept_children (this);
-	}
-
-	public override void visit_expression_statement (ExpressionStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_if_statement (IfStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_switch_statement (SwitchStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_switch_section (SwitchSection section) {
-		section.accept_children (this);
-	}
-
-	public override void visit_switch_label (SwitchLabel label) {
-		label.accept_children (this);
-	}
-
-	bool always_true (Expression condition) {
-		var literal = condition as BooleanLiteral;
-		return (literal != null && literal.value);
-	}
-
-	bool always_false (Expression condition) {
-		var literal = condition as BooleanLiteral;
-		return (literal != null && !literal.value);
-	}
-
-	public override void visit_loop (Loop loop) {
-		loop.accept_children (this);
-	}
-
-	public override void visit_while_statement (WhileStatement stmt) {
-		// convert to simple loop
-
-		if (always_true (stmt.condition)) {
-			// do not generate if block if condition is always true
-		} 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 {
-			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);
-		}
-
-		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);
-
-		stmt.body.checked = false;
-		check (loop);
-	}
-
-	public override void visit_do_statement (DoStatement stmt) {
-		// convert to simple 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;
-		}
-
-		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;
-		context.analyzer.replaced_nodes.add (stmt);
-		parent_block.replace_statement (stmt, block);
-
-		stmt.body.checked = false;
-		check (block);
-	}
-
-	public override void visit_for_statement (ForStatement stmt) {
-		// convert to simple loop
-
-		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);
-		}
-
-		// 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));
-
-		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));
-		}
-
-		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;
-		context.analyzer.replaced_nodes.add (stmt);
-		parent_block.replace_statement (stmt, block);
-
-		stmt.body.checked = false;
-		check (block);
-	}
-
-	public override void visit_foreach_statement (ForeachStatement stmt) {
-		push_builder (new CodeBuilder (context, stmt, stmt.source_reference));
-		var collection = b.add_temp_declaration (stmt.collection.value_type, stmt.collection);
-
-		stmt.body.remove_local_variable (stmt.element_variable);
-		stmt.element_variable.checked = false;
-		var decl = new DeclarationStatement (stmt.element_variable, stmt.element_variable.source_reference);
-
-		switch (stmt.foreach_iteration) {
-		case ForeachIteration.ARRAY:
-		case ForeachIteration.GVALUE_ARRAY:
-			// array or GValueArray
-			var array = collection;
-			if (stmt.foreach_iteration == ForeachIteration.GVALUE_ARRAY) {
-				array = collection+".values";
-			}
-			var i = b.add_temp_declaration (null, expression ("0"));
-			b.open_for (null, expression (@"$i < $array.length"), expression (@"$i++"));
-			stmt.element_variable.initializer = expression (@"$array[$i]");
-			break;
-		case ForeachIteration.GLIST:
-			// GList or GSList
-			b.open_for (null, expression (@"$collection != null"), expression (@"$collection = $collection.next"));
-			stmt.element_variable.initializer = expression (@"$collection.data");
-			break;
-		case ForeachIteration.INDEX:
-			// get()+size
-			var size = b.add_temp_declaration (null, expression ("$collection.size"));
-			var i = b.add_temp_declaration (null, expression ("0"));
-			b.open_for (null, expression (@"$i < $size"), expression (@"$i++"));
-			stmt.element_variable.initializer = expression (@"$collection.get ($i)");
-			break;
-		case ForeachIteration.NEXT_VALUE:
-			// iterator+next_value()
-			var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
-			var temp = b.add_temp_declaration (stmt.type_reference);
-			b.open_while (expression (@"($temp = $iterator.next_value ()) != null"));
-			stmt.element_variable.initializer = expression (temp);
-			break;
-		case ForeachIteration.NEXT_GET:
-			// iterator+next()+get()
-			var iterator = b.add_temp_declaration (null, expression (@"$collection.iterator ()"));
-			b.open_while (expression (@"$iterator.next ()"));
-			stmt.element_variable.initializer = expression (@"$iterator.get ()");
-			break;
-		default:
-			assert_not_reached ();
-		}
-
-		stmt.body.insert_statement (0, decl);
-		b.add_statement (stmt.body);
-		b.close ();
-
-		var parent_block = context.analyzer.get_current_block (stmt);
-		context.analyzer.replaced_nodes.add (stmt);
-		parent_block.replace_statement (stmt, new EmptyStatement (stmt.source_reference));
-
-		stmt.body.checked = false;
-		b.check (this);
-		pop_builder ();
-	}
-
-	public override void visit_break_statement (BreakStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_continue_statement (ContinueStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_return_statement (ReturnStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_yield_statement (YieldStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_throw_statement (ThrowStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_try_statement (TryStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_catch_clause (CatchClause clause) {
-		clause.accept_children (this);
-	}
-
-	public override void visit_lock_statement (LockStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_unlock_statement (UnlockStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_delete_statement (DeleteStatement stmt) {
-		stmt.accept_children (this);
-	}
-
-	public override void visit_expression (Expression expr) {
-		expr.accept_children (this);
-	}
-
-	public override void visit_method_call (MethodCall expr) {
-		if (expr.tree_can_fail) {
-			if (expr.parent_node is LocalVariable || expr.parent_node is ExpressionStatement) {
-				// simple statements, no side effects after method call
-			} else if (!(context.analyzer.get_current_symbol (expr) is Block)) {
-				if (context.profile != Profile.DOVA) {
-					// can't handle errors in field initializers
-					Report.error (expr.source_reference, "Field initializers must not throw errors");
-				}
-			} 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 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);
-
-				context.analyzer.replaced_nodes.add (expr);
-				old_parent_node.replace_expression (expr, temp_access);
-				check (temp_access);
-			}
-		}
-	}
-
-	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_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;
-
-		context.analyzer.replaced_nodes.add (expr);
-		expr.parent_node.replace_expression (expr, ma);
-		check (ma);
-	}
 }



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