2009-03-17 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / statement.cs
index 365975474401ebd4dee66b2e4a97c49216d55a5c..f1ba2d191ecc0d568a0e45aabf20b5f40bf32209 100644 (file)
@@ -1270,7 +1270,7 @@ namespace Mono.CSharp {
        // The information about a user-perceived local variable
        //
        public class LocalInfo : IKnownVariable, ILocalVariable {
-               public readonly Expression Type;
+               public readonly FullNamedExpression Type;
 
                public Type VariableType;
                public readonly string Name;
@@ -1300,8 +1300,8 @@ namespace Mono.CSharp {
                Flags flags;
                ReadOnlyContext ro_context;
                LocalBuilder builder;
-               
-               public LocalInfo (Expression type, string name, Block block, Location l)
+
+               public LocalInfo (FullNamedExpression type, string name, Block block, Location l)
                {
                        Type = type;
                        Name = name;
@@ -1478,7 +1478,7 @@ namespace Mono.CSharp {
                        // Variables in anonymous block are not resolved yet
                        //
                        if (VariableType == null)
-                               return new LocalInfo (Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
+                               return new LocalInfo ((FullNamedExpression) Type.Clone (clonectx), Name, clonectx.LookupBlock (Block), Location);
 
                        //
                        // Variables in method block are resolved
@@ -1873,7 +1873,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       LocalInfo vi = new LocalInfo (type, name, this, l);
+                       LocalInfo vi = new LocalInfo ((FullNamedExpression) type, name, this, l);
                        AddVariable (vi);
 
                        if ((flags & Flags.VariablesInitialized) != 0)
@@ -1911,7 +1911,7 @@ namespace Mono.CSharp {
                {
                        Report.Error (412, loc, "The type parameter name `{0}' is the same as `{1}'",
                                name, conflict);
-               }                                       
+               }
 
                public bool AddConstant (Expression type, string name, Expression value, Location l)
                {
@@ -3602,6 +3602,7 @@ namespace Mono.CSharp {
                public static void Reset ()
                {
                        unique_counter = 0;
+                       allowed_types = null;
                }
 
                public override bool Resolve (EmitContext ec)
@@ -3614,7 +3615,7 @@ namespace Mono.CSharp {
 
 #if GMCS_SOURCE
                        if ((new_expr == null) && TypeManager.IsNullableType (Expr.Type)) {
-                               unwrap = Nullable.Unwrap.Create (Expr, ec);
+                               unwrap = Nullable.Unwrap.Create (Expr, false);
                                if (unwrap == null)
                                        return false;
 
@@ -4299,81 +4300,51 @@ namespace Mono.CSharp {
                        }
                }
 
-               class StringEmitter : Emitter {
-                       class StringPtr : Expression
-                       {
-                               LocalBuilder b;
-
-                               public StringPtr (LocalBuilder b, Location l)
-                               {
-                                       this.b = b;
-                                       eclass = ExprClass.Value;
-                                       type = TypeManager.char_ptr_type;
-                                       loc = l;
-                               }
-
-                               public override Expression CreateExpressionTree (EmitContext ec)
-                               {
-                                       throw new NotSupportedException ("ET");
-                               }
-
-                               public override Expression DoResolve (EmitContext ec)
-                               {
-                                       // This should never be invoked, we are born in fully
-                                       // initialized state.
-
-                                       return this;
-                               }
-
-                               public override void Emit (EmitContext ec)
-                               {
-                                       if (TypeManager.int_get_offset_to_string_data == null) {
-                                               // TODO: Move to resolve !!
-                                               TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedMethod (
-                                                       TypeManager.runtime_helpers_type, "get_OffsetToStringData", loc, Type.EmptyTypes);
-                                       }
-
-                                       ILGenerator ig = ec.ig;
-
-                                       ig.Emit (OpCodes.Ldloc, b);
-                                       ig.Emit (OpCodes.Conv_I);
-                                       ig.Emit (OpCodes.Call, TypeManager.int_get_offset_to_string_data);
-                                       ig.Emit (OpCodes.Add);
-                               }
-                       }
-
-                       LocalBuilder pinned_string;
-                       Location loc;
+               class StringEmitter : Emitter
+               {
+                       LocalInfo pinned_string;
 
                        public StringEmitter (Expression expr, LocalInfo li, Location loc):
                                base (expr, li)
                        {
-                               this.loc = loc;
+                               pinned_string = new LocalInfo (new TypeExpression (TypeManager.string_type, loc), null, null, loc);
+                               pinned_string.Pinned = true;
                        }
 
                        public override void Emit (EmitContext ec)
                        {
-                               ILGenerator ig = ec.ig;
-                               pinned_string = TypeManager.DeclareLocalPinned (ig, TypeManager.string_type);
-                                       
+                               pinned_string.Resolve (ec);
+                               pinned_string.ResolveVariable (ec);
+
                                converted.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, pinned_string);
+                               pinned_string.EmitAssign (ec);
 
-                               Expression sptr = new StringPtr (pinned_string, loc);
-                               converted = Convert.ImplicitConversionRequired (
-                                       ec, sptr, vi.VariableType, loc);
-                                       
-                               if (converted == null)
-                                       return;
+                               PropertyInfo p = TypeManager.int_get_offset_to_string_data;
+                               if (p == null) {
+                                       // TODO: Move to resolve
+                                       p = TypeManager.int_get_offset_to_string_data = TypeManager.GetPredefinedProperty (
+                                               TypeManager.runtime_helpers_type, "OffsetToStringData", pinned_string.Location, TypeManager.int32_type);
 
-                               converted.Emit (ec);
+                                       if (p == null)
+                                               return;
+                               }
+
+                               // TODO: Should use Binary::Add
+                               pinned_string.Emit (ec);
+                               ec.ig.Emit (OpCodes.Conv_I);
+
+                               PropertyExpr pe = new PropertyExpr (pinned_string.VariableType, p, pinned_string.Location);
+                               //pe.InstanceExpression = pinned_string;
+                               pe.Resolve (ec).Emit (ec);
+
+                               ec.ig.Emit (OpCodes.Add);
                                vi.EmitAssign (ec);
                        }
 
                        public override void EmitExit (EmitContext ec)
                        {
                                ec.ig.Emit (OpCodes.Ldnull);
-                               ec.ig.Emit (OpCodes.Stloc, pinned_string);
+                               pinned_string.EmitAssign (ec);
                        }
                }
 
@@ -4884,6 +4855,7 @@ namespace Mono.CSharp {
                }
        }
 
+       // FIXME: Why is it almost exact copy of Using ??
        public class UsingTemporary : ExceptionStatement {
                TemporaryVariable local_copy;
                public Statement Statement;
@@ -5008,7 +4980,6 @@ namespace Mono.CSharp {
                Expression var;
                Expression init;
 
-               Expression converted_var;
                ExpressionStatement assign;
 
                public Using (Expression var, Expression init, Statement stmt, Location l)
@@ -5019,31 +4990,6 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
-               bool ResolveVariable (EmitContext ec)
-               {
-                       ExpressionStatement a = new SimpleAssign (var, init, loc);
-                       a = a.ResolveStatement (ec);
-                       if (a == null)
-                               return false;
-
-                       assign = a;
-
-                       if (TypeManager.ImplementsInterface (a.Type, TypeManager.idisposable_type)) {
-                               converted_var = var;
-                               return true;
-                       }
-
-                       Expression e = Convert.ImplicitConversionStandard (ec, a, TypeManager.idisposable_type, var.Location);
-                       if (e == null) {
-                               Error_IsNotConvertibleToIDisposable (var);
-                               return false;
-                       }
-
-                       converted_var = e;
-
-                       return true;
-               }
-
                static public void Error_IsNotConvertibleToIDisposable (Expression expr)
                {
                        Report.SymbolRelatedToPreviousError (expr.Type);
@@ -5064,42 +5010,18 @@ namespace Mono.CSharp {
                protected override void EmitFinallyBody (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
+                       Label skip = ig.DefineLabel ();
 
-                       if (!TypeManager.IsStruct (var.Type)) {
-                               Label skip = ig.DefineLabel ();
+                       bool emit_null_check = !TypeManager.IsValueType (var.Type);
+                       if (emit_null_check) {
                                var.Emit (ec);
                                ig.Emit (OpCodes.Brfalse, skip);
-                               converted_var.Emit (ec);
-                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               ig.MarkLabel (skip);
-                       } else {
-                               Expression ml = Expression.MemberLookup(ec.ContainerType, TypeManager.idisposable_type, var.Type, "Dispose", Mono.CSharp.Location.Null);
-
-                               if (!(ml is MethodGroupExpr)) {
-                                       var.Emit (ec);
-                                       ig.Emit (OpCodes.Box, var.Type);
-                                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               } else {
-                                       MethodInfo mi = null;
-
-                                       foreach (MethodInfo mk in ((MethodGroupExpr) ml).Methods) {
-                                               if (TypeManager.GetParameterData (mk).Count == 0) {
-                                                       mi = mk;
-                                                       break;
-                                               }
-                                       }
-
-                                       if (mi == null) {
-                                               Report.Error(-100, Mono.CSharp.Location.Null, "Internal error: No Dispose method which takes 0 parameters.");
-                                               return;
-                                       }
+                       }
 
-                                       IMemoryLocation mloc = (IMemoryLocation) var;
+                       Invocation.EmitCall (ec, false, var, TypeManager.void_dispose_void, new ArrayList (0), loc);
 
-                                       mloc.AddressOf (ec, AddressOp.Load);
-                                       ig.Emit (OpCodes.Call, mi);
-                               }
-                       }
+                       if (emit_null_check)
+                               ig.MarkLabel (skip);
                }
 
                public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
@@ -5130,6 +5052,27 @@ namespace Mono.CSharp {
                        return ok;
                }
 
+               bool ResolveVariable (EmitContext ec)
+               {
+                       assign = new SimpleAssign (var, init, loc);
+                       assign = assign.ResolveStatement (ec);
+                       if (assign == null)
+                               return false;
+
+                       if (assign.Type == TypeManager.idisposable_type ||
+                               TypeManager.ImplementsInterface (assign.Type, TypeManager.idisposable_type)) {
+                               return true;
+                       }
+
+                       Expression e = Convert.ImplicitConversionStandard (ec, assign, TypeManager.idisposable_type, var.Location);
+                       if (e == null) {
+                               Error_IsNotConvertibleToIDisposable (var);
+                               return false;
+                       }
+
+                       throw new NotImplementedException ("covariance?");
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Using target = (Using) t;
@@ -5805,10 +5748,9 @@ namespace Mono.CSharp {
 
                                protected override void EmitFinallyBody (EmitContext ec)
                                {
-                                       ILGenerator ig = ec.ig;
-
                                        Expression instance = parent.enumerator;
                                        if (!TypeManager.IsValueType (parent.enumerator_type)) {
+                                               ILGenerator ig = ec.ig;
 
                                                parent.enumerator.Emit (ec);