[vala/wip/transform: 12/48] Code builder



commit fb4736bff19bfc263b6a2a655dd254aaa453d12a
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 ++++++++++++++++++++++++++++++++++
 vala/valadeletestatement.vala        |    2 +-
 4 files changed, 185 insertions(+), 56 deletions(-)
---
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index a0be0e8..af6fa2e 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) {
 		foreach (BasicTypeInfo info in basic_types) {
@@ -59,22 +58,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;
 	}
@@ -161,74 +160,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;
 	}
 
@@ -251,22 +229,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 6b3a79d..d0eb485 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -34,6 +34,7 @@ libvalacore_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 0000000..f08fc92
--- /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);
+	}
+}
diff --git a/vala/valadeletestatement.vala b/vala/valadeletestatement.vala
index 5f639d4..ff3ff68 100644
--- a/vala/valadeletestatement.vala
+++ b/vala/valadeletestatement.vala
@@ -51,7 +51,7 @@ public class Vala.DeleteStatement : CodeNode, Statement {
 	}
 
 	public override void replace_expression (Expression old_node, Expression new_node) {
-		if (expression = old_node) {
+		if (expression == old_node) {
 			expression = new_node;
 		}
 	}



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