patch allows:

Var to be used in foreach

or

Existing local variable (in scope)

This patch is needed for genie although it may be useful for vala too...

jamie
Index: vala/valasemanticanalyzer.vala
===================================================================
--- vala/valasemanticanalyzer.vala	(revision 1419)
+++ vala/valasemanticanalyzer.vala	(working copy)
@@ -1016,7 +1016,7 @@
 			stmt.error = true;
 			Report.error (stmt.condition.source_reference, "Condition must be boolean");
 			return;
-		}
+		} 
 	}
 
 	public override void visit_for_statement (ForStatement stmt) {
@@ -1035,21 +1035,31 @@
 		}
 	}
 
-	public override void visit_foreach_statement (ForeachStatement stmt) {
-		current_source_file.add_type_dependency (stmt.type_reference, SourceFileDependencyType.SOURCE);
 
-		stmt.element_variable = new LocalVariable (stmt.type_reference, stmt.variable_name);
+	LocalVariable? get_local_variable_in_scope (string variable_name) {
+		Symbol symbol_reference = null;
+		var sym = current_symbol;
+		LocalVariable result = null;
+		
+		
+		while (sym != null && symbol_reference == null && !(symbol_reference is LocalVariable)) {
+			symbol_reference = symbol_lookup_inherited (sym, variable_name);
+			sym = sym.parent_symbol;
+		}
+		
+		result = (LocalVariable) symbol_reference;
+		
+		return result;	
+	}
 
-		stmt.body.scope.add (stmt.variable_name, stmt.element_variable);
+	public override void visit_foreach_statement (ForeachStatement stmt) {
 
-		stmt.body.add_local_variable (stmt.element_variable);
-		stmt.element_variable.active = true;
-
 		stmt.owner = current_symbol.scope;
 		current_symbol = stmt;
 
-		stmt.accept_children (this);
-
+		/* handle collection first in case we need to infer the data type of the type reference */
+		stmt.accept_collection (this);
+		
 		foreach (LocalVariable local in stmt.get_local_variables ()) {
 			local.active = false;
 		}
@@ -1067,11 +1077,7 @@
 		}
 
 		var collection_type = stmt.collection.value_type.copy ();
-		stmt.collection_variable = new LocalVariable (collection_type, "%s_collection".printf (stmt.variable_name));
-
-		stmt.add_local_variable (stmt.collection_variable);
-		stmt.collection_variable.active = true;
-	
+		
 		DataType element_data_type = null;
 		bool need_type_check = false;
 	
@@ -1108,7 +1114,42 @@
 			Report.error (stmt.source_reference, "Collection not iterable");
 			return;
 		}
+		
+	
+		/* can be null if inference or existing local variable in scope is availble */
+		if (stmt.type_reference == null) {
+		
+			var sym = get_local_variable_in_scope (stmt.variable_name);
 
+			/* means no existing variable with that name found so create a new local var */
+			if (sym == null) { 
+				stmt.type_reference = element_data_type.copy ();
+				current_source_file.add_type_dependency (stmt.type_reference, SourceFileDependencyType.SOURCE);
+				stmt.element_variable = new LocalVariable (stmt.type_reference, stmt.variable_name);
+				stmt.body.scope.add (stmt.variable_name, stmt.element_variable);
+				stmt.body.add_local_variable (stmt.element_variable);
+				stmt.element_variable.active = true;
+			} else {
+				stmt.element_variable = sym;
+				stmt.type_reference = sym.variable_type;
+				need_type_check = true;
+			}
+			
+		}  else {
+			current_source_file.add_type_dependency (stmt.type_reference, SourceFileDependencyType.SOURCE);
+			stmt.element_variable = new LocalVariable (stmt.type_reference, stmt.variable_name);
+			stmt.body.scope.add (stmt.variable_name, stmt.element_variable);
+			stmt.body.add_local_variable (stmt.element_variable);
+			stmt.element_variable.active = true;
+		}
+		
+		stmt.accept_children (this);
+		
+		stmt.collection_variable = new LocalVariable (collection_type, "%s_collection".printf (stmt.variable_name));
+
+		stmt.add_local_variable (stmt.collection_variable);
+		stmt.collection_variable.active = true;
+
 		if (need_type_check && element_data_type != null) {
 			/* allow implicit upcasts ? */
 			if (!element_data_type.compatible (stmt.type_reference)) {
@@ -1486,11 +1527,10 @@
 		// don't call g_object_ref_sink on inner and outer expression
 		expr.value_type.floating_reference = false;
 	}
-
+	
 	public override void visit_member_access (MemberAccess expr) {
 		Symbol base_symbol = null;
 		bool may_access_instance_members = false;
-
 		expr.symbol_reference = null;
 
 		if (expr.inner == null) {
Index: vala/valaforeachstatement.vala
===================================================================
--- vala/valaforeachstatement.vala	(revision 1419)
+++ vala/valaforeachstatement.vala	(working copy)
@@ -30,11 +30,13 @@
 	/**
 	 * Specifies the element type.
 	 */
-	public DataType type_reference {
+	public DataType? type_reference {
 		get { return _data_type; }
 		set {
 			_data_type = value;
-			_data_type.parent_node = this;
+			if (_data_type != null) {
+				_data_type.parent_node = this;
+			}
 		}
 	}
 	
@@ -98,7 +100,7 @@
 	 * @param source reference to source code
 	 * @return       newly created foreach statement
 	 */
-	public ForeachStatement (DataType type_reference, string variable_name, Expression collection, Block body, SourceReference source_reference) {
+	public ForeachStatement (DataType? type_reference, string variable_name, Expression collection, Block body, SourceReference source_reference) {
 		this.variable_name = variable_name;
 		this.collection = collection;
 		this.body = body;
@@ -111,13 +113,22 @@
 	}
 
 	public override void accept_children (CodeVisitor visitor) {
-		type_reference.accept (visitor);
-
-		collection.accept (visitor);
-		visitor.visit_end_full_expression (collection);
-
+	
+		if (type_reference == null) {
+			collection.accept (visitor);
+		} else {
+		
+			type_reference.accept (visitor);
+			collection.accept (visitor);
+			visitor.visit_end_full_expression (collection);
+		}
 		body.accept (visitor);
+		
 	}
+	
+	public void accept_collection (CodeVisitor visitor) {
+		collection.accept (visitor);
+	}
 
 	public override void replace_expression (Expression old_node, Expression new_node) {
 		if (collection == old_node) {
_______________________________________________
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list

Reply via email to