[vala/wip/transform: 20/102] Code builder



commit 800f491282fa2373a0337907ff6dfcf56516aec9
Author: Luca Bruno <lucabru src gnome org>
Date:   Thu Dec 29 19:42:55 2011 +0100

    Code builder

 codegen/valagvarianttransformer.vala |  84 +++++++------------
 vala/Makefile.am                     |   1 +
 vala/valacodebuilder.vala            | 154 +++++++++++++++++++++++++++++++++++
 3 files changed, 184 insertions(+), 55 deletions(-)
---
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index 5ff5abe7d..239f8488e 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -45,8 +45,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
                { "g", "signature", true }
        };
 
-       Statement current_statement;
-       Block current_block;
+       CodeBuilder b;
 
        bool get_basic_type_info (string signature, out BasicTypeInfo basic_type) {
                if (signature != null) {
@@ -61,22 +60,22 @@ public class Vala.GVariantTransformer : CodeTransformer {
                return false;
        }
 
-       MemberAccess member_access (string symbol_string, CodeNode node) {
+       MemberAccess member_access (string symbol_string) {
                MemberAccess? ma = null;
                bool first = true;
                foreach (unowned string s in symbol_string.substring(1).split (".")) {
                        if (first) {
-                               ma = new MemberAccess (ma, symbol_string[0].to_string()+s, 
node.source_reference);
+                               ma = new MemberAccess (ma, symbol_string[0].to_string()+s, 
b.source_reference);
                                first = false;
                        } else {
-                               ma = new MemberAccess (ma, s, node.source_reference);
+                               ma = new MemberAccess (ma, s, b.source_reference);
                        }
                }
                return ma;
        }
 
        Expression serialize_basic (BasicTypeInfo basic_type, Expression expr) {
-               var new_call = new ObjectCreationExpression (member_access ("GLib.Variant." + 
basic_type.type_name, expr), expr.source_reference);
+               var new_call = new ObjectCreationExpression (member_access ("GLib.Variant." + 
basic_type.type_name), expr.source_reference);
                new_call.add_argument (expr);
                return new_call;
        }
@@ -163,74 +162,53 @@ public class Vala.GVariantTransformer : CodeTransformer {
        }
 
        Expression serialize_array (ArrayType array_type, Expression array_expr) {
-               LocalVariable temp = new LocalVariable (array_type, array_expr.get_temp_name (), array_expr, 
array_expr.source_reference);
-               var decl = new DeclarationStatement (temp, array_expr.source_reference);
-               context.analyzer.get_insert_block (current_statement).insert_before (current_statement, decl);
-               check (decl);
+               string temp = b.add_temp_declaration (array_type, null);
 
-               LocalVariable[] indices = new LocalVariable[array_type.rank];
+               string[] indices = new string[array_type.rank];
                for (int dim=1; dim <= array_type.rank; dim++) {
-                       var index = new LocalVariable (null, array_expr.get_temp_name (), new IntegerLiteral 
("0"), array_expr.source_reference);
-                       decl = new DeclarationStatement (index, array_expr.source_reference);
-                       context.analyzer.get_insert_block (current_statement).insert_before 
(current_statement, decl);
-                       check (decl);
-                       indices[dim-1] = index;
+                       indices[dim-1] = b.add_temp_declaration (null, new IntegerLiteral ("0"));
                }
                return serialize_array_dim (array_type, 1, indices, temp);
        }
 
-       Expression serialize_array_dim (ArrayType array_type, int dim, LocalVariable[] indices, LocalVariable 
array_var) {
-               var gvariant_type = new ObjectCreationExpression (member_access ("GLib.VariantType", 
array_var), array_var.source_reference);
+       Expression serialize_array_dim (ArrayType array_type, int dim, string[] indices, string array_var) {
+               var gvariant_type = new ObjectCreationExpression (member_access ("GLib.VariantType"), 
b.source_reference);
                gvariant_type.add_argument (new StringLiteral ("\""+get_type_signature (array_type)+"\""));
 
-               var builderinit = new ObjectCreationExpression (member_access ("GLib.VariantBuilder", 
array_var), array_var.source_reference);
+               var builderinit = new ObjectCreationExpression (member_access ("GLib.VariantBuilder"), 
b.source_reference);
                builderinit.add_argument (gvariant_type);
 
-               var builder = new LocalVariable (null, array_var.get_temp_name (), builderinit, 
array_var.source_reference);
-               var decl = new DeclarationStatement (builder, array_var.source_reference);
-               context.analyzer.get_insert_block (current_statement).insert_before (current_statement, decl);
-               check (decl);
+               var builder = b.add_temp_declaration (null, builderinit);
 
-               Expression length = member_access (array_var.name+".length", array_var);
+               Expression length = member_access (array_var+".length");
                if (array_type.rank > 1) {
-                       ElementAccess ea = new ElementAccess (length, array_var.source_reference);
-                       ea.append_index (new IntegerLiteral ((dim-1).to_string (), 
array_var.source_reference));
+                       ElementAccess ea = new ElementAccess (length, b.source_reference);
+                       ea.append_index (new IntegerLiteral ((dim-1).to_string (), b.source_reference));
                        length = ea;
                }
 
                var index = indices[dim-1];
-               var forcond = new BinaryExpression (BinaryOperator.LESS_THAN, member_access (index.name, 
array_var), length, array_var.source_reference);
-               var foriter = new PostfixExpression (member_access (index.name, array_var), true, 
array_var.source_reference);
-               var forbody = new Block (array_var.source_reference);
-               var old_block = current_block;
-               current_block = forbody;
+               var forcond = new BinaryExpression (BinaryOperator.LESS_THAN, member_access (index), length, 
b.source_reference);
+               var foriter = new PostfixExpression (member_access (index), true, b.source_reference);
+               b.open_for (null, forcond, foriter);
 
                Expression element_variant;
                if (dim < array_type.rank) {
                        element_variant = serialize_array_dim (array_type, dim + 1, indices, array_var);
                } else {
-                       var element_expr = new ElementAccess (member_access (array_var.name, array_var), 
array_var.source_reference);
+                       var element_expr = new ElementAccess (member_access (array_var), b.source_reference);
                        for (int i=0; i < dim; i++) {
-                               element_expr.append_index (member_access (indices[i].name, array_var));
+                               element_expr.append_index (member_access (indices[i]));
                        }
                        element_variant = serialize_expression (array_type.element_type, element_expr);
                }
-               current_block = old_block;
 
-               var builder_add = new MethodCall (member_access (builder.name+".add_value", array_var), 
array_var.source_reference);
+               var builder_add = new MethodCall (member_access (builder+".add_value"), b.source_reference);
                builder_add.add_argument (element_variant);
-               forbody.add_statement (new ExpressionStatement (builder_add, array_var.source_reference));
+               b.add_expression (builder_add);
+               b.close ();
 
-               var forstmt = new ForStatement (forcond, forbody, array_var.source_reference);
-               forstmt.add_iterator (foriter);
-               if (dim == 1) {
-                       context.analyzer.get_current_block (current_statement).insert_before 
(current_statement, forstmt);
-                       check (forstmt);
-               } else {
-                       current_block.add_statement (forstmt);
-               }
-
-               var builder_end = new MethodCall (member_access (builder.name+".end", array_var), 
array_var.source_reference);
+               var builder_end = new MethodCall (member_access (builder+".end"), b.source_reference);
                return builder_end;
        }
 
@@ -253,22 +231,18 @@ public class Vala.GVariantTransformer : CodeTransformer {
                        return;
                }
 
-               current_statement = get_current_statement (expr);
+               b = new CodeBuilder (context, expr.parent_statement, expr.source_reference);
                var old_parent_node = expr.parent_node;
                var target_type = expr.target_type.copy ();
 
-               current_block = context.analyzer.get_current_block (current_statement);
                Expression result = serialize_expression (expr.value_type, expr);
 
                result.target_type = target_type;
+               context.analyzer.replaced_nodes.add (expr);
                old_parent_node.replace_expression (expr, result);
-               check (result);
-       }
-
-       Statement get_current_statement (CodeNode node) {
-               while (!(node is Statement)) {
-                       node = node.parent_node;
+               foreach (var node in b.check_nodes) {
+                       check (node);
                }
-               return (Statement) node;
+               check (result);
        }
 }
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 91c457282..835fa69aa 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -48,6 +48,7 @@ libvala_la_VALASOURCES = \
        valacharacterliteral.vala \
        valaclass.vala \
        valaclasstype.vala \
+       valacodebuilder.vala \
        valacodecontext.vala \
        valacodegenerator.vala \
        valacodenode.vala \
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
new file mode 100644
index 000000000..f08fc92bb
--- /dev/null
+++ b/vala/valacodebuilder.vala
@@ -0,0 +1,154 @@
+/* valacodebuilder.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>
+ */
+
+using GLib;
+
+public class Vala.CodeBuilder {
+       Block current_block;
+       Statement insert_statement;
+       Block insert_block;
+       public SourceReference source_reference;
+       ArrayList<Statement> statement_stack = new ArrayList<Statement> ();
+       public ArrayList<CodeNode> check_nodes = new ArrayList<CodeNode> ();
+
+       public CodeBuilder (CodeContext context, Statement insert_statement, SourceReference 
source_reference) {
+               this.current_block = new Block (source_reference);
+               this.insert_statement = insert_statement;
+               this.insert_block = context.analyzer.get_insert_block (insert_statement);
+               this.source_reference = source_reference;
+
+               var statement_block = context.analyzer.get_current_block (insert_statement);
+               statement_block.insert_before (insert_statement, current_block);
+               check_nodes.add (current_block);
+       }
+
+       public void open_block () {
+               statement_stack.add (current_block);
+               var parent_block = current_block;
+
+               current_block = new Block (source_reference);
+
+               parent_block.add_statement (current_block);
+       }
+
+       public void open_if (Expression condition) {
+               statement_stack.add (current_block);
+               var parent_block = current_block;
+
+               current_block = new Block (source_reference);
+
+               var stmt = new IfStatement (condition, current_block, null, source_reference);
+               statement_stack.add (stmt);
+
+               parent_block.add_statement (stmt);
+       }
+
+       public void add_else () {
+               current_block = new Block (source_reference);
+
+               var stmt = (IfStatement) statement_stack[statement_stack.size-1];
+               assert (stmt.false_statement == null);
+               stmt.false_statement = current_block;
+       }
+
+       public void else_if (Expression condition) {
+               var parent_if = (IfStatement) statement_stack[statement_stack.size - 1];
+               assert (parent_if.false_statement == null);
+
+               statement_stack.remove_at (statement_stack.size - 1);
+
+               current_block = new Block (source_reference);
+
+               var stmt = new IfStatement (condition, current_block, null, source_reference);
+               var block = new Block (source_reference);
+               block.add_statement (stmt);
+               parent_if.false_statement = block;
+               statement_stack.add (stmt);
+       }
+
+       public void open_while (Expression condition) {
+               statement_stack.add (current_block);
+               var parent_block = current_block;
+
+               current_block = new Block (source_reference);
+
+               var stmt = new WhileStatement (condition, current_block, source_reference);
+               parent_block.add_statement (stmt);
+       }
+
+       public void open_for (Expression? initializer, Expression condition, Expression? iterator) {
+               statement_stack.add (current_block);
+               var parent_block = current_block;
+
+               current_block = new Block (source_reference);
+
+               var stmt = new ForStatement (condition, current_block, source_reference);
+               if (initializer != null) {
+                       stmt.add_initializer (initializer);
+               }
+               if (iterator != null) {
+                       stmt.add_iterator (iterator);
+               }
+
+               parent_block.add_statement (stmt);
+       }
+
+       public void add_statement (Statement statement) {
+               current_block.add_statement (statement);
+       }
+
+       public void add_expression (Expression expression) {
+               add_statement (new ExpressionStatement (expression, source_reference));
+       }
+
+       public void add_assignment (Expression left, Expression right) {
+               add_expression (new Assignment (left, right, AssignmentOperator.SIMPLE, source_reference));
+       }
+
+       public void add_return (Expression? expression = null) {
+               add_statement (new ReturnStatement (expression, source_reference));
+       }
+
+       public void add_break () {
+               add_statement (new BreakStatement (source_reference));
+       }
+
+       public void add_continue () {
+               add_statement (new ContinueStatement (source_reference));
+       }
+
+       public string add_temp_declaration (DataType? type, Expression? initializer) {
+               var local = new LocalVariable (type, CodeNode.get_temp_name (), initializer, 
source_reference);
+               var stmt = new DeclarationStatement (local, source_reference);
+               insert_block.insert_before (insert_statement, stmt);
+               check_nodes.insert (0, stmt);
+               return local.name;
+       }
+
+       public void close () {
+               do {
+                       var top = statement_stack[statement_stack.size - 1];
+                       statement_stack.remove_at (statement_stack.size - 1);
+                       current_block = top as Block;
+               } while (current_block == null);
+       }
+}


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