summaryrefslogtreecommitdiff
path: root/vala
diff options
context:
space:
mode:
authorLuca Bruno <lucabru@src.gnome.org>2011-08-07 12:22:15 +0200
committerRico Tzschichholz <ricotz@ubuntu.com>2019-03-11 13:49:26 +0100
commit2a5750135a633e743ab70d474aeaded762d5e5bb (patch)
tree8e72b801d05b1d176a310fc450676794f3316446 /vala
parent9c8417eaa82f6c2f9cf861e85ef16810758a105c (diff)
downloadvala-2a5750135a633e743ab70d474aeaded762d5e5bb.tar.gz
Code transformer
Diffstat (limited to 'vala')
-rw-r--r--vala/Makefile.am1
-rw-r--r--vala/valacodetransformer.vala264
-rw-r--r--vala/valamethodcall.vala33
3 files changed, 265 insertions, 33 deletions
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 6be70557d..ccf80e4bd 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -51,6 +51,7 @@ libvala_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 000000000..1f0136d79
--- /dev/null
+++ b/vala/valacodetransformer.vala
@@ -0,0 +1,264 @@
+/* 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_non_local_symbol (expr) is Block)) {
+ // 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);
+ var decl = new DeclarationStatement (local, expr.source_reference);
+
+ expr.insert_statement (context.analyzer.get_insert_block (expr), decl);
+
+ var temp_access = SemanticAnalyzer.create_temp_access (local, 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 041d096d2..262b789d8 100644
--- a/vala/valamethodcall.vala
+++ b/vala/valamethodcall.vala
@@ -643,39 +643,6 @@ public class Vala.MethodCall : Expression {
value_type.check (context);
- 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_non_local_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.copy (), get_temp_name (), null, source_reference);
- var decl = new DeclarationStatement (local, source_reference);
-
- insert_statement (context.analyzer.get_insert_block (this), decl);
-
- var temp_access = SemanticAnalyzer.create_temp_access (local, 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 the
- // variable is in the same block as the declaration
- // otherwise there will be scoping issues in the generated code
- 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;
}