2007-06-20 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / statement.cs
index aaca8791ff31d0bbe9771ee2b6c64238a792c520..207cf7bdc70a3094169c02bd3ad59728084d6a15 100644 (file)
@@ -1243,7 +1243,7 @@ namespace Mono.CSharp {
                public bool Resolve (EmitContext ec)
                {
                        if (VariableType == null) {
-                               TypeExpr texpr = Type.ResolveAsTypeTerminal (ec, false);
+                               TypeExpr texpr = Type.ResolveAsContextualType (ec, false);
                                if (texpr == null)
                                        return false;
                                
@@ -3915,22 +3915,7 @@ namespace Mono.CSharp {
                                return false;
                        }
                        
-                       TypeExpr texpr = null;
-                       if (type is VarExpr) {
-                               Unary u = ((Pair) declarators[0]).Second as Unary;
-                               if (u == null)
-                                       return false;
-                               
-                               Expression e = u.Expr.Resolve (ec);
-                               if (e == null || e.Type == null)
-                                       return false;
-                               
-                               Type t = TypeManager.GetPointerType (e.Type);
-                               texpr = new TypeExpression (t, loc);
-                       }
-                       else
-                               texpr = type.ResolveAsTypeTerminal (ec, false);
-
+                       TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false);
                        if (texpr == null)
                                return false;
 
@@ -3948,9 +3933,6 @@ namespace Mono.CSharp {
                                LocalInfo vi = (LocalInfo) p.First;
                                Expression e = (Expression) p.Second;
                                
-                               if (type is VarExpr)
-                                       vi.VariableType = expr_type;
-
                                vi.VariableInfo.SetAssigned (ec);
                                vi.SetReadOnlyContext (LocalInfo.ReadOnlyContext.Fixed);
 
@@ -4406,7 +4388,7 @@ namespace Mono.CSharp {
                Type expr_type;
                Expression [] resolved_vars;
                Expression [] converted_vars;
-               ExpressionStatement [] assign;
+               Expression [] assign;
                TemporaryVariable local_copy;
                
                public Using (object expression_or_block, Statement stmt, Location l)
@@ -4421,97 +4403,52 @@ namespace Mono.CSharp {
                //
                bool ResolveLocalVariableDecls (EmitContext ec)
                {
-                       int i = 0;
+                       resolved_vars = new Expression[var_list.Count];
+                       assign = new Expression [var_list.Count];
+                       converted_vars = new Expression[var_list.Count];
 
-                       TypeExpr texpr = null;
-                       
-                       if (expr is VarExpr) {
-                               Expression e = ((Expression)((DictionaryEntry)var_list[0]).Value).Resolve (ec);
-                               if (e == null || e.Type == null)
-                                       return false;
-                               texpr = new TypeExpression (e.Type, loc);
-                       }
-                       else
-                               texpr = expr.ResolveAsTypeTerminal (ec, false);
-
-                       if (texpr == null)
-                               return false;
-
-                       expr_type = texpr.Type;
-
-                       //
-                       // The type must be an IDisposable or an implicit conversion
-                       // must exist.
-                       //
-                       converted_vars = new Expression [var_list.Count];
-                       resolved_vars = new Expression [var_list.Count];
-                       assign = new ExpressionStatement [var_list.Count];
-
-                       bool need_conv = !TypeManager.ImplementsInterface (
-                               expr_type, TypeManager.idisposable_type);
-
-                       foreach (DictionaryEntry e in var_list){
+                       for (int i = 0; i < assign.Length; ++i) {
+                               DictionaryEntry e = (DictionaryEntry) var_list [i];
                                Expression var = (Expression) e.Key;
-                               
-                               if (expr is VarExpr) {
-                                       LocalVariableReference l = var as LocalVariableReference;
-                                       ((LocalInfo)l.Block.Variables[l.Name]).VariableType = expr_type;
-                                       ((VarExpr)expr).Handled = true;
-                               }
+                               Expression new_expr = (Expression) e.Value;
 
-                               var = var.ResolveLValue (ec, new EmptyExpression (), loc);
-                               if (var == null)
+                               Expression a = new Assign (var, new_expr, loc);
+                               a = a.Resolve (ec);
+                               if (a == null)
                                        return false;
 
                                resolved_vars [i] = var;
+                               assign [i] = a;
 
-                               if (!need_conv) {
-                                       i++;
+                               if (TypeManager.ImplementsInterface (a.Type, TypeManager.idisposable_type)) {
+                                       converted_vars [i] = var;
                                        continue;
                                }
 
-                               converted_vars [i] = Convert.ImplicitConversion (
-                                       ec, var, TypeManager.idisposable_type, loc);
-
-                               if (converted_vars [i] == null) {
-                                       Error_IsNotConvertibleToIDisposable ();
+                               a = Convert.ImplicitConversion (ec, a, TypeManager.idisposable_type, var.Location);
+                               if (a == null) {
+                                       Error_IsNotConvertibleToIDisposable (var);
                                        return false;
                                }
 
-                               i++;
-                       }
-
-                       i = 0;
-                       foreach (DictionaryEntry e in var_list){
-                               Expression var = resolved_vars [i];
-                               Expression new_expr = (Expression) e.Value;
-                               Expression a;
-
-                               a = new Assign (var, new_expr, loc);
-                               a = a.Resolve (ec);
-                               if (a == null)
-                                       return false;
-
-                               if (!need_conv)
-                                       converted_vars [i] = var;
-                               assign [i] = (ExpressionStatement) a;
-                               i++;
+                               converted_vars [i] = a;
                        }
 
                        return true;
                }
 
-               void Error_IsNotConvertibleToIDisposable ()
+               static void Error_IsNotConvertibleToIDisposable (Expression expr)
                {
-                       Report.Error (1674, loc, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
-                               TypeManager.CSharpName (expr_type));
+                       Report.SymbolRelatedToPreviousError (expr.Type);
+                       Report.Error (1674, expr.Location, "`{0}': type used in a using statement must be implicitly convertible to `System.IDisposable'",
+                               expr.GetSignatureForError ());
                }
 
                bool ResolveExpression (EmitContext ec)
                {
                        if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)){
                                if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) {
-                                       Error_IsNotConvertibleToIDisposable ();
+                                       Error_IsNotConvertibleToIDisposable (expr);
                                        return false;
                                }
                        }
@@ -4531,7 +4468,7 @@ namespace Mono.CSharp {
                        int i = 0;
 
                        for (i = 0; i < assign.Length; i++) {
-                               assign [i].EmitStatement (ec);
+                               assign [i].Emit (ec);
 
                                if (emit_finally)
                                        ig.BeginExceptionBlock ();
@@ -4755,58 +4692,11 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       if (type is VarExpr) {
-                               Type element_type = null;
-                               if (TypeManager.HasElementType (expr.Type))
-                                       element_type = TypeManager.GetElementType (expr.Type);
-                               else {
-                                       MethodGroupExpr mg = Expression.MemberLookup (
-                                               ec.ContainerType, expr.Type, "GetEnumerator", MemberTypes.Method,
-                                               Expression.AllBindingFlags, loc) as MethodGroupExpr;
-                                       
-                                       if (mg == null)
-                                                       return false;
-                                       
-                                       MethodInfo get_enumerator = null;
-                                       foreach (MethodInfo mi in mg.Methods) {
-                                               if (TypeManager.GetParameterData (mi).Count != 0)
-                                                       continue;
-                                               if ((mi.Attributes & MethodAttributes.Public) != MethodAttributes.Public)
-                                                       continue;
-                                               if (CollectionForeach.IsOverride (mi))
-                                                       continue;
-                                               get_enumerator = mi;
-                                       }
-                                       
-                                       if (get_enumerator == null)
-                                               return false;
-                                       
-                                       PropertyInfo pi = TypeManager.GetProperty (get_enumerator.ReturnType, "Current");
-                                       
-                                       if (pi == null)
-                                               return false;
-                                               
-                                       element_type = pi.PropertyType;
-                               }
-
-                               type = new TypeLookupExpression (element_type.AssemblyQualifiedName);
-                
-                               LocalVariableReference lv = variable as LocalVariableReference;
-                               ((LocalInfo)lv.Block.Variables[lv.Name]).VariableType = element_type;
-                       }
-
-                       Constant c = expr as Constant;
-                       if (c != null && c.GetValue () == null) {
+                       if (expr.Type == TypeManager.null_type) {
                                Report.Error (186, loc, "Use of null is not valid in this context");
                                return false;
                        }
 
-                       TypeExpr texpr = type.ResolveAsTypeTerminal (ec, false);
-                       if (texpr == null)
-                               return false;
-
-                       Type var_type = texpr.Type;
-
                        if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
                                Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
                                        expr.ExprClassName);
@@ -4827,13 +4717,12 @@ namespace Mono.CSharp {
                        }
 
                        if (expr.Type.IsArray) {
-                               array = new ArrayForeach (var_type, variable, expr, statement, loc);
+                               array = new ArrayForeach (type, variable, expr, statement, loc);
                                return array.Resolve (ec);
-                       } else {
-                               collection = new CollectionForeach (
-                                       var_type, variable, expr, statement, loc);
-                               return collection.Resolve (ec);
                        }
+                       
+                       collection = new CollectionForeach (type, variable, expr, statement, loc);
+                       return collection.Resolve (ec);
                }
 
                protected override void DoEmit (EmitContext ec)
@@ -4881,7 +4770,7 @@ namespace Mono.CSharp {
                        Expression variable, expr, conv;
                        Statement statement;
                        Type array_type;
-                       Type var_type;
+                       Expression var_type;
                        TemporaryVariable[] lengths;
                        ArrayCounter[] counter;
                        int rank;
@@ -4889,7 +4778,7 @@ namespace Mono.CSharp {
                        TemporaryVariable copy;
                        Expression access;
 
-                       public ArrayForeach (Type var_type, Expression var,
+                       public ArrayForeach (Expression var_type, Expression var,
                                             Expression expr, Statement stmt, Location l)
                        {
                                this.var_type = var_type;
@@ -4925,7 +4814,17 @@ namespace Mono.CSharp {
                                if (access == null)
                                        return false;
 
-                               conv = Convert.ExplicitConversion (ec, access, var_type, loc);
+                               VarExpr ve = var_type as VarExpr;
+                               if (ve != null) {
+                                       // Infer implicitly typed local variable from foreach array type
+                                       var_type = new TypeExpression (access.Type, ve.Location);
+                               }
+
+                               var_type = var_type.ResolveAsTypeTerminal (ec, false);
+                               if (var_type == null)
+                                       return false;
+
+                               conv = Convert.ExplicitConversion (ec, access, var_type.Type, loc);
                                if (conv == null)
                                        return false;
 
@@ -5007,11 +4906,12 @@ namespace Mono.CSharp {
                        MethodGroupExpr get_enumerator;
                        PropertyExpr get_current;
                        MethodInfo move_next;
-                       Type var_type, enumerator_type;
+                       Expression var_type;
+                       Type enumerator_type;
                        bool is_disposable;
                        bool enumerator_found;
 
-                       public CollectionForeach (Type var_type, Expression var,
+                       public CollectionForeach (Expression var_type, Expression var,
                                                  Expression expr, Statement stmt, Location l)
                        {
                                this.var_type = var_type;
@@ -5311,6 +5211,16 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
+                               VarExpr ve = var_type as VarExpr;
+                               if (ve != null) {
+                                       // Infer implicitly typed local variable from foreach enumerable type
+                                       var_type = new TypeExpression (get_current.PropertyInfo.PropertyType, var_type.Location);
+                               }
+
+                               var_type = var_type.ResolveAsTypeTerminal (ec, false);
+                               if (var_type == null)
+                                       return false;
+                                                               
                                enumerator = new TemporaryVariable (enumerator_type, loc);
                                enumerator.Resolve (ec);
 
@@ -5331,7 +5241,7 @@ namespace Mono.CSharp {
                                get_current.InstanceExpression = enumerator;
 
                                Statement block = new CollectionForeachStatement (
-                                       var_type, variable, get_current, statement, loc);
+                                       var_type.Type, variable, get_current, statement, loc);
 
                                loop = new While (move_next_expr, block, loc);