[vala/wip/transform: 4/4] Code transformer



commit 68f98d84a1b3b26beb8afe066ef20686fbca6412
Author: Luca Bruno <lucabru src gnome org>
Date:   Sun Aug 7 12:22:15 2011 +0200

    Code transformer

 compiler/valacompiler.vala    |    7 +
 vala/Makefile.am              |    1 +
 vala/valacodetransformer.vala |  269 +++++++++++++++++++++++++++++++++++++++++
 vala/valamethodcall.vala      |   41 ------
 4 files changed, 277 insertions(+), 41 deletions(-)
---
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index eab72c4..23704fe 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -342,6 +342,13 @@ class Vala.Compiler {
 			}
 		}
 
+		var transformer = new CodeTransformer ();
+		transformer.transform (context);
+
+		if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () > 0)) {
+			return quit ();
+		}
+
 		if (dump_tree != null) {
 			var code_writer = new CodeWriter (CodeWriterType.DUMP);
 			code_writer.write_file (context, dump_tree);
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 936a2cb..655bea9 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -37,6 +37,7 @@ libvalacore_la_VALASOURCES = \
 	valacodecontext.vala \
 	valacodegenerator.vala \
 	valacodenode.vala \
+	valacodetransformer.vala \
 	valacodevisitor.vala \
 	valacodewriter.vala \
 	valacomment.vala \
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
new file mode 100644
index 0000000..e370e78
--- /dev/null
+++ b/vala/valacodetransformer.vala
@@ -0,0 +1,269 @@
+/* valacodetransformer.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 transforming the code tree.
+ */
+public class Vala.CodeTransformer : CodeVisitor {
+	public CodeContext context;
+
+	/**
+	 * Transform the code tree for the specified code context.
+	 *
+	 * @param context a code context
+	 */
+	public void transform (CodeContext context) {
+		this.context = context;
+
+		/* we're only interested in non-pkg source files */
+		var source_files = context.get_source_files ();
+		foreach (SourceFile file in source_files) {
+			if (file.file_type == SourceFileType.SOURCE ||
+			    (context.header_filename != null && file.file_type == SourceFileType.FAST)) {
+				file.accept (this);
+			}
+		}
+	}
+
+	public void check (CodeNode node) {
+		if (!node.check (context)) {
+			return;
+		}
+		//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);
+	}
+
+	public override void visit_while_statement (WhileStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_do_statement (DoStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_for_statement (ForStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	public override void visit_foreach_statement (ForeachStatement stmt) {
+		stmt.accept_children (this);
+	}
+
+	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_insert_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_insert_block (expr).add_local_variable (local);
+
+				old_parent_node.replace_expression (expr, temp_access);
+				check (temp_access);
+			}
+		}
+	}
+}
diff --git a/vala/valamethodcall.vala b/vala/valamethodcall.vala
index 132cc67..307aab8 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -588,8 +588,6 @@ public class Vala.MethodCall : Expression {
 		formal_value_type = ret_type;
 		value_type = formal_value_type.get_actual_type (target_object_type, call as MemberAccess, this);
 
-		bool may_throw = false;
-
 		if (mtype is MethodType) {
 			var m = ((MethodType) mtype).method_symbol;
 			if (is_yield_expression) {
@@ -604,7 +602,6 @@ public class Vala.MethodCall : Expression {
 				}
 				current_method.yield_count++;
 			}
-
 			if (m.returns_floating_reference) {
 				value_type.floating_reference = true;
 			}
@@ -698,44 +695,6 @@ public class Vala.MethodCall : Expression {
 			return false;
 		}
 
-		if (tree_can_fail) {
-			if (parent_node is LocalVariable || parent_node is ExpressionStatement) {
-				// simple statements, no side effects after method call
-			} else if (!(context.analyzer.get_current_symbol (this) is Block)) {
-				if (context.profile != Profile.DOVA) {
-					// can't handle errors in field initializers
-					Report.error (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 = parent_node;
-
-				var local = new LocalVariable (value_type, get_temp_name (), null, source_reference);
-				// use floating variable to avoid unnecessary (and sometimes impossible) copies
-				local.floating = true;
-				var decl = new DeclarationStatement (local, source_reference);
-
-				insert_statement (context.analyzer.get_insert_block (this), decl);
-
-				Expression temp_access = new MemberAccess.simple (local.name, source_reference);
-				temp_access.target_type = target_type;
-
-				// don't set initializer earlier as this changes parent_node and parent_statement
-				local.initializer = this;
-				decl.check (context);
-
-				// 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 (this);
-				block.remove_local_variable (local);
-				context.analyzer.get_insert_block (this).add_local_variable (local);
-
-				old_parent_node.replace_expression (this, temp_access);
-				temp_access.check (context);
-			}
-		}
-
 		return !error;
 	}
 



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