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



commit db4a7f71b648607cc8697a64eec243ea2b731b36
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      |   39 ------
 4 files changed, 277 insertions(+), 39 deletions(-)
---
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index 1f471ed..354e7d5 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -324,6 +324,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 d6df894..1c4b3c9 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 56b4293..4d8a11d 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -596,8 +596,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) {
@@ -612,7 +610,6 @@ public class Vala.MethodCall : Expression {
                                }
                                current_method.yield_count++;
                        }
-
                        if (m.returns_floating_reference) {
                                value_type.floating_reference = true;
                        }
@@ -706,42 +703,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)) {
-                               // 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]