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