vala r2083 - in trunk: . gobject vala



Author: juergbi
Date: Sat Nov 29 12:20:30 2008
New Revision: 2083
URL: http://svn.gnome.org/viewvc/vala?rev=2083&view=rev

Log:
2008-11-29  JÃrg Billeter  <j bitron ch>

	* vala/Makefile.am:
	* vala/valablock.vala:
	* vala/valacodenode.vala:
	* vala/valaconditionalexpression.vala:
	* vala/valadeclarationstatement.vala:
	* vala/valaexpression.vala:
	* vala/valanullchecker.vala:
	* vala/valastatementlist.vala:
	* gobject/valaccodebasemodule.vala:
	* gobject/valaccodegenerator.vala:
	* gobject/valaccodemodule.vala:

	Convert ternary conditionals into if statements,
	fixes bug 543870 and bug 554594


Added:
   trunk/vala/valastatementlist.vala
Modified:
   trunk/ChangeLog
   trunk/gobject/valaccodebasemodule.vala
   trunk/gobject/valaccodegenerator.vala
   trunk/gobject/valaccodemodule.vala
   trunk/vala/Makefile.am
   trunk/vala/valablock.vala
   trunk/vala/valacodenode.vala
   trunk/vala/valaconditionalexpression.vala
   trunk/vala/valadeclarationstatement.vala
   trunk/vala/valaexpression.vala
   trunk/vala/valanullchecker.vala

Modified: trunk/gobject/valaccodebasemodule.vala
==============================================================================
--- trunk/gobject/valaccodebasemodule.vala	(original)
+++ trunk/gobject/valaccodebasemodule.vala	Sat Nov 29 12:20:30 2008
@@ -135,6 +135,8 @@
 
 	public Set<string> wrappers;
 
+	Map<string,string> variable_name_map = new HashMap<string,string> (str_hash, str_equal);
+
 	public CCodeBaseModule (CCodeGenerator codegen, CCodeModule? next) {
 		base (codegen, next);
 
@@ -1276,7 +1278,14 @@
 	}
 
 	public string get_variable_cname (string name) {
-		if (c_keywords.contains (name)) {
+		if (name[0] == '.') {
+			// compiler-internal variable
+			if (!variable_name_map.contains (name)) {
+				variable_name_map.set (name, "_tmp%d".printf (next_temp_var_id));
+				next_temp_var_id++;
+			}
+			return variable_name_map.get (name);
+		} else if (c_keywords.contains (name)) {
 			return name + "_";
 		} else {
 			return name;
@@ -2886,10 +2895,6 @@
 		expr.ccodenode = create_type_check (expr.expression.ccodenode, expr.type_reference);
 	}
 
-	public override void visit_conditional_expression (ConditionalExpression expr) {
-		expr.ccodenode = new CCodeConditionalExpression ((CCodeExpression) expr.condition.ccodenode, (CCodeExpression) expr.true_expression.ccodenode, (CCodeExpression) expr.false_expression.ccodenode);
-	}
-
 	public override void visit_lambda_expression (LambdaExpression l) {
 		// use instance position from delegate
 		var dt = (DelegateType) l.target_type;

Modified: trunk/gobject/valaccodegenerator.vala
==============================================================================
--- trunk/gobject/valaccodegenerator.vala	(original)
+++ trunk/gobject/valaccodegenerator.vala	Sat Nov 29 12:20:30 2008
@@ -323,10 +323,6 @@
 		head.visit_type_check (expr);
 	}
 
-	public override void visit_conditional_expression (ConditionalExpression expr) {
-		head.visit_conditional_expression (expr);
-	}
-
 	public override void visit_lambda_expression (LambdaExpression l) {
 		head.visit_lambda_expression (l);
 	}

Modified: trunk/gobject/valaccodemodule.vala
==============================================================================
--- trunk/gobject/valaccodemodule.vala	(original)
+++ trunk/gobject/valaccodemodule.vala	Sat Nov 29 12:20:30 2008
@@ -320,10 +320,6 @@
 		next.visit_type_check (expr);
 	}
 
-	public virtual void visit_conditional_expression (ConditionalExpression expr) {
-		next.visit_conditional_expression (expr);
-	}
-
 	public virtual void visit_lambda_expression (LambdaExpression l) {
 		next.visit_lambda_expression (l);
 	}

Modified: trunk/vala/Makefile.am
==============================================================================
--- trunk/vala/Makefile.am	(original)
+++ trunk/vala/Makefile.am	Sat Nov 29 12:20:30 2008
@@ -122,6 +122,7 @@
 	valasourcelocation.vala \
 	valasourcereference.vala \
 	valastatement.vala \
+	valastatementlist.vala \
 	valastringliteral.vala \
 	valastruct.vala \
 	valaswitchlabel.vala \

Modified: trunk/vala/valablock.vala
==============================================================================
--- trunk/vala/valablock.vala	(original)
+++ trunk/vala/valablock.vala	Sat Nov 29 12:20:30 2008
@@ -64,7 +64,18 @@
 	 * @return statement list
 	 */
 	public Gee.List<Statement> get_statements () {
-		return new ReadOnlyList<Statement> (statement_list);
+		var list = new ArrayList<Statement> ();
+		foreach (Statement stmt in statement_list) {
+			var stmt_list = stmt as StatementList;
+			if (stmt_list != null) {
+				for (int i = 0; i < stmt_list.length; i++) {
+					list.add (stmt_list.get (i));
+				}
+			} else {
+				list.add (stmt);
+			}
+		}
+		return list;
 	}
 	
 	/**
@@ -75,7 +86,11 @@
 	public void add_local_variable (LocalVariable local) {
 		local_variables.add (local);
 	}
-	
+
+	public void remove_local_variable (LocalVariable local) {
+		local_variables.remove (local);
+	}
+
 	/**
 	 * Returns a copy of the list of local variables.
 	 *
@@ -103,22 +118,60 @@
 		checked = true;
 
 		owner = analyzer.current_symbol.scope;
+
+		var old_symbol = analyzer.current_symbol;
 		analyzer.current_symbol = this;
 
-		foreach (Statement stmt in statement_list) {
-			stmt.check (analyzer);
+		for (int i = 0; i < statement_list.size; i++) {
+			statement_list[i].check (analyzer);
 		}
 
 		foreach (LocalVariable local in get_local_variables ()) {
 			local.active = false;
 		}
 
-		foreach (Statement stmt in get_statements ()) {
+		foreach (Statement stmt in statement_list) {
 			add_error_types (stmt.get_error_types ());
 		}
 
-		analyzer.current_symbol = analyzer.current_symbol.parent_symbol;
+		analyzer.current_symbol = old_symbol;
 
 		return !error;
 	}
+
+	public void insert_before (Statement stmt, Statement new_stmt) {
+		for (int i = 0; i < statement_list.size; i++) {
+			var stmt_list = statement_list[i] as StatementList;
+			if (stmt_list != null) {
+				for (int j = 0; j < stmt_list.length; j++) {
+					if (stmt_list.get (j) == stmt) {
+						stmt_list.insert (j, new_stmt);
+						break;
+					}
+				}
+			} else if (statement_list[i] == stmt) {
+				stmt_list = new StatementList (source_reference);
+				stmt_list.add (new_stmt);
+				stmt_list.add (stmt);
+				statement_list[i] = stmt_list;
+			}
+		}
+	}
+
+	public void replace_statement (Statement old_stmt, Statement new_stmt) {
+		for (int i = 0; i < statement_list.size; i++) {
+			var stmt_list = statement_list[i] as StatementList;
+			if (stmt_list != null) {
+				for (int j = 0; j < stmt_list.length; j++) {
+					if (stmt_list.get (j) == old_stmt) {
+						stmt_list.set (j, new_stmt);
+						break;
+					}
+				}
+			} else if (statement_list[i] == old_stmt) {
+				statement_list[i] = new_stmt;
+				break;
+			}
+		}
+	}
 }

Modified: trunk/vala/valacodenode.vala
==============================================================================
--- trunk/vala/valacodenode.vala	(original)
+++ trunk/vala/valacodenode.vala	Sat Nov 29 12:20:30 2008
@@ -83,6 +83,8 @@
 
 	private CCodeNode? _ccodenode;
 
+	static int last_temp_nr = 0;
+
 	/**
 	 * Specifies the exceptions that can be thrown by this node or a child node
 	 */
@@ -183,4 +185,8 @@
 
 	public virtual void get_used_variables (Collection<LocalVariable> collection) {
 	}
+
+	public string get_temp_name () {
+		return "." + (++last_temp_nr).to_string ();
+	}
 }

Modified: trunk/vala/valaconditionalexpression.vala
==============================================================================
--- trunk/vala/valaconditionalexpression.vala	(original)
+++ trunk/vala/valaconditionalexpression.vala	Sat Nov 29 12:20:30 2008
@@ -29,18 +29,46 @@
 	/**
 	 * The condition.
 	 */
-	public Expression condition { get; set; }
-	
+	public Expression condition {
+		get {
+			return _condition;
+		}
+		set {
+			_condition = value;
+			_condition.parent_node = this;
+		}
+	}
+
 	/**
 	 * The expression to be evaluated if the condition holds.
 	 */
-	public Expression true_expression { get; set; }
+	public Expression true_expression {
+		get {
+			return _true_expression;
+		}
+		set {
+			_true_expression = value;
+			_true_expression.parent_node = this;
+		}
+	}
 
 	/**
 	 * The expression to be evaluated if the condition doesn't hold.
 	 */
-	public Expression false_expression { get; set; }
-	
+	public Expression false_expression {
+		get {
+			return _false_expression;
+		}
+		set {
+			_false_expression = value;
+			_false_expression.parent_node = this;
+		}
+	}
+
+	Expression _condition;
+	Expression _true_expression;
+	Expression _false_expression;
+
 	/**
 	 * Creates a new conditional expression.
 	 *
@@ -77,17 +105,35 @@
 
 		checked = true;
 
-		if (!condition.check (analyzer) || !false_expression.check (analyzer) || !true_expression.check (analyzer)) {
-			return false;
-		}
+		// convert ternary expression into if statement
+		// required for flow analysis and exception handling
 
-		if (!condition.value_type.compatible (analyzer.bool_type)) {
-			error = true;
-			Report.error (condition.source_reference, "Condition must be boolean");
+		string temp_name = get_temp_name ();
+
+		true_expression.target_type = target_type;
+		false_expression.target_type = target_type;
+
+		var true_local = new LocalVariable (null, temp_name, true_expression, true_expression.source_reference);
+		var true_block = new Block (true_expression.source_reference);
+		var true_decl = new DeclarationStatement (true_local, true_expression.source_reference);
+		true_block.add_statement (true_decl);
+
+		var false_local = new LocalVariable (null, temp_name, false_expression, false_expression.source_reference);
+		var false_block = new Block (false_expression.source_reference);
+		var false_decl = new DeclarationStatement (false_local, false_expression.source_reference);
+		false_block.add_statement (false_decl);
+
+		var if_stmt = new IfStatement (condition, true_block, false_block, source_reference);
+		if (!if_stmt.check (analyzer)) {
 			return false;
 		}
 
-		/* FIXME: support memory management */
+		true_expression = true_local.initializer;
+		false_expression = false_local.initializer;
+
+		true_block.remove_local_variable (true_local);
+		false_block.remove_local_variable (false_local);
+
 		if (false_expression.value_type.compatible (true_expression.value_type)) {
 			value_type = true_expression.value_type.copy ();
 		} else if (true_expression.value_type.compatible (false_expression.value_type)) {
@@ -98,6 +144,33 @@
 			return false;
 		}
 
-		return !error;
+		value_type.value_owned = (true_expression.value_type.value_owned || false_expression.value_type.value_owned);
+
+		var local = new LocalVariable (value_type, temp_name, null, source_reference);
+		var decl = new DeclarationStatement (local, source_reference);
+		decl.check (analyzer);
+
+		true_expression.target_type = value_type;
+		false_expression.target_type = value_type;
+
+		var true_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, true_expression.source_reference), true_expression, AssignmentOperator.SIMPLE, true_expression.source_reference), true_expression.source_reference);
+		true_stmt.check (analyzer);
+
+		var false_stmt = new ExpressionStatement (new Assignment (new MemberAccess.simple (local.name, false_expression.source_reference), false_expression, AssignmentOperator.SIMPLE, false_expression.source_reference), false_expression.source_reference);
+		false_stmt.check (analyzer);
+
+		true_block.replace_statement (true_decl, true_stmt);
+		false_block.replace_statement (false_decl, false_stmt);
+
+		insert_statement ((Block) analyzer.current_symbol, decl);
+		insert_statement ((Block) analyzer.current_symbol, if_stmt);
+
+		var ma = new MemberAccess.simple (local.name, source_reference);
+		ma.target_type = target_type;
+		ma.check (analyzer);
+
+		parent_node.replace_expression (this, ma);
+
+		return true;
 	}
 }

Modified: trunk/vala/valadeclarationstatement.vala
==============================================================================
--- trunk/vala/valadeclarationstatement.vala	(original)
+++ trunk/vala/valadeclarationstatement.vala	Sat Nov 29 12:20:30 2008
@@ -29,7 +29,19 @@
 	/**
 	 * The local variable or constant declaration.
 	 */
-	public Symbol declaration { get; set; }
+	public Symbol declaration {
+		get {
+			return _declaration;
+		}
+		set {
+			_declaration = value;
+			if (_declaration != null) {
+				_declaration.parent_node = this;
+			}
+		}
+	}
+
+	Symbol _declaration;
 
 	/**
 	 * Creates a new declaration statement.

Modified: trunk/vala/valaexpression.vala
==============================================================================
--- trunk/vala/valaexpression.vala	(original)
+++ trunk/vala/valaexpression.vala	Sat Nov 29 12:20:30 2008
@@ -84,4 +84,25 @@
 	public virtual bool is_non_null () {
 		return false;
 	}
+
+	public Statement? parent_statement {
+		get {
+			var expr = parent_node as Expression;
+			var stmt = parent_node as Statement;
+			var local = parent_node as LocalVariable;
+			if (stmt != null) {
+				return stmt;
+			} else if (expr != null) {
+				return expr.parent_statement;
+			} else if (local != null) {
+				return (Statement) local.parent_node;
+			} else {
+				return null;
+			}
+		}
+	}
+
+	public void insert_statement (Block block, Statement stmt) {
+		block.insert_before (parent_statement, stmt);
+	}
 }

Modified: trunk/vala/valanullchecker.vala
==============================================================================
--- trunk/vala/valanullchecker.vala	(original)
+++ trunk/vala/valanullchecker.vala	Sat Nov 29 12:20:30 2008
@@ -235,10 +235,6 @@
 		expr.accept_children (this);
 	}
 
-	public override void visit_conditional_expression (ConditionalExpression expr) {
-		check_non_null (expr.condition);
-	}
-
 	public override void visit_lambda_expression (LambdaExpression l) {
 		l.accept_children (this);
 	}

Added: trunk/vala/valastatementlist.vala
==============================================================================
--- (empty file)
+++ trunk/vala/valastatementlist.vala	Sat Nov 29 12:20:30 2008
@@ -0,0 +1,57 @@
+/* valastatementlist.vala
+ *
+ * Copyright (C) 2008  JÃrg Billeter
+ *
+ * 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:
+ * 	JÃrg Billeter <j bitron ch>
+ */
+
+using Gee;
+
+public class Vala.StatementList : CodeNode, Statement {
+	private Gee.List<Statement> list = new ArrayList<Statement> ();
+
+	public int length {
+		get { return list.size; }
+	}
+
+	public StatementList (SourceReference source_reference) {
+		this.source_reference = source_reference;
+	}
+
+	public Statement get (int index) {
+		return list.get (index);
+	}
+
+	public void set (int index, Statement stmt) {
+		list.set (index, stmt);
+	}
+
+	public void add (Statement stmt) {
+		list.add (stmt);
+	}
+
+	public void insert (int index, Statement stmt) {
+		list.insert (index, stmt);
+	}
+
+	public override void accept (CodeVisitor visitor) {
+		foreach (Statement stmt in list) {
+			stmt.accept (visitor);
+		}
+	}
+}



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