Forgot to commit
[mono.git] / mcs / mcs / statement.cs
index 0d0d0ff196b26270b56d7d6ca484b09783c18453..5491e925f963f24cbf65a2f24be2ad8741c85cdd 100644 (file)
@@ -83,7 +83,7 @@ namespace Mono.CSharp {
                /// </summary>
                public virtual void Emit (EmitContext ec)
                {
-                       ec.Mark (loc, true);
+                       ec.Mark (loc);
                        DoEmit (ec);
                }
 
@@ -91,10 +91,7 @@ namespace Mono.CSharp {
                // This routine must be overrided in derived classes and make copies
                // of all the data that might be modified if resolved
                // 
-               protected virtual void CloneTo (CloneContext clonectx, Statement target)
-               {
-                       throw new InternalErrorException ("{0} does not implement Statement.CloneTo", this.GetType ());
-               }
+               protected abstract void CloneTo (CloneContext clonectx, Statement target);
 
                public Statement Clone (CloneContext clonectx)
                {
@@ -116,6 +113,7 @@ namespace Mono.CSharp {
                        return Clone (clonectx);
                }
 
+               public abstract void MutateHoistedGenericType (AnonymousMethodStorey storey);
        }
 
        //
@@ -202,6 +200,10 @@ namespace Mono.CSharp {
                {
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement target)
                {
                        // nothing needed.
@@ -233,6 +235,14 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       TrueStatement.MutateHoistedGenericType (storey);
+                       if (FalseStatement != null)
+                               FalseStatement.MutateHoistedGenericType (storey);
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        bool ok = true;
@@ -354,7 +364,6 @@ namespace Mono.CSharp {
        public class Do : Statement {
                public Expression expr;
                public Statement  EmbeddedStatement;
-               bool infinite;
                
                public Do (Statement statement, Expression bool_expr, Location l)
                {
@@ -383,13 +392,10 @@ namespace Mono.CSharp {
                        if (expr == null)
                                ok = false;
                        else if (expr is Constant){
-                               bool res = !((Constant) expr).IsDefaultValue;
-
-                               if (res)
-                                       infinite = true;
+                               bool infinite = !((Constant) expr).IsDefaultValue;
+                               if (infinite)
+                                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        }
-                       if (infinite)
-                               ec.CurrentBranching.CurrentUsageVector.Goto ();
 
                        ec.EndFlowBranching ();
 
@@ -428,6 +434,12 @@ namespace Mono.CSharp {
                        ec.LoopEnd = old_end;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       EmbeddedStatement.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Do target = (Do) t;
@@ -527,7 +539,7 @@ namespace Mono.CSharp {
                                Statement.Emit (ec);
                        
                                ig.MarkLabel (ec.LoopBegin);
-                               ec.Mark (loc, true);
+                               ec.Mark (loc);
 
                                expr.EmitBranchable (ec, while_loop, true);
                                
@@ -550,6 +562,12 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.Statement = Statement.Clone (clonectx);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       Statement.MutateHoistedGenericType (storey);
+               }
        }
 
        public class For : Statement {
@@ -630,7 +648,7 @@ namespace Mono.CSharp {
 
                        return ok;
                }
-               
+
                protected override void DoEmit (EmitContext ec)
                {
                        if (InitStatement != null && InitStatement != EmptyStatement.Value)
@@ -684,6 +702,18 @@ namespace Mono.CSharp {
                        ec.LoopEnd = old_end;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (InitStatement != null)
+                               InitStatement.MutateHoistedGenericType (storey);
+                       if (Test != null)
+                               Test.MutateHoistedGenericType (storey);
+                       if (Increment != null)
+                               Increment.MutateHoistedGenericType (storey);
+
+                       Statement.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        For target = (For) t;
@@ -719,6 +749,11 @@ namespace Mono.CSharp {
                        expr.EmitStatement (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+               }
+
                public override string ToString ()
                {
                        return "StatementExpression (" + expr + ")";
@@ -779,12 +814,12 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       AnonymousContainer am = ec.CurrentAnonymousMethod;
-                       if ((am != null) && am.IsIterator && ec.InIterator) {
+                       if (ec.CurrentBlock.Toplevel.IsIterator) {
                                Report.Error (1622, loc, "Cannot return a value from iterators. Use the yield return " +
                                                  "statement to return a value, or yield break to end the iteration");
                        }
 
+                       AnonymousExpression am = ec.CurrentAnonymousMethod;
                        if (am == null && ec.ReturnType == TypeManager.void_type) {
                                MemberCore mc = ec.ResolveContext as MemberCore;
                                Report.Error (127, loc, "`{0}': A return keyword must not be followed by any expression when method returns void",
@@ -837,6 +872,12 @@ namespace Mono.CSharp {
                                ec.ig.Emit (OpCodes.Ret);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (Expr != null)
+                               Expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Return target = (Return) t;
@@ -875,6 +916,11 @@ namespace Mono.CSharp {
                        label.AddReference ();
                }
 
+               protected override void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       // Nothing to clone
+               }
+
                protected override void DoEmit (EmitContext ec)
                {
                        if (label == null)
@@ -882,6 +928,10 @@ namespace Mono.CSharp {
                        Label l = label.LabelTarget (ec);
                        ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, l);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
        }
 
        public class LabeledStatement : Statement {
@@ -933,6 +983,11 @@ namespace Mono.CSharp {
                        vectors = vector;
                }
 
+               protected override void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       // nothing to clone
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        // this flow-branching will be terminated when the surrounding block ends
@@ -948,6 +1003,10 @@ namespace Mono.CSharp {
                        ec.ig.MarkLabel (label);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
+
                public void AddReference ()
                {
                        referenced = true;
@@ -965,6 +1024,11 @@ namespace Mono.CSharp {
                        loc = l;
                }
 
+               protected override void CloneTo (CloneContext clonectx, Statement target)
+               {
+                       // nothing to clone
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        ec.CurrentBranching.CurrentUsageVector.Goto ();
@@ -984,6 +1048,10 @@ namespace Mono.CSharp {
                        }
                        ec.ig.Emit (OpCodes.Br, ec.Switch.DefaultTarget);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
        }
 
        /// <summary>
@@ -1006,6 +1074,8 @@ namespace Mono.CSharp {
                                return false;
                        }
 
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
+
                        expr = expr.Resolve (ec);
                        if (expr == null)
                                return false;
@@ -1017,21 +1087,18 @@ namespace Mono.CSharp {
                        }
 
                        Type type = ec.Switch.SwitchType;
-                       if (!Convert.ImplicitStandardConversionExists (c, type))
-                               Report.Warning (469, 2, loc, "The `goto case' value is not implicitly " +
-                                               "convertible to type `{0}'", TypeManager.CSharpName (type));
-
-                       bool fail = false;
-                       object val = c.GetValue ();
-                       if ((val != null) && (c.Type != type) && (c.Type != TypeManager.object_type))
-                               val = TypeManager.ChangeType (val, type, out fail);
-
-                       if (fail) {
-                               Report.Error (30, loc, "Cannot convert type `{0}' to `{1}'",
-                                             c.GetSignatureForError (), TypeManager.CSharpName (type));
+                       Constant res = c.TryReduce (ec, type, c.Location);
+                       if (res == null) {
+                               c.Error_ValueCannotBeConverted (ec, loc, type, true);
                                return false;
                        }
 
+                       if (!Convert.ImplicitStandardConversionExists (c, type))
+                               Report.Warning (469, 2, loc,
+                                       "The `goto case' value is not implicitly convertible to type `{0}'",
+                                       TypeManager.CSharpName (type));
+
+                       object val = res.GetValue ();
                        if (val == null)
                                val = SwitchLabel.NullStringCase;
                                        
@@ -1043,7 +1110,6 @@ namespace Mono.CSharp {
                                return false;
                        }
 
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
                        return true;
                }
 
@@ -1052,12 +1118,16 @@ namespace Mono.CSharp {
                        ec.ig.Emit (OpCodes.Br, sl.GetILLabelCode (ec));
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        GotoCase target = (GotoCase) t;
 
                        target.expr = expr.Clone (clonectx);
-                       target.sl = sl.Clone (clonectx);
                }
        }
        
@@ -1072,28 +1142,22 @@ namespace Mono.CSharp {
 
                public override bool Resolve (EmitContext ec)
                {
-                       ec.CurrentBranching.CurrentUsageVector.Goto ();
-
-                       if (expr == null)
+                       if (expr == null) {
+                               ec.CurrentBranching.CurrentUsageVector.Goto ();
                                return ec.CurrentBranching.CheckRethrow (loc);
+                       }
 
-                       expr = expr.Resolve (ec);
-                       if (expr == null)
-                               return false;
-
-                       ExprClass eclass = expr.eclass;
+                       expr = expr.Resolve (ec, ResolveFlags.Type | ResolveFlags.VariableOrValue);
+                       ec.CurrentBranching.CurrentUsageVector.Goto ();
 
-                       if (!(eclass == ExprClass.Variable || eclass == ExprClass.PropertyAccess ||
-                             eclass == ExprClass.Value || eclass == ExprClass.IndexerAccess)) {
-                               expr.Error_UnexpectedKind (ec.DeclContainer, "value, variable, property or indexer access ", loc);
+                       if (expr == null)
                                return false;
-                       }
 
                        Type t = expr.Type;
 
                        if ((t != TypeManager.exception_type) &&
                            !TypeManager.IsSubclassOf (t, TypeManager.exception_type) &&
-                           !(expr is NullLiteral)) {
+                           t != TypeManager.null_type) {
                                Error (155, "The type caught or thrown must be derived from System.Exception");
                                return false;
                        }
@@ -1111,6 +1175,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (expr != null)
+                               expr.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Throw target = (Throw) t;
@@ -1141,6 +1211,10 @@ namespace Mono.CSharp {
                {
                        ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopEnd);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
                
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
@@ -1170,33 +1244,21 @@ namespace Mono.CSharp {
                        ec.ig.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, ec.LoopBegin);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        // nothing needed.
                }
        }
 
-       public abstract class Variable
+       public interface ILocalVariable
        {
-               public abstract Type Type {
-                       get;
-               }
-
-               public abstract bool HasInstance {
-                       get;
-               }
-
-               public abstract bool NeedsTemporary {
-                       get;
-               }
-
-               public abstract void EmitInstance (EmitContext ec);
-
-               public abstract void Emit (EmitContext ec);
-
-               public abstract void EmitAssign (EmitContext ec);
-
-               public abstract void EmitAddressOf (EmitContext ec);
+               void Emit (EmitContext ec);
+               void EmitAssign (EmitContext ec);
+               void EmitAddressOf (EmitContext ec);
        }
 
        public interface IKnownVariable {
@@ -1207,8 +1269,8 @@ namespace Mono.CSharp {
        //
        // The information about a user-perceived local variable
        //
-       public class LocalInfo : IKnownVariable {
-               public Expression Type;
+       public class LocalInfo : IKnownVariable, ILocalVariable {
+               public readonly FullNamedExpression Type;
 
                public Type VariableType;
                public readonly string Name;
@@ -1216,11 +1278,7 @@ namespace Mono.CSharp {
                public readonly Block Block;
 
                public VariableInfo VariableInfo;
-
-               Variable var;
-               public Variable Variable {
-                       get { return var; }
-               }
+               public HoistedVariable HoistedVariableReference;
 
                [Flags]
                enum Flags : byte {
@@ -1228,7 +1286,6 @@ namespace Mono.CSharp {
                        ReadOnly = 2,
                        Pinned = 4,
                        IsThis = 8,
-                       Captured = 16,
                        AddressTaken = 32,
                        CompilerGenerated = 64,
                        IsConstant = 128
@@ -1243,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;
@@ -1261,11 +1318,10 @@ namespace Mono.CSharp {
 
                public void ResolveVariable (EmitContext ec)
                {
-                       Block theblock = Block;
-                       if (theblock.ScopeInfo != null)
-                               var = theblock.ScopeInfo.GetCapturedVariable (this);
+                       if (HoistedVariableReference != null)
+                               return;
 
-                       if (var == null) {
+                       if (builder == null) {
                                if (Pinned)
                                        //
                                        // This is needed to compile on both .NET 1.x and .NET 2.x
@@ -1274,12 +1330,25 @@ namespace Mono.CSharp {
                                        builder = TypeManager.DeclareLocalPinned (ec.ig, VariableType);
                                else
                                        builder = ec.ig.DeclareLocal (VariableType);
-
-                               var = new LocalVariable (this, builder);
                        }
                }
 
-               public void EmitSymbolInfo (EmitContext ec, string name)
+               public void Emit (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldloc, builder);
+               }
+
+               public void EmitAssign (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Stloc, builder);
+               }
+
+               public void EmitAddressOf (EmitContext ec)
+               {
+                       ec.ig.Emit (OpCodes.Ldloca, builder);
+               }
+
+               public void EmitSymbolInfo (EmitContext ec)
                {
                        if (builder != null)
                                ec.DefineLocalVariable (Name, builder);
@@ -1306,22 +1375,18 @@ namespace Mono.CSharp {
 
                public bool Resolve (EmitContext ec)
                {
-                       if (VariableType == null) {
-                               TypeExpr texpr = Type.ResolveAsContextualType (ec, false);
-                               if (texpr == null)
-                                       return false;
+                       if (VariableType != null)
+                               return true;
+
+                       TypeExpr texpr = Type.ResolveAsContextualType (ec, false);
+                       if (texpr == null)
+                               return false;
                                
-                               VariableType = texpr.Type;
-                       }
+                       VariableType = texpr.Type;
 
                        if (TypeManager.IsGenericParameter (VariableType))
                                return true;
 
-                       if (VariableType == TypeManager.void_type) {
-                               Expression.Error_VoidInvalidInTheContext (Location);
-                               return false;
-                       }
-
                        if (VariableType.IsAbstract && VariableType.IsSealed) {
                                FieldBase.Error_VariableOfStaticClass (Location, Name, VariableType);
                                return false;
@@ -1333,11 +1398,6 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public bool IsCaptured {
-                       get { return (flags & Flags.Captured) != 0; }
-                       set { flags |= Flags.Captured; }
-               }
-
                public bool IsConstant {
                        get { return (flags & Flags.IsConstant) != 0; }
                        set { flags |= Flags.IsConstant; }
@@ -1380,12 +1440,12 @@ namespace Mono.CSharp {
                                throw new InternalErrorException ("Variable is not readonly");
 
                        switch (ro_context) {
-                               case ReadOnlyContext.Fixed:
-                                       return "fixed variable";
-                               case ReadOnlyContext.Foreach:
-                                       return "foreach iteration variable";
-                               case ReadOnlyContext.Using:
-                                       return "using variable";
+                       case ReadOnlyContext.Fixed:
+                               return "fixed variable";
+                       case ReadOnlyContext.Foreach:
+                               return "foreach iteration variable";
+                       case ReadOnlyContext.Using:
+                               return "using variable";
                        }
                        throw new NotImplementedException ();
                }
@@ -1412,57 +1472,13 @@ namespace Mono.CSharp {
                        get { return Location; }
                }
 
-               protected class LocalVariable : Variable
-               {
-                       public readonly LocalInfo LocalInfo;
-                       LocalBuilder builder;
-
-                       public LocalVariable (LocalInfo local, LocalBuilder builder)
-                       {
-                               this.LocalInfo = local;
-                               this.builder = builder;
-                       }
-
-                       public override Type Type {
-                               get { return LocalInfo.VariableType; }
-                       }
-
-                       public override bool HasInstance {
-                               get { return false; }
-                       }
-
-                       public override bool NeedsTemporary {
-                               get { return false; }
-                       }
-
-                       public override void EmitInstance (EmitContext ec)
-                       {
-                               // Do nothing.
-                       }
-
-                       public override void Emit (EmitContext ec)
-                       {
-                               ec.ig.Emit (OpCodes.Ldloc, builder);
-                       }
-
-                       public override void EmitAssign (EmitContext ec)
-                       {
-                               ec.ig.Emit (OpCodes.Stloc, builder);
-                       }
-
-                       public override void EmitAddressOf (EmitContext ec)
-                       {
-                               ec.ig.Emit (OpCodes.Ldloca, builder);
-                       }
-               }
-
                public LocalInfo Clone (CloneContext clonectx)
                {
                        //
                        // 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
@@ -1489,11 +1505,11 @@ namespace Mono.CSharp {
        /// </remarks>
        public class Block : Statement {
                public Block    Parent;
-               public readonly Location  StartLocation;
+               public Location StartLocation;
                public Location EndLocation = Location.Null;
 
                public ExplicitBlock Explicit;
-               public ToplevelBlock Toplevel;
+               public ToplevelBlock Toplevel; // TODO: Use Explicit
 
                [Flags]
                public enum Flags : byte {
@@ -1501,15 +1517,16 @@ namespace Mono.CSharp {
                        BlockUsed = 2,
                        VariablesInitialized = 4,
                        HasRet = 8,
-                       IsDestructor = 16,
-                       Unsafe = 32,
-                       IsIterator = 64
+                       Unsafe = 16,
+                       IsIterator = 32,
+                       HasCapturedVariable = 64,
+                       HasCapturedThis = 128
                }
                protected Flags flags;
 
                public bool Unchecked {
                        get { return (flags & Flags.Unchecked) != 0; }
-                       set { flags |= Flags.Unchecked; }
+                       set { flags = value ? flags | Flags.Unchecked : flags & ~Flags.Unchecked; }
                }
 
                public bool Unsafe {
@@ -1534,7 +1551,7 @@ namespace Mono.CSharp {
                //
                // Labels.  (label, block) pairs.
                //
-               HybridDictionary labels;
+               protected HybridDictionary labels;
 
                //
                // Keeps track of (name, type) pairs
@@ -1555,9 +1572,7 @@ namespace Mono.CSharp {
                //
                Block switch_block;
 
-               // TODO: merge with scope_initializers
-               ExpressionStatement scope_init;
-               ArrayList scope_initializers;
+               protected ArrayList scope_initializers;
 
                ArrayList anonymous_children;
 
@@ -1566,7 +1581,6 @@ namespace Mono.CSharp {
                int this_id;
 
                int assignable_slots;
-               protected ScopeInfo scope_info;
                bool unreachable_shown;
                bool unreachable;
                
@@ -1582,6 +1596,20 @@ namespace Mono.CSharp {
                        : this (parent, (Flags) 0, start, end)
                { }
 
+               //
+               // Useful when TopLevel block is downgraded to normal block
+               //
+               public Block (ToplevelBlock parent, ToplevelBlock source)
+                       : this (parent, source.flags, source.StartLocation, source.EndLocation)
+               {
+                       statements = source.statements;
+                       children = source.children;
+                       labels = source.labels;
+                       variables = source.variables;
+                       constants = source.constants;
+                       switch_block = source.switch_block;
+               }
+
                public Block (Block parent, Flags flags, Location start, Location end)
                {
                        if (parent != null) {
@@ -1779,6 +1807,12 @@ namespace Mono.CSharp {
                        if (e is VariableReference || (e is Constant && b.GetLocalInfo (name) != null))
                                return true;
 
+                       if (this is ToplevelBlock) {
+                               Report.SymbolRelatedToPreviousError (kvi.Location, name);
+                               e.Error_VariableIsUsedBeforeItIsDeclared (name);
+                               return false;
+                       }
+
                        //
                        // Even though we detected the error when the name is used, we
                        // treat it as if the variable declaration was in error.
@@ -1788,31 +1822,45 @@ namespace Mono.CSharp {
                        return false;
                }
 
-               public LocalInfo AddVariable (Expression type, string name, Location l)
+               protected virtual bool CheckParentConflictName (ToplevelBlock block, string name, Location l)
                {
                        LocalInfo vi = GetLocalInfo (name);
                        if (vi != null) {
                                Report.SymbolRelatedToPreviousError (vi.Location, name);
-                               if (Explicit == vi.Block.Explicit)
+                               if (Explicit == vi.Block.Explicit) {
                                        Error_AlreadyDeclared (l, name, null);
-                               else
-                                       Error_AlreadyDeclared (l, name, "parent");
-                               return null;
+                               } else {
+                                       Error_AlreadyDeclared (l, name, this is ToplevelBlock ?
+                                               "parent or current" : "parent");
+                               }
+                               return false;
                        }
 
-                       ToplevelParameterInfo pi = Toplevel.GetParameterInfo (name);
-                       if (pi != null) {
-                               Report.SymbolRelatedToPreviousError (pi.Location, name);
-                               Error_AlreadyDeclared (loc, name,
-                                       pi.Block == Toplevel ? "method argument" : "parent or current");
-                               return null;
+                       if (block != null) {
+                               Expression e = block.GetParameterReference (name, Location.Null);
+                               if (e != null) {
+                                       ParameterReference pr = e as ParameterReference;
+                                       if (this is Linq.QueryBlock && (pr != null && pr.Parameter is Linq.QueryBlock.ImplicitQueryParameter || e is MemberAccess))
+                                               Error_AlreadyDeclared (loc, name);
+                                       else
+                                               Error_AlreadyDeclared (loc, name, "parent or current");
+                                       return false;
+                               }
                        }
-                       
+
+                       return true;
+               }
+
+               public LocalInfo AddVariable (Expression type, string name, Location l)
+               {
+                       if (!CheckParentConflictName (Toplevel, name, l))
+                               return null;
+
                        if (Toplevel.GenericMethod != null) {
                                foreach (TypeParameter tp in Toplevel.GenericMethod.CurrentTypeParameters) {
                                        if (tp.Name == name) {
                                                Report.SymbolRelatedToPreviousError (tp);
-                                               Error_AlreadyDeclaredTypeParameter (loc, name);
+                                               Error_AlreadyDeclaredTypeParameter (loc, name, "local variable");
                                                return null;
                                        }
                                }
@@ -1825,7 +1873,7 @@ namespace Mono.CSharp {
                                return null;
                        }
 
-                       vi = new LocalInfo (type, name, this, l);
+                       LocalInfo vi = new LocalInfo ((FullNamedExpression) type, name, this, l);
                        AddVariable (vi);
 
                        if ((flags & Flags.VariablesInitialized) != 0)
@@ -1859,10 +1907,11 @@ namespace Mono.CSharp {
                                "A local variable named `{0}' is already defined in this scope", name);
                }
                                        
-               protected virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name)
+               public virtual void Error_AlreadyDeclaredTypeParameter (Location loc, string name, string conflict)
                {
-                       GenericMethod.Error_ParameterNameCollision (loc, name, "local variable");
-               }                                       
+                       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)
                {
@@ -1899,13 +1948,15 @@ namespace Mono.CSharp {
 
                public LocalInfo GetLocalInfo (string name)
                {
+                       LocalInfo ret;
                        for (Block b = this; b != null; b = b.Parent) {
                                if (b.variables != null) {
-                                       LocalInfo ret = b.variables [name] as LocalInfo;
+                                       ret = (LocalInfo) b.variables [name];
                                        if (ret != null)
                                                return ret;
                                }
                        }
+
                        return null;
                }
 
@@ -1931,7 +1982,7 @@ namespace Mono.CSharp {
                // It should be used by expressions which require to
                // register a statement during resolve process.
                //
-               public void AddScopeStatement (StatementExpression s)
+               public void AddScopeStatement (Statement s)
                {
                        if (scope_initializers == null)
                                scope_initializers = new ArrayList ();
@@ -1958,35 +2009,15 @@ namespace Mono.CSharp {
                        get { return (flags & Flags.HasRet) != 0; }
                }
 
-               public bool IsDestructor {
-                       get { return (flags & Flags.IsDestructor) != 0; }
-               }
-
-               public void SetDestructor ()
-               {
-                       flags |= Flags.IsDestructor;
-               }
-
                public int AssignableSlots {
                        get {
-                               if ((flags & Flags.VariablesInitialized) == 0)
-                                       throw new Exception ("Variables have not been initialized yet");
+// TODO: Re-enable                     
+//                             if ((flags & Flags.VariablesInitialized) == 0)
+//                                     throw new Exception ("Variables have not been initialized yet");
                                return assignable_slots;
                        }
                }
 
-               public ScopeInfo ScopeInfo {
-                       get { return scope_info; }
-               }
-
-               public ScopeInfo CreateScopeInfo ()
-               {
-                       if (scope_info == null)
-                               scope_info = ScopeInfo.CreateScope (this);
-
-                       return scope_info;
-               }
-
                public ArrayList AnonymousChildren {
                        get { return anonymous_children; }
                }
@@ -2049,10 +2080,10 @@ namespace Mono.CSharp {
 
                                e = ce.ConvertImplicitly (variable_type);
                                if (e == null) {
-                                       if (!variable_type.IsValueType && variable_type != TypeManager.string_type && !ce.IsDefaultValue)
-                                               Const.Error_ConstantCanBeInitializedWithNullOnly (vi.Location, vi.Name);
+                                       if (TypeManager.IsReferenceType (variable_type))
+                                               Const.Error_ConstantCanBeInitializedWithNullOnly (variable_type, vi.Location, vi.Name);
                                        else
-                                               ce.Error_ValueCannotBeConverted (null, vi.Location, variable_type, false);
+                                               ce.Error_ValueCannotBeConverted (ec, vi.Location, variable_type, false);
                                        continue;
                                }
 
@@ -2094,13 +2125,6 @@ namespace Mono.CSharp {
                //
                public virtual void EmitMeta (EmitContext ec)
                {
-                       Report.Debug (64, "BLOCK EMIT META", this, Parent, Toplevel, ScopeInfo, ec);
-                       if (ScopeInfo != null) {
-                               scope_init = ScopeInfo.GetScopeInitializer (ec);
-                               Report.Debug (64, "BLOCK EMIT META #1", this, Toplevel, ScopeInfo,
-                                             ec, scope_init);
-                       }
-
                        if (variables != null){
                                foreach (LocalInfo vi in variables.Values)
                                        vi.ResolveVariable (ec);
@@ -2137,7 +2161,7 @@ namespace Mono.CSharp {
                        }
                }
 
-               private void CheckPossibleMistakenEmptyStatement (Statement s)
+               static void CheckPossibleMistakenEmptyStatement (Statement s)
                {
                        Statement body;
 
@@ -2193,7 +2217,7 @@ namespace Mono.CSharp {
                                // Check possible empty statement (CS0642)
                                if (Report.WarningLevel >= 3 &&
                                        ix + 1 < statement_count &&
-                                               statements [ix + 1] is Block)
+                                               statements [ix + 1] is ExplicitBlock)
                                        CheckPossibleMistakenEmptyStatement (s);
 
                                //
@@ -2203,13 +2227,14 @@ namespace Mono.CSharp {
                                        if (s is EmptyStatement)
                                                continue;
 
-                                       if (s is Block)
-                                               ((Block) s).unreachable = true;
-
                                        if (!unreachable_shown && !(s is LabeledStatement)) {
                                                Report.Warning (162, 2, s.loc, "Unreachable code detected");
                                                unreachable_shown = true;
                                        }
+
+                                       Block c_block = s as Block;
+                                       if (c_block != null)
+                                               c_block.unreachable = c_block.unreachable_shown = true;
                                }
 
                                //
@@ -2293,61 +2318,66 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        Block prev_block = ec.CurrentBlock;
-
                        ec.CurrentBlock = this;
 
-                       bool emit_debug_info = SymbolWriter.HasSymbolWriter;
-                       bool is_lexical_block = (this == Explicit) && (Parent != null) &&
-                               ((flags & Flags.IsIterator) == 0);
+                       if (scope_initializers != null)
+                               EmitScopeInitializers (ec);
 
-                       bool omit_debug_info = ec.OmitDebuggingInfo;
+                       ec.Mark (StartLocation);
+                       DoEmit (ec);
 
-                       if (emit_debug_info) {
-                               if (is_lexical_block)
-                                       ec.BeginScope ();
-                       }
+                       if (SymbolWriter.HasSymbolWriter)
+                               EmitSymbolInfo (ec);
+
+                       ec.CurrentBlock = prev_block;
+               }
 
-                       if ((scope_init != null) || (scope_initializers != null))
-                               SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
+               protected void EmitScopeInitializers (EmitContext ec)
+               {
+                       SymbolWriter.OpenCompilerGeneratedBlock (ec.ig);
 
-                       if (scope_init != null) {
-                               ec.OmitDebuggingInfo = true;
-                               scope_init.EmitStatement (ec);
-                               ec.OmitDebuggingInfo = omit_debug_info;
-                       }
-                       if (scope_initializers != null) {
-                               ec.OmitDebuggingInfo = true;
-                               foreach (StatementExpression s in scope_initializers)
+                       using (ec.Set (EmitContext.Flags.OmitDebuggingInfo)) {
+                               foreach (Statement s in scope_initializers)
                                        s.Emit (ec);
-                               ec.OmitDebuggingInfo = omit_debug_info;
                        }
 
-                       if ((scope_init != null) || (scope_initializers != null))
-                               SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
+                       SymbolWriter.CloseCompilerGeneratedBlock (ec.ig);
+               }
 
-                       ec.Mark (StartLocation, true);
-                       DoEmit (ec);
+               protected virtual void EmitSymbolInfo (EmitContext ec)
+               {
+                       if (variables != null) {
+                               foreach (LocalInfo vi in variables.Values) {
+                                       vi.EmitSymbolInfo (ec);
+                               }
+                       }
+               }
 
-                       if (emit_debug_info) {
-                               EmitSymbolInfo (ec);
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       MutateVariables (storey);
 
-                               if (is_lexical_block)
-                                       ec.EndScope ();
+                       if (scope_initializers != null) {
+                               foreach (Statement s in scope_initializers)
+                                       s.MutateHoistedGenericType (storey);
                        }
 
-                       ec.CurrentBlock = prev_block;
+                       foreach (Statement s in statements)
+                               s.MutateHoistedGenericType (storey);
                }
 
-               protected virtual void EmitSymbolInfo (EmitContext ec)
+               void MutateVariables (AnonymousMethodStorey storey)
                {
                        if (variables != null) {
-                               foreach (DictionaryEntry de in variables) {
-                                       string name = (string) de.Key;
-                                       LocalInfo vi = (LocalInfo) de.Value;
-
-                                       vi.EmitSymbolInfo (ec, name);
+                               foreach (LocalInfo vi in variables.Values) {
+                                       vi.VariableType = storey.MutateType (vi.VariableType);
                                }
                        }
+
+                       if (temporary_variables != null) {
+                               foreach (LocalInfo vi in temporary_variables)
+                                       vi.VariableType = storey.MutateType (vi.VariableType);
+                       }
                }
 
                public override string ToString ()
@@ -2394,6 +2424,9 @@ namespace Mono.CSharp {
        }
 
        public class ExplicitBlock : Block {
+               HybridDictionary known_variables;
+               protected AnonymousMethodStorey am_storey;
+
                public ExplicitBlock (Block parent, Location start, Location end)
                        : this (parent, (Flags) 0, start, end)
                {
@@ -2405,12 +2438,6 @@ namespace Mono.CSharp {
                        this.Explicit = this;
                }
 
-               public bool IsIterator {
-                       get { return (flags & Flags.IsIterator) != 0; }
-               }
-
-               HybridDictionary known_variables;
-
                // <summary>
                //   Marks a variable with name @name as being used in this or a child block.
                //   If a variable name has been used in a child block, it's illegal to
@@ -2427,30 +2454,149 @@ namespace Mono.CSharp {
                                Parent.Explicit.AddKnownVariable (name, info);
                }
 
-               internal IKnownVariable GetKnownVariable (string name)
-               {
-                       return known_variables == null ? null : (IKnownVariable) known_variables [name];
+               public AnonymousMethodStorey AnonymousMethodStorey {
+                       get { return am_storey; }
                }
 
-               protected override void CloneTo (CloneContext clonectx, Statement t)
+               //
+               // Creates anonymous method storey in current block
+               //
+               public AnonymousMethodStorey CreateAnonymousMethodStorey (EmitContext ec)
                {
-                       ExplicitBlock target = (ExplicitBlock) t;
-                       target.known_variables = null;
-                       base.CloneTo (clonectx, t);
-               }
-       }
+                       //
+                       // When referencing a variable in iterator storey from children anonymous method
+                       //
+                       if (Toplevel.am_storey is IteratorStorey) {
+                               return Toplevel.am_storey;
+                       }
 
-       public class ToplevelParameterInfo : IKnownVariable {
-               public readonly ToplevelBlock Block;
-               public readonly int Index;
-               public VariableInfo VariableInfo;
+                       //
+                       // An iterator has only 1 storey block
+                       //
+                       if (ec.CurrentIterator != null)
+                           return ec.CurrentIterator.Storey;
 
-               Block IKnownVariable.Block {
-                       get { return Block; }
-               }
-               public Parameter Parameter {
+                       if (am_storey == null) {
+                               MemberBase mc = ec.ResolveContext as MemberBase;
+                               GenericMethod gm = mc == null ? null : mc.GenericMethod;
+
+                               //
+                               // Creates anonymous method storey for this block
+                               //
+                               am_storey = new AnonymousMethodStorey (this, ec.TypeContainer, mc, gm, "AnonStorey");
+                       }
+
+                       return am_storey;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+                       if (am_storey != null)
+                               am_storey.EmitStoreyInstantiation (ec);
+
+                       bool emit_debug_info = SymbolWriter.HasSymbolWriter && Parent != null && !(am_storey is IteratorStorey);
+                       if (emit_debug_info)
+                               ec.BeginScope ();
+
+                       base.Emit (ec);
+
+                       if (emit_debug_info)
+                               ec.EndScope ();
+               }
+
+               public override void EmitMeta (EmitContext ec)
+               {
+                       //
+                       // Creates anonymous method storey
+                       //
+                       if (am_storey != null) {
+                               if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.Storey != null) {
+                                       //
+                                       // Creates parent storey reference when hoisted this is accessible
+                                       //
+                                       if (am_storey.OriginalSourceBlock.Explicit.HasCapturedThis) {
+                                               ExplicitBlock parent = Toplevel.Parent.Explicit;
+
+                                               //
+                                               // Hoisted this exists in top-level parent storey only
+                                               //
+                                               while (parent.am_storey == null || parent.am_storey.Parent is AnonymousMethodStorey)
+                                                       parent = parent.Parent.Explicit;
+
+                                               am_storey.AddParentStoreyReference (parent.am_storey);
+                                       }
+
+                                       am_storey.ChangeParentStorey (ec.CurrentAnonymousMethod.Storey);
+                               }
+
+                               am_storey.DefineType ();
+                               am_storey.ResolveType ();
+                               am_storey.Define ();
+                               am_storey.Parent.PartialContainer.AddCompilerGeneratedClass (am_storey);
+
+                               ArrayList ref_blocks = am_storey.ReferencesFromChildrenBlock;
+                               if (ref_blocks != null) {
+                                       foreach (ExplicitBlock ref_block in ref_blocks) {
+                                               for (ExplicitBlock b = ref_block.Explicit; b != this; b = b.Parent.Explicit) {
+                                                       if (b.am_storey != null) {
+                                                               b.am_storey.AddParentStoreyReference (am_storey);
+
+                                                               // Stop propagation inside same top block
+                                                               if (b.Toplevel == Toplevel)
+                                                                       break;
+
+                                                               b = b.Toplevel;
+                                                   }
+                                                       b.HasCapturedVariable = true;
+                                               }
+                                       }
+                               }
+                       }
+
+                       base.EmitMeta (ec);
+               }
+
+               internal IKnownVariable GetKnownVariable (string name)
+               {
+                       return known_variables == null ? null : (IKnownVariable) known_variables [name];
+               }
+
+               public bool HasCapturedThis
+               {
+                       set { flags = value ? flags | Flags.HasCapturedThis : flags & ~Flags.HasCapturedThis; }
+                       get { return (flags & Flags.HasCapturedThis) != 0; }
+               }
+
+               public bool HasCapturedVariable
+               {
+                       set { flags = value ? flags | Flags.HasCapturedVariable : flags & ~Flags.HasCapturedVariable; }
+                       get { return (flags & Flags.HasCapturedVariable) != 0; }
+               }
+
+               protected override void CloneTo (CloneContext clonectx, Statement t)
+               {
+                       ExplicitBlock target = (ExplicitBlock) t;
+                       target.known_variables = null;
+                       base.CloneTo (clonectx, t);
+               }
+       }
+
+       public class ToplevelParameterInfo : IKnownVariable {
+               public readonly ToplevelBlock Block;
+               public readonly int Index;
+               public VariableInfo VariableInfo;
+
+               Block IKnownVariable.Block {
+                       get { return Block; }
+               }
+               public Parameter Parameter {
                        get { return Block.Parameters [Index]; }
                }
+
+               public Type ParameterType {
+                       get { return Block.Parameters.Types [Index]; }
+               }
+
                public Location Location {
                        get { return Parameter.Location; }
                }
@@ -2470,44 +2616,72 @@ namespace Mono.CSharp {
        // In particular, this was introduced when the support for Anonymous
        // Methods was implemented. 
        // 
-       public class ToplevelBlock : ExplicitBlock {
+       public class ToplevelBlock : ExplicitBlock
+       {
+               // 
+               // Block is converted to an expression
+               //
+               sealed class BlockScopeExpression : Expression
+               {
+                       Expression child;
+                       readonly ToplevelBlock block;
+
+                       public BlockScopeExpression (Expression child, ToplevelBlock block)
+                       {
+                               this.child = child;
+                               this.block = block;
+                       }
+
+                       public override Expression CreateExpressionTree (EmitContext ec)
+                       {
+                               throw new NotSupportedException ();
+                       }
+
+                       public override Expression DoResolve (EmitContext ec)
+                       {
+                               if (child == null)
+                                       return null;
+                               
+                               block.ResolveMeta (ec, ParametersCompiled.EmptyReadOnlyParameters);
+                               child = child.Resolve (ec);
+                               if (child == null)
+                                       return null;
+
+                               eclass = child.eclass;
+                               type = child.Type;
+                               return this;
+                       }
+
+                       public override void Emit (EmitContext ec)
+                       {
+                               block.EmitMeta (ec);
+                               block.EmitScopeInitializers (ec);
+                               child.Emit (ec);
+                       }
+
+                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                       {
+                               type = storey.MutateType (type);
+                               child.MutateHoistedGenericType (storey);
+                               block.MutateHoistedGenericType (storey);
+                       }
+               }
+
                GenericMethod generic;
                FlowBranchingToplevel top_level_branching;
-               AnonymousContainer anonymous_container;
-               RootScopeInfo root_scope;
-               Parameters parameters;
+               protected ParametersCompiled parameters;
                ToplevelParameterInfo[] parameter_info;
+               LocalInfo this_variable;
+
+               public HoistedVariable HoistedThisVariable;
 
                //
                // The parameters for the block.
                //
-               public Parameters Parameters {
+               public ParametersCompiled Parameters {
                        get { return parameters; }
                }
 
-               public bool CompleteContexts (EmitContext ec)
-               {
-                       Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS", this, Parent, root_scope);
-
-                       if (root_scope != null)
-                               root_scope.LinkScopes ();
-
-                       if (Parent == null && root_scope != null) {
-                               Report.Debug (64, "TOPLEVEL COMPLETE CONTEXTS #1", this, root_scope);
-
-                               if (root_scope.DefineType () == null)
-                                       return false;
-                               if (!root_scope.ResolveType ())
-                                       return false;
-                               if (!root_scope.ResolveMembers ())
-                                       return false;
-                               if (!root_scope.DefineMembers ())
-                                       return false;
-                       }
-
-                       return true;
-               }
-
                public GenericMethod GenericMethod {
                        get { return generic; }
                }
@@ -2516,49 +2690,45 @@ namespace Mono.CSharp {
                        get { return Parent == null ? null : Parent.Toplevel; }
                }
 
-               public AnonymousContainer AnonymousContainer {
-                       get { return anonymous_container; }
-                       set { anonymous_container = value; }
-               }
-
-               public ToplevelBlock (Block parent, Parameters parameters, Location start) :
+               public ToplevelBlock (Block parent, ParametersCompiled parameters, Location start) :
                        this (parent, (Flags) 0, parameters, start)
                {
                }
 
-               public ToplevelBlock (Block parent, Parameters parameters, GenericMethod generic, Location start) :
+               public ToplevelBlock (Block parent, ParametersCompiled parameters, GenericMethod generic, Location start) :
                        this (parent, parameters, start)
                {
                        this.generic = generic;
                }
                
-               public ToplevelBlock (Parameters parameters, Location start) :
+               public ToplevelBlock (ParametersCompiled parameters, Location start) :
                        this (null, (Flags) 0, parameters, start)
                {
                }
 
-               public ToplevelBlock (Flags flags, Parameters parameters, Location start) :
+               ToplevelBlock (Flags flags, ParametersCompiled parameters, Location start) :
                        this (null, flags, parameters, start)
                {
                }
 
                // We use 'Parent' to hook up to the containing block, but don't want to register the current block as a child.
                // So, we use a two-stage setup -- first pass a null parent to the base constructor, and then override 'Parent'.
-               public ToplevelBlock (Block parent, Flags flags, Parameters parameters, Location start) :
+               public ToplevelBlock (Block parent, Flags flags, ParametersCompiled parameters, Location start) :
                        base (null, flags, start, Location.Null)
                {
                        this.Toplevel = this;
 
-                       this.parameters = parameters == null ? Parameters.EmptyReadOnlyParameters : parameters;
+                       this.parameters = parameters;
                        this.Parent = parent;
                        if (parent != null)
                                parent.AddAnonymousChild (this);
 
-                       if (this.parameters.Count != 0)
+                       if (!this.parameters.IsEmpty)
                                ProcessParameters ();
                }
 
-               public ToplevelBlock (Location loc) : this (null, (Flags) 0, null, loc)
+               public ToplevelBlock (Location loc)
+                       : this (null, (Flags) 0, ParametersCompiled.EmptyReadOnlyParameters, loc)
                {
                }
 
@@ -2590,15 +2760,11 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public virtual Expression GetTransparentIdentifier (string name)
-               {
-                       return null;
-               }
-
                void ProcessParameters ()
                {
                        int n = parameters.Count;
                        parameter_info = new ToplevelParameterInfo [n];
+                       ToplevelBlock top_parent = Parent == null ? null : Parent.Toplevel;
                        for (int i = 0; i < n; ++i) {
                                parameter_info [i] = new ToplevelParameterInfo (this, i);
 
@@ -2607,21 +2773,8 @@ namespace Mono.CSharp {
                                        continue;
 
                                string name = p.Name;
-                               LocalInfo vi = GetLocalInfo (name);
-                               if (vi != null) {
-                                       Report.SymbolRelatedToPreviousError (vi.Location, name);
-                                       Error_AlreadyDeclared (loc, name, "parent or current");
-                                       continue;
-                               }
-
-                               ToplevelParameterInfo pi = Parent == null ? null : Parent.Toplevel.GetParameterInfo (name);
-                               if (pi != null) {
-                                       Report.SymbolRelatedToPreviousError (pi.Location, name);
-                                       Error_AlreadyDeclared (loc, name, "parent or current");
-                                       continue;
-                               }
-
-                               AddKnownVariable (name, parameter_info [i]);
+                               if (CheckParentConflictName (top_parent, name, loc))
+                                       AddKnownVariable (name, parameter_info [i]);
                        }
 
                        // mark this block as "used" so that we create local declarations in a sub-block
@@ -2641,46 +2794,36 @@ namespace Mono.CSharp {
                        return true;
                }
 
-               public RootScopeInfo CreateRootScope (TypeContainer host)
+               public override Expression CreateExpressionTree (EmitContext ec)
                {
-                       if (root_scope != null)
-                               return root_scope;
-
-                       if (Container == null)
-                               root_scope = new RootScopeInfo (
-                                       this, host, generic, StartLocation);
+                       if (statements.Count == 1) {
+                               Expression expr = ((Statement) statements[0]).CreateExpressionTree (ec);
+                               if (scope_initializers != null)
+                                       expr = new BlockScopeExpression (expr, this);
 
-                       if (scope_info != null)
-                               throw new InternalErrorException ();
-
-                       scope_info = root_scope;
-                       return root_scope;
-               }
+                               return expr;
+                       }
 
-               public override Expression CreateExpressionTree (EmitContext ec)
-               {
-                       return ((Statement) statements [0]).CreateExpressionTree (ec);
+                       return base.CreateExpressionTree (ec);
                }
 
-               public void CreateIteratorHost (RootScopeInfo root)
+               //
+               // Reformats this block to be top-level iterator block
+               //
+               public IteratorStorey ChangeToIterator (Iterator iterator, ToplevelBlock source)
                {
-                       Report.Debug (64, "CREATE ITERATOR HOST", this, root, Parent, root_scope);
+                       IsIterator = true;
 
-                       if (Parent != null || root_scope != null)
-                               throw new InternalErrorException ();
+                       // Creates block with original statements
+                       AddStatement (new IteratorStatement (iterator, new Block (this, source)));
 
-                       scope_info = root_scope = root;
-               }
+                       source.statements = new ArrayList (1);
+                       source.AddStatement (new Return (iterator, iterator.Location));
+                       source.IsIterator = false;
 
-               public RootScopeInfo RootScope {
-                       get {
-                               if (root_scope != null)
-                                       return root_scope;
-                               else if (Container != null)
-                                       return Container.RootScope;
-                               else
-                                       return null;
-                       }
+                       IteratorStorey iterator_storey = new IteratorStorey (iterator);
+                       source.am_storey = iterator_storey;
+                       return iterator_storey;
                }
 
                public FlowBranchingToplevel TopLevelBranching {
@@ -2688,44 +2831,26 @@ namespace Mono.CSharp {
                }
 
                //
-               // This is used if anonymous methods are used inside an iterator
-               // (see 2test-22.cs for an example).
-               //
-               // The AnonymousMethod is created while parsing - at a time when we don't
-               // know yet that we're inside an iterator, so it's `Container' is initially
-               // null.  Later on, when resolving the iterator, we need to move the
-               // anonymous method into that iterator.
-               //
-               public void ReParent (ToplevelBlock new_parent)
-               {
-                       if ((flags & Flags.VariablesInitialized) != 0)
-                               throw new InternalErrorException ("block has already been resolved");
-
-                       Parent = new_parent;
-               }
-
-               //
-               // Returns a `ParameterReference' for the given name, or null if there
-               // is no such parameter
+               // Returns a parameter reference expression for the given name,
+               // or null if there is no such parameter
                //
-               public ParameterReference GetParameterReference (string name, Location loc)
-               {
-                       ToplevelParameterInfo p = GetParameterInfo (name);
-                       return p == null ? null : new ParameterReference (this, p, loc);
-               }
-
-               public ToplevelParameterInfo GetParameterInfo (string name)
+               public Expression GetParameterReference (string name, Location loc)
                {
-                       int idx;
                        for (ToplevelBlock t = this; t != null; t = t.Container) {
-                               Parameter par = t.Parameters.GetParameterByName (name, out idx);
-                               if (par != null)
-                                       return t.parameter_info [idx];
+                               Expression expr = t.GetParameterReferenceExpression (name, loc);
+                               if (expr != null)
+                                       return expr;
                        }
+
                        return null;
                }
 
-               LocalInfo this_variable = null;
+               protected virtual Expression GetParameterReferenceExpression (string name, Location loc)
+               {
+                       int idx = parameters.GetParameterIndexByName (name);
+                       return idx < 0 ?
+                               null : new ParameterReference (parameter_info [idx], loc);
+               }
 
                // <summary>
                //   Returns the "this" instance variable of this block.
@@ -2755,12 +2880,17 @@ namespace Mono.CSharp {
                        return this_variable;
                }
 
+               public bool IsIterator {
+                       get { return (flags & Flags.IsIterator) != 0; }
+                       set { flags = value ? flags | Flags.IsIterator : flags & ~Flags.IsIterator; }
+               }
+
                public bool IsThisAssigned (EmitContext ec)
                {
                        return this_variable == null || this_variable.IsThisAssigned (ec);
                }
 
-               public bool ResolveMeta (EmitContext ec, Parameters ip)
+               public bool ResolveMeta (EmitContext ec, ParametersCompiled ip)
                {
                        int errors = Report.Errors;
                        int orig_count = parameters.Count;
@@ -2778,7 +2908,7 @@ namespace Mono.CSharp {
                        int offset = Parent == null ? 0 : Parent.AssignableSlots;
 
                        for (int i = 0; i < orig_count; ++i) {
-                               Parameter.Modifier mod = parameters.ParameterModifier (i);
+                               Parameter.Modifier mod = parameters.FixedParameters [i].ModFlags;
 
                                if ((mod & Parameter.Modifier.OUT) != Parameter.Modifier.OUT)
                                        continue;
@@ -2821,63 +2951,28 @@ namespace Mono.CSharp {
 
                public override void EmitMeta (EmitContext ec)
                {
+                       parameters.ResolveVariable ();
+
                        // Avoid declaring an IL variable for this_variable since it is not accessed
                        // from the generated IL
                        if (this_variable != null)
                                Variables.Remove ("this");
                        base.EmitMeta (ec);
-                       parameters.ResolveVariable (this);
                }
 
                protected override void EmitSymbolInfo (EmitContext ec)
                {
-                       if ((AnonymousContainer != null) && (AnonymousContainer.Scope != null))
-                               SymbolWriter.DefineScopeVariable (AnonymousContainer.Scope.ID);
+                       AnonymousExpression ae = ec.CurrentAnonymousMethod;
+                       if ((ae != null) && (ae.Storey != null))
+                               SymbolWriter.DefineScopeVariable (ae.Storey.ID);
 
                        base.EmitSymbolInfo (ec);
                }
 
-               public void MakeIterator (Iterator iterator)
-               {
-                       flags |= Flags.IsIterator;
-
-                       Block block = new ExplicitBlock (this, flags, StartLocation, EndLocation);
-                       foreach (Statement stmt in statements)
-                               block.AddStatement (stmt);
-                       statements.Clear ();
-                       statements.Add (new MoveNextStatement (iterator, block));
-               }
-
-               protected class MoveNextStatement : Statement {
-                       Iterator iterator;
-                       Block block;
-
-                       public MoveNextStatement (Iterator iterator, Block block)
-                       {
-                               this.iterator = iterator;
-                               this.block = block;
-                               this.loc = iterator.Location;
-                       }
-
-                       public override bool Resolve (EmitContext ec)
-                       {
-                               ec.StartFlowBranching (iterator);
-                               bool ok = block.Resolve (ec);
-                               ec.EndFlowBranching ();
-                               return ok;
-                       }
-
-                       protected override void DoEmit (EmitContext ec)
-                       {
-                               iterator.EmitMoveNext (ec, block);
-                       }
-               }
-
-               public override string ToString ()
+               public override void Emit (EmitContext ec)
                {
-                       return String.Format ("{0} ({1}:{2}{3}:{4})", GetType (), ID, StartLocation,
-                                             root_scope, anonymous_container != null ?
-                                             anonymous_container.Scope : null);
+                       base.Emit (ec);
+                       ec.Mark (EndLocation);
                }
        }
        
@@ -2908,6 +3003,10 @@ namespace Mono.CSharp {
                        }
                }
 
+               public Location Location {
+                       get { return loc; }
+               }
+
                public object Converted {
                        get {
                                return converted;
@@ -2959,7 +3058,7 @@ namespace Mono.CSharp {
                                return true;
                        }
                        
-                       c = c.ImplicitConversionRequired (required_type, loc);
+                       c = c.ImplicitConversionRequired (ec, required_type, loc);
                        if (c == null)
                                return false;
 
@@ -2974,8 +3073,6 @@ namespace Mono.CSharp {
                                label = "default";
                        else if (converted == NullStringCase)
                                label = "null";
-                       else if (TypeManager.IsEnumType (switch_type)) 
-                               label = TypeManager.CSharpEnumValue (switch_type, converted);
                        else
                                label = converted.ToString ();
                        
@@ -3032,23 +3129,22 @@ namespace Mono.CSharp {
                Label null_target;
                Expression new_expr;
                bool is_constant;
+               bool has_null_case;
                SwitchSection constant_section;
                SwitchSection default_section;
 
-#if GMCS_SOURCE
+               ExpressionStatement string_dictionary;
+               FieldExpr switch_cache_field;
+               static int unique_counter;
+
                //
-               // Nullable Types support for GMCS.
+               // Nullable Types support
                //
                Nullable.Unwrap unwrap;
 
                protected bool HaveUnwrap {
                        get { return unwrap != null; }
                }
-#else
-               protected bool HaveUnwrap {
-                       get { return false; }
-               }
-#endif
 
                //
                // The types allowed to be implicitly cast from
@@ -3110,8 +3206,7 @@ namespace Mono.CSharp {
                                        TypeManager.int64_type,
                                        TypeManager.uint64_type,
                                        TypeManager.char_type,
-                                       TypeManager.string_type,
-                                       TypeManager.bool_type
+                                       TypeManager.string_type
                                };
                        }
 
@@ -3137,10 +3232,7 @@ namespace Mono.CSharp {
                                        continue;
 
                                if (converted != null){
-                                       Report.ExtraInformation (
-                                               loc,
-                                               String.Format ("reason: more than one conversion to an integral type exist for type {0}",
-                                                              TypeManager.CSharpName (expr.Type)));
+                                       Report.ExtraInformation (loc, "(Ambiguous implicit user defined conversion in previous ");
                                        return null;
                                }
 
@@ -3180,6 +3272,9 @@ namespace Mono.CSharp {
                                        }
                                        
                                        object key = sl.Converted;
+                                       if (key == SwitchLabel.NullStringCase)
+                                               has_null_case = true;
+
                                        try {
                                                Elements.Add (key, sl);
                                        } catch (ArgumentException) {
@@ -3280,7 +3375,7 @@ namespace Mono.CSharp {
                /// <param name="ec"></param>
                /// <param name="val"></param>
                /// <returns></returns>
-               void TableSwitchEmit (EmitContext ec, LocalBuilder val)
+               void TableSwitchEmit (EmitContext ec, Expression val)
                {
                        int element_count = Elements.Count;
                        object [] element_keys = new object [element_count];
@@ -3288,7 +3383,7 @@ namespace Mono.CSharp {
                        Array.Sort (element_keys);
 
                        // initialize the block list with one element per key
-                       ArrayList key_blocks = new ArrayList ();
+                       ArrayList key_blocks = new ArrayList (element_count);
                        foreach (object key in element_keys)
                                key_blocks.Add (new KeyBlock (System.Convert.ToInt64 (key)));
 
@@ -3345,7 +3440,7 @@ namespace Mono.CSharp {
                        // okay now we can start...
                        ILGenerator ig = ec.ig;
                        Label lbl_end = ig.DefineLabel ();      // at the end ;-)
-                       Label lbl_default = ig.DefineLabel ();
+                       Label lbl_default = default_target;
 
                        Type type_keys = null;
                        if (element_keys.Length > 0)
@@ -3361,15 +3456,18 @@ namespace Mono.CSharp {
                        for (int iBlock = key_blocks.Count - 1; iBlock >= 0; --iBlock)
                        {
                                KeyBlock kb = ((KeyBlock) key_blocks [iBlock]);
-                               lbl_default = (iBlock == 0) ? DefaultTarget : ig.DefineLabel ();
+                               lbl_default = (iBlock == 0) ? default_target : ig.DefineLabel ();
                                if (kb.Length <= 2)
                                {
-                                       foreach (object key in kb.element_keys)
-                                       {
-                                               ig.Emit (OpCodes.Ldloc, val);
-                                               EmitObjectInteger (ig, key);
+                                       foreach (object key in kb.element_keys) {
                                                SwitchLabel sl = (SwitchLabel) Elements [key];
-                                               ig.Emit (OpCodes.Beq, sl.GetILLabel (ec));
+                                               if (key is int && (int) key == 0) {
+                                                       val.EmitBranchable (ec, sl.GetILLabel (ec), false);
+                                               } else {
+                                                       val.Emit (ec);
+                                                       EmitObjectInteger (ig, key);
+                                                       ig.Emit (OpCodes.Beq, sl.GetILLabel (ec));
+                                               }
                                        }
                                }
                                else
@@ -3382,15 +3480,15 @@ namespace Mono.CSharp {
                                                // TODO: optimize constant/I4 cases
 
                                                // check block range (could be > 2^31)
-                                               ig.Emit (OpCodes.Ldloc, val);
+                                               val.Emit (ec);
                                                EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
                                                ig.Emit (OpCodes.Blt, lbl_default);
-                                               ig.Emit (OpCodes.Ldloc, val);
+                                               val.Emit (ec);
                                                EmitObjectInteger (ig, System.Convert.ChangeType (kb.last, type_keys));
                                                ig.Emit (OpCodes.Bgt, lbl_default);
 
                                                // normalize range
-                                               ig.Emit (OpCodes.Ldloc, val);
+                                               val.Emit (ec);
                                                if (kb.first != 0)
                                                {
                                                        EmitObjectInteger (ig, System.Convert.ChangeType (kb.first, type_keys));
@@ -3401,7 +3499,7 @@ namespace Mono.CSharp {
                                        else
                                        {
                                                // normalize range
-                                               ig.Emit (OpCodes.Ldloc, val);
+                                               val.Emit (ec);
                                                int first = (int) kb.first;
                                                if (first > 0)
                                                {
@@ -3445,145 +3543,37 @@ namespace Mono.CSharp {
                        //       make sure to mark other labels in the default section
 
                        // the last default just goes to the end
-                       ig.Emit (OpCodes.Br, lbl_default);
+                       if (element_keys.Length > 0)
+                               ig.Emit (OpCodes.Br, lbl_default);
 
                        // now emit the code for the sections
                        bool found_default = false;
-                       bool found_null = false;
-                       foreach (SwitchSection ss in Sections)
-                       {
-                               foreach (SwitchLabel sl in ss.Labels)
-                                       if (sl.Converted == SwitchLabel.NullStringCase)
-                                               found_null = true;
-                       }
 
-                       foreach (SwitchSection ss in Sections)
-                       {
-                               foreach (SwitchLabel sl in ss.Labels)
-                               {
-                                       ig.MarkLabel (sl.GetILLabel (ec));
-                                       ig.MarkLabel (sl.GetILLabelCode (ec));
-                                       if (sl.Converted == SwitchLabel.NullStringCase)
+                       foreach (SwitchSection ss in Sections) {
+                               foreach (SwitchLabel sl in ss.Labels) {
+                                       if (sl.Converted == SwitchLabel.NullStringCase) {
                                                ig.MarkLabel (null_target);
-                                       else if (sl.Label == null) {
+                                       else if (sl.Label == null) {
                                                ig.MarkLabel (lbl_default);
                                                found_default = true;
-                                               if (!found_null)
+                                               if (!has_null_case)
                                                        ig.MarkLabel (null_target);
                                        }
+                                       ig.MarkLabel (sl.GetILLabel (ec));
+                                       ig.MarkLabel (sl.GetILLabelCode (ec));
                                }
                                ss.Block.Emit (ec);
                        }
                        
                        if (!found_default) {
                                ig.MarkLabel (lbl_default);
-                               if (HaveUnwrap && !found_null) {
+                               if (!has_null_case) {
                                        ig.MarkLabel (null_target);
                                }
                        }
                        
                        ig.MarkLabel (lbl_end);
                }
-               //
-               // This simple emit switch works, but does not take advantage of the
-               // `switch' opcode. 
-               // TODO: remove non-string logic from here
-               // TODO: binary search strings?
-               //
-               void SimpleSwitchEmit (EmitContext ec, LocalBuilder val)
-               {
-                       ILGenerator ig = ec.ig;
-                       Label end_of_switch = ig.DefineLabel ();
-                       Label next_test = ig.DefineLabel ();
-                       bool first_test = true;
-                       bool pending_goto_end = false;
-                       bool null_marked = false;
-                       bool null_found;
-                       int section_count = Sections.Count;
-
-                       // TODO: implement switch optimization for string by using Hashtable
-                       //if (SwitchType == TypeManager.string_type && section_count > 7)
-                       //      Console.WriteLine ("Switch optimization possible " + loc);
-
-                       ig.Emit (OpCodes.Ldloc, val);
-                       
-                       if (Elements.Contains (SwitchLabel.NullStringCase)){
-                               ig.Emit (OpCodes.Brfalse, null_target);
-                       } else
-                               ig.Emit (OpCodes.Brfalse, default_target);
-                       
-                       ig.Emit (OpCodes.Ldloc, val);
-                       ig.Emit (OpCodes.Call, TypeManager.string_isinterned_string);
-                       ig.Emit (OpCodes.Stloc, val);
-
-                       for (int section = 0; section < section_count; section++){
-                               SwitchSection ss = (SwitchSection) Sections [section];
-
-                               if (ss == default_section)
-                                       continue;
-
-                               Label sec_begin = ig.DefineLabel ();
-
-                               ig.Emit (OpCodes.Nop);
-
-                               if (pending_goto_end)
-                                       ig.Emit (OpCodes.Br, end_of_switch);
-
-                               int label_count = ss.Labels.Count;
-                               null_found = false;
-                               for (int label = 0; label < label_count; label++){
-                                       SwitchLabel sl = (SwitchLabel) ss.Labels [label];
-                                       ig.MarkLabel (sl.GetILLabel (ec));
-                                       
-                                       if (!first_test){
-                                               ig.MarkLabel (next_test);
-                                               next_test = ig.DefineLabel ();
-                                       }
-                                       //
-                                       // If we are the default target
-                                       //
-                                       if (sl.Label != null){
-                                               object lit = sl.Converted;
-
-                                               if (lit == SwitchLabel.NullStringCase){
-                                                       null_found = true;
-                                                       if (label + 1 == label_count)
-                                                               ig.Emit (OpCodes.Br, next_test);
-                                                       continue;
-                                               }
-                                               
-                                               ig.Emit (OpCodes.Ldloc, val);
-                                               ig.Emit (OpCodes.Ldstr, (string)lit);
-                                               if (label_count == 1)
-                                                       ig.Emit (OpCodes.Bne_Un, next_test);
-                                               else {
-                                                       if (label+1 == label_count)
-                                                               ig.Emit (OpCodes.Bne_Un, next_test);
-                                                       else
-                                                               ig.Emit (OpCodes.Beq, sec_begin);
-                                               }
-                                       }
-                               }
-                               if (null_found) {
-                                       ig.MarkLabel (null_target);
-                                       null_marked = true;
-                               }
-                               ig.MarkLabel (sec_begin);
-                               foreach (SwitchLabel sl in ss.Labels)
-                                       ig.MarkLabel (sl.GetILLabelCode (ec));
-
-                               ss.Block.Emit (ec);
-                               pending_goto_end = !ss.Block.HasRet;
-                               first_test = false;
-                       }
-                       ig.MarkLabel (next_test);
-                       ig.MarkLabel (default_target);
-                       if (!null_marked)
-                               ig.MarkLabel (null_target);
-                       if (default_section != null)
-                               default_section.Block.Emit (ec);
-                       ig.MarkLabel (end_of_switch);
-               }
 
                SwitchSection FindSection (SwitchLabel label)
                {
@@ -3597,6 +3587,18 @@ namespace Mono.CSharp {
                        return null;
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       foreach (SwitchSection ss in Sections)
+                               ss.Block.MutateHoistedGenericType (storey);
+               }
+
+               public static void Reset ()
+               {
+                       unique_counter = 0;
+                       allowed_types = null;
+               }
+
                public override bool Resolve (EmitContext ec)
                {
                        Expr = Expr.Resolve (ec);
@@ -3605,15 +3607,13 @@ namespace Mono.CSharp {
 
                        new_expr = SwitchGoverningType (ec, Expr);
 
-#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;
 
                                new_expr = SwitchGoverningType (ec, unwrap);
                        }
-#endif
 
                        if (new_expr == null){
                                Report.Error (151, loc, "A value of an integral type or string expected for switch");
@@ -3683,35 +3683,152 @@ namespace Mono.CSharp {
 
                        Report.Debug (1, "END OF SWITCH BLOCK", loc, ec.CurrentBranching);
 
-                       if (TypeManager.string_isinterned_string == null) {
-                               TypeManager.string_isinterned_string = TypeManager.GetPredefinedMethod (TypeManager.string_type,
-                                       "IsInterned", loc, TypeManager.string_type);
+                       if (!ok)
+                               return false;
+
+                       if (SwitchType == TypeManager.string_type && !is_constant) {
+                               // TODO: Optimize single case, and single+default case
+                               ResolveStringSwitchMap (ec);
                        }
 
-                       return ok;
+                       return true;
                }
-               
-               protected override void DoEmit (EmitContext ec)
+
+               void ResolveStringSwitchMap (EmitContext ec)
                {
-                       ILGenerator ig = ec.ig;
+                       FullNamedExpression string_dictionary_type;
+                       if (TypeManager.generic_ienumerable_type != null) {
+                               MemberAccess system_collections_generic = new MemberAccess (new MemberAccess (
+                                       new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc), "Generic", loc);
 
-                       default_target = ig.DefineLabel ();
-                       null_target = ig.DefineLabel ();
+                               string_dictionary_type = new MemberAccess (system_collections_generic, "Dictionary",
+                                       new TypeArguments (
+                                               new TypeExpression (TypeManager.string_type, loc),
+                                               new TypeExpression (TypeManager.int32_type, loc)), loc);
+                       } else {
+                               MemberAccess system_collections_generic = new MemberAccess (
+                                       new QualifiedAliasMember (QualifiedAliasMember.GlobalAlias, "System", loc), "Collections", loc);
 
-                       // Store variable for comparission purposes
-                       LocalBuilder value;
-                       if (HaveUnwrap) {
-                               value = ig.DeclareLocal (SwitchType);
-#if GMCS_SOURCE
-                               unwrap.EmitCheck (ec);
-                               ig.Emit (OpCodes.Brfalse, null_target);
+                               string_dictionary_type = new MemberAccess (system_collections_generic, "Hashtable", loc);
+                       }
+
+                       Field field = new Field (ec.TypeContainer, string_dictionary_type,
+                               Modifiers.STATIC | Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED,
+                               new MemberName (CompilerGeneratedClass.MakeName (null, "f", "switch$map", unique_counter++), loc), null);
+                       if (!field.Define ())
+                               return;
+                       ec.TypeContainer.PartialContainer.AddField (field);
+
+                       ArrayList init = new ArrayList ();
+                       int counter = 0;
+                       Elements.Clear ();
+                       string value = null;
+                       foreach (SwitchSection section in Sections) {
+                               int last_count = init.Count;
+                               foreach (SwitchLabel sl in section.Labels) {
+                                       if (sl.Label == null || sl.Converted == SwitchLabel.NullStringCase)
+                                               continue;
+
+                                       value = (string) sl.Converted;
+                                       ArrayList init_args = new ArrayList (2);
+                                       init_args.Add (new StringLiteral (value, sl.Location));
+                                       init_args.Add (new IntConstant (counter, loc));
+                                       init.Add (new CollectionElementInitializer (init_args, loc));
+                               }
+
+                               //
+                               // Don't add empty sections
+                               //
+                               if (last_count == init.Count)
+                                       continue;
+
+                               Elements.Add (counter, section.Labels [0]);
+                               ++counter;
+                       }
+
+                       ArrayList args = new ArrayList (1);
+                       args.Add (new Argument (new IntConstant (init.Count, loc)));
+                       Expression initializer = new NewInitialize (string_dictionary_type, args,
+                               new CollectionOrObjectInitializers (init, loc), loc);
+
+                       switch_cache_field = new FieldExpr (field.FieldBuilder, loc);
+                       string_dictionary = new SimpleAssign (switch_cache_field, initializer.Resolve (ec));
+               }
+
+               void DoEmitStringSwitch (LocalTemporary value, EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+                       Label l_initialized = ig.DefineLabel ();
+
+                       //
+                       // Skip initialization when value is null
+                       //
+                       value.EmitBranchable (ec, null_target, false);
+
+                       //
+                       // Check if string dictionary is initialized and initialize
+                       //
+                       switch_cache_field.EmitBranchable (ec, l_initialized, true);
+                       string_dictionary.EmitStatement (ec);
+                       ig.MarkLabel (l_initialized);
+
+                       LocalTemporary string_switch_variable = new LocalTemporary (TypeManager.int32_type);
+
+                       if (TypeManager.generic_ienumerable_type != null) {
+                               ArrayList get_value_args = new ArrayList (2);
+                               get_value_args.Add (new Argument (value));
+                               get_value_args.Add (new Argument (string_switch_variable, Argument.AType.Out));
+                               Expression get_item = new Invocation (new MemberAccess (switch_cache_field, "TryGetValue", loc), get_value_args).Resolve (ec);
+                               if (get_item == null)
+                                       return;
+
+                               //
+                               // A value was not found, go to default case
+                               //
+                               get_item.EmitBranchable (ec, default_target, false);
+                       } else {
+                               ArrayList get_value_args = new ArrayList (1);
+                               get_value_args.Add (value);
+
+                               Expression get_item = new IndexerAccess (new ElementAccess (switch_cache_field, get_value_args), loc).Resolve (ec);
+                               if (get_item == null)
+                                       return;
+
+                               LocalTemporary get_item_object = new LocalTemporary (TypeManager.object_type);
+                               get_item_object.EmitAssign (ec, get_item, true, false);
+                               ec.ig.Emit (OpCodes.Brfalse, default_target);
+
+                               ExpressionStatement get_item_int = (ExpressionStatement) new SimpleAssign (string_switch_variable,
+                                       new Cast (new TypeExpression (TypeManager.int32_type, loc), get_item_object, loc)).Resolve (ec);
+
+                               get_item_int.EmitStatement (ec);
+                               get_item_object.Release (ec);
+                       }
+
+                       TableSwitchEmit (ec, string_switch_variable);
+                       string_switch_variable.Release (ec);
+               }
+               
+               protected override void DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
+
+                       default_target = ig.DefineLabel ();
+                       null_target = ig.DefineLabel ();
+
+                       // Store variable for comparission purposes
+                       // TODO: Don't duplicate non-captured VariableReference
+                       LocalTemporary value;
+                       if (HaveUnwrap) {
+                               value = new LocalTemporary (SwitchType);
+                               unwrap.EmitCheck (ec);
+                               ig.Emit (OpCodes.Brfalse, null_target);
                                new_expr.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, value);
-#endif
+                               value.Store (ec);
                        } else if (!is_constant) {
-                               value = ig.DeclareLocal (SwitchType);
+                               value = new LocalTemporary (SwitchType);
                                new_expr.Emit (ec);
-                               ig.Emit (OpCodes.Stloc, value);
+                               value.Store (ec);
                        } else
                                value = null;
 
@@ -3728,10 +3845,14 @@ namespace Mono.CSharp {
                        if (is_constant) {
                                if (constant_section != null)
                                        constant_section.Block.Emit (ec);
-                       } else if (SwitchType == TypeManager.string_type)
-                               SimpleSwitchEmit (ec, value);
-                       else
+                       } else if (string_dictionary != null) {
+                               DoEmitStringSwitch (value, ec);
+                       } else {
                                TableSwitchEmit (ec, value);
+                       }
+
+                       if (value != null)
+                               value.Release (ec);
 
                        // Restore context state. 
                        ig.MarkLabel (ec.LoopEnd);
@@ -3849,7 +3970,7 @@ namespace Mono.CSharp {
 
                ArrayList resume_points;
                int first_resume_pc;
-               public void AddResumePoint (ResumableStatement stmt, Location loc, int pc)
+               public void AddResumePoint (ResumableStatement stmt, int pc)
                {
                        if (resume_points == null) {
                                resume_points = new ArrayList ();
@@ -3954,7 +4075,7 @@ namespace Mono.CSharp {
                        if (expr == null)
                                return false;
 
-                       if (expr.Type.IsValueType){
+                       if (!TypeManager.IsReferenceType (expr.Type)){
                                Report.Error (185, loc,
                                              "`{0}' is not a reference type as required by the lock statement",
                                              TypeManager.CSharpName (expr.Type));
@@ -3991,7 +4112,7 @@ namespace Mono.CSharp {
                {
                        ILGenerator ig = ec.ig;
 
-                       temp.Store (ec, expr);
+                       temp.EmitAssign (ec, expr);
                        temp.Emit (ec);
                        ig.Emit (OpCodes.Call, TypeManager.void_monitor_enter_object);
                }
@@ -4006,6 +4127,13 @@ namespace Mono.CSharp {
                        temp.Emit (ec);
                        ec.ig.Emit (OpCodes.Call, TypeManager.void_monitor_exit_object);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr.MutateHoistedGenericType (storey);
+                       temp.MutateHoistedGenericType (storey);
+                       Statement.MutateHoistedGenericType (storey);
+               }
                
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
@@ -4037,6 +4165,11 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Block.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unchecked target = (Unchecked) t;
@@ -4066,6 +4199,11 @@ namespace Mono.CSharp {
                                Block.Emit (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Block.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Checked target = (Checked) t;
@@ -4094,6 +4232,12 @@ namespace Mono.CSharp {
                        using (ec.With (EmitContext.Flags.InUnsafe, true))
                                Block.Emit (ec);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Block.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Unsafe target = (Unsafe) t;
@@ -4139,92 +4283,62 @@ namespace Mono.CSharp {
                                // Store pointer in pinned location
                                //
                                converted.Emit (ec);
-                               vi.Variable.EmitAssign (ec);
+                               vi.EmitAssign (ec);
                        }
 
                        public override void EmitExit (EmitContext ec)
                        {
                                ec.ig.Emit (OpCodes.Ldc_I4_0);
                                ec.ig.Emit (OpCodes.Conv_U);
-                               vi.Variable.EmitAssign (ec);
+                               vi.EmitAssign (ec);
                        }
                }
 
-               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);
-                               vi.Variable.EmitAssign (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);
                        }
                }
 
@@ -4287,43 +4401,6 @@ namespace Mono.CSharp {
                                        Report.Error (254, loc, "The right hand side of a fixed statement assignment may not be a cast expression");
                                        return false;
                                }
-                               
-                               //
-                               // Case 1: & object.
-                               //
-                               if (e is Unary && ((Unary) e).Oper == Unary.Operator.AddressOf){
-                                       Expression child = ((Unary) e).Expr;
-
-                                       if (child is ParameterReference || child is LocalVariableReference){
-                                               Report.Error (
-                                                       213, loc, 
-                                                       "No need to use fixed statement for parameters or " +
-                                                       "local variable declarations (address is already " +
-                                                       "fixed)");
-                                               return false;
-                                       }
-
-                                       ec.InFixedInitializer = true;
-                                       e = e.Resolve (ec);
-                                       ec.InFixedInitializer = false;
-                                       if (e == null)
-                                               return false;
-
-                                       child = ((Unary) e).Expr;
-                                       
-                                       if (!TypeManager.VerifyUnManaged (child.Type, loc))
-                                               return false;
-
-                                       if (!Convert.ImplicitConversionExists (ec, e, expr_type)) {
-                                               e.Error_ValueCannotBeConverted (ec, e.Location, expr_type, false);
-                                               return false;
-                                       }
-
-                                       data [i] = new ExpressionEmitter (e, vi);
-                                       i++;
-
-                                       continue;
-                               }
 
                                ec.InFixedInitializer = true;
                                e = e.Resolve (ec);
@@ -4360,7 +4437,7 @@ namespace Mono.CSharp {
                                        converted = new Conditional (new Binary (Binary.Operator.LogicalOr,
                                                new Binary (Binary.Operator.Equality, e, new NullLiteral (loc)),
                                                new Binary (Binary.Operator.Equality, new MemberAccess (e, "Length"), new IntConstant (0, loc))),
-                                                       NullPointer.Null,
+                                                       new NullPointer (loc),
                                                        converted);
 
                                        converted = converted.Resolve (ec);                                     
@@ -4381,24 +4458,26 @@ namespace Mono.CSharp {
                                }
 
                                // Case 4: fixed buffer
-                               FixedBufferPtr fixed_buffer_ptr = e as FixedBufferPtr;
-                               if (fixed_buffer_ptr != null) {
-                                       data [i++] = new ExpressionEmitter (fixed_buffer_ptr, vi);
+                               if (e is FixedBufferPtr) {
+                                       data [i++] = new ExpressionEmitter (e, vi);
                                        continue;
                                }
 
                                //
-                               // For other cases, flag a `this is already fixed expression'
+                               // Case 1: & object.
                                //
-                               if (e is LocalVariableReference || e is ParameterReference ||
-                                   Convert.ImplicitConversionExists (ec, e, vi.VariableType)){
-                                   
-                                       Report.Error (245, loc, "right hand expression is already fixed, no need to use fixed statement ");
-                                       return false;
+                               Unary u = e as Unary;
+                               if (u != null && u.Oper == Unary.Operator.AddressOf) {
+                                       IVariableReference vr = u.Expr as IVariableReference;
+                                       if (vr == null || !vr.IsFixed) {
+                                               data [i] = new ExpressionEmitter (e, vi);
+                                       }
                                }
 
-                               Report.Error (245, loc, "Fixed statement only allowed on strings, arrays or address-of expressions");
-                               return false;
+                               if (data [i++] == null)
+                                       Report.Error (213, vi.Location, "You cannot use the fixed statement to take the address of an already fixed expression");
+
+                               e = Convert.ImplicitConversionRequired (ec, e, expr_type, loc);
                        }
 
                        ec.StartFlowBranching (FlowBranching.BranchingType.Conditional, loc);
@@ -4428,6 +4507,12 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       // Fixed statement cannot be used inside anonymous methods or lambdas
+                       throw new NotSupportedException ();
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Fixed target = (Fixed) t;
@@ -4488,19 +4573,27 @@ namespace Mono.CSharp {
                                VarBlock.Emit (ec);
 
                        if (Name != null) {
-                               LocalInfo vi = Block.GetLocalInfo (Name);
-                               if (vi == null)
-                                       throw new Exception ("Variable does not exist in this block");
+                               // TODO: Move to resolve
+                               LocalVariableReference lvr = new LocalVariableReference (Block, Name, loc);
+                               lvr.Resolve (ec);
+                               
+#if GMCS_SOURCE
+                               // Only to make verifier happy
+                               if (TypeManager.IsGenericParameter (lvr.Type))
+                                       ig.Emit (OpCodes.Unbox_Any, lvr.Type);
+#endif
 
-                               if (vi.Variable.NeedsTemporary) {
-                                       LocalBuilder e = ig.DeclareLocal (vi.VariableType);
-                                       ig.Emit (OpCodes.Stloc, e);
+                               Expression source;
+                               if (lvr.IsHoisted) {
+                                       LocalTemporary lt = new LocalTemporary (lvr.Type);
+                                       lt.Store (ec);
+                                       source = lt;
+                               } else {
+                                       // Variable is at the top of the stack
+                                       source = EmptyExpression.Null;
+                               }
 
-                                       vi.Variable.EmitInstance (ec);
-                                       ig.Emit (OpCodes.Ldloc, e);
-                                       vi.Variable.EmitAssign (ec);
-                               } else
-                                       vi.Variable.EmitAssign (ec);
+                               lvr.EmitAssign (ec, source, false, false);
                        } else
                                ig.Emit (OpCodes.Pop);
 
@@ -4536,6 +4629,15 @@ namespace Mono.CSharp {
                        }
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       if (type != null)
+                               type = storey.MutateType (type);
+                       if (VarBlock != null)
+                               VarBlock.MutateHoistedGenericType (storey);
+                       Block.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        Catch target = (Catch) t;
@@ -4596,6 +4698,12 @@ namespace Mono.CSharp {
                        fini.Emit (ec);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       stmt.MutateHoistedGenericType (storey);
+                       fini.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryFinally target = (TryFinally) t;
@@ -4661,7 +4769,9 @@ namespace Mono.CSharp {
                                Type resolved_type = c.CatchType;
                                for (int ii = 0; ii < last_index; ++ii) {
                                        if (resolved_type == prev_catches [ii] || TypeManager.IsSubclassOf (resolved_type, prev_catches [ii])) {
-                                               Report.Error (160, c.loc, "A previous catch clause already catches all exceptions of this or a super type `{0}'", prev_catches [ii].FullName);
+                                               Report.Error (160, c.loc,
+                                                       "A previous catch clause already catches all exceptions of this or a super type `{0}'",
+                                                       TypeManager.CSharpName (prev_catches [ii]));
                                                ok = false;
                                        }
                                }
@@ -4672,7 +4782,7 @@ namespace Mono.CSharp {
                        if (General != null) {
                                if (CodeGen.Assembly.WrapNonExceptionThrows) {
                                        foreach (Catch c in Specific){
-                                               if (c.CatchType == TypeManager.exception_type) {
+                                               if (c.CatchType == TypeManager.exception_type && PredefinedAttributes.Get.RuntimeCompatibility.IsDefined) {
                                                        Report.Warning (1058, 1, c.loc, "A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a `System.Runtime.CompilerServices.RuntimeWrappedException'");
                                                }
                                        }
@@ -4718,6 +4828,18 @@ namespace Mono.CSharp {
                                ig.EndExceptionBlock ();
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       Block.MutateHoistedGenericType (storey);
+
+                       if (General != null)
+                               General.MutateHoistedGenericType (storey);
+                       if (Specific != null) {
+                               foreach (Catch c in Specific)
+                                       c.MutateHoistedGenericType (storey);
+                       }
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        TryCatch target = (TryCatch) t;
@@ -4733,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;
@@ -4782,7 +4905,7 @@ namespace Mono.CSharp {
 
                protected override void EmitPreTryBody (EmitContext ec)
                {
-                       local_copy.Store (ec, expr);
+                       local_copy.EmitAssign (ec, expr);
                }
 
                protected override void EmitTryBody (EmitContext ec)
@@ -4790,10 +4913,10 @@ namespace Mono.CSharp {
                        Statement.Emit (ec);
                }
 
-               protected override void EmitFinallyBody (EmitContext ec)
+               protected override void EmitFinallyBody (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
-                       if (!expr_type.IsValueType) {
+                       if (!TypeManager.IsStruct (expr_type)) {
                                Label skip = ig.DefineLabel ();
                                local_copy.Emit (ec);
                                ig.Emit (OpCodes.Brfalse, skip);
@@ -4832,6 +4955,13 @@ namespace Mono.CSharp {
                        ig.Emit (OpCodes.Call, mi);
                }
 
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       expr_type = storey.MutateType (expr_type);
+                       local_copy.MutateHoistedGenericType (storey);
+                       Statement.MutateHoistedGenericType (storey);
+               }
+
                protected override void CloneTo (CloneContext clonectx, Statement t)
                {
                        UsingTemporary target = (UsingTemporary) t;
@@ -4850,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)
@@ -4861,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);
@@ -4906,42 +5010,25 @@ namespace Mono.CSharp {
                protected override void EmitFinallyBody (EmitContext ec)
                {
                        ILGenerator ig = ec.ig;
+                       Label skip = ig.DefineLabel ();
 
-                       if (!var.Type.IsValueType) {
-                               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;
-                                       }
+                       Invocation.EmitCall (ec, false, var, TypeManager.void_dispose_void, new ArrayList (0), loc);
 
-                                       IMemoryLocation mloc = (IMemoryLocation) var;
+                       if (emit_null_check)
+                               ig.MarkLabel (skip);
+               }
 
-                                       mloc.AddressOf (ec, AddressOp.Load);
-                                       ig.Emit (OpCodes.Call, mi);
-                               }
-                       }
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       assign.MutateHoistedGenericType (storey);
+                       var.MutateHoistedGenericType (storey);
+                       stmt.MutateHoistedGenericType (storey);
                }
 
                public override bool Resolve (EmitContext ec)
@@ -4965,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;
@@ -4979,153 +5087,80 @@ namespace Mono.CSharp {
        ///   Implementation of the foreach C# statement
        /// </summary>
        public class Foreach : Statement {
-               Expression type;
-               Expression variable;
-               Expression expr;
-               Statement statement;
-               ArrayForeach array;
-               CollectionForeach collection;
-               
-               public Foreach (Expression type, LocalVariableReference var, Expression expr,
-                               Statement stmt, Location l)
-               {
-                       this.type = type;
-                       this.variable = var;
-                       this.expr = expr;
-                       statement = stmt;
-                       loc = l;
-               }
-
-               public Statement Statement {
-                       get { return statement; }
-               }
-
-               public override bool Resolve (EmitContext ec)
-               {
-                       expr = expr.Resolve (ec);
-                       if (expr == null)
-                               return false;
-
-                       if (expr.IsNull) {
-                               Report.Error (186, loc, "Use of null is not valid in this context");
-                               return false;
-                       }
-
-                       if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
-                               Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
-                                       expr.ExprClassName);
-                               return false;
-                       }
-
-                       //
-                       // We need an instance variable.  Not sure this is the best
-                       // way of doing this.
-                       //
-                       // FIXME: When we implement propertyaccess, will those turn
-                       // out to return values in ExprClass?  I think they should.
-                       //
-                       if (!(expr.eclass == ExprClass.Variable || expr.eclass == ExprClass.Value ||
-                             expr.eclass == ExprClass.PropertyAccess || expr.eclass == ExprClass.IndexerAccess)){
-                               collection.Error_Enumerator ();
-                               return false;
-                       }
-
-                       if (expr.Type.IsArray) {
-                               array = new ArrayForeach (type, variable, expr, statement, loc);
-                               return array.Resolve (ec);
-                       }
-                       
-                       collection = new CollectionForeach (type, variable, expr, statement, loc);
-                       return collection.Resolve (ec);
-               }
 
-               protected override void DoEmit (EmitContext ec)
+               sealed class ArrayForeach : Statement
                {
-                       ILGenerator ig = ec.ig;
-                       
-                       Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
-                       ec.LoopBegin = ig.DefineLabel ();
-                       ec.LoopEnd = ig.DefineLabel ();
+                       class ArrayCounter : TemporaryVariable
+                       {
+                               StatementExpression increment;
 
-                       if (collection != null)
-                               collection.Emit (ec);
-                       else
-                               array.Emit (ec);
-                       
-                       ec.LoopBegin = old_begin;
-                       ec.LoopEnd = old_end;
-               }
+                               public ArrayCounter (Location loc)
+                                       : base (TypeManager.int32_type, loc)
+                               {
+                               }
 
-               protected class ArrayCounter : TemporaryVariable
-               {
-                       public ArrayCounter (Location loc)
-                               : base (TypeManager.int32_type, loc)
-                       { }
+                               public void ResolveIncrement (EmitContext ec)
+                               {
+                                       increment = new StatementExpression (new UnaryMutator (UnaryMutator.Mode.PostIncrement, this));
+                                       increment.Resolve (ec);
+                               }
 
-                       public void Initialize (EmitContext ec)
-                       {
-                               EmitThis (ec);
-                               ec.ig.Emit (OpCodes.Ldc_I4_0);
-                               EmitStore (ec);
+                               public void EmitIncrement (EmitContext ec)
+                               {
+                                       increment.Emit (ec);
+                               }
                        }
 
-                       public void Increment (EmitContext ec)
-                       {
-                               EmitThis (ec);
-                               Emit (ec);
-                               ec.ig.Emit (OpCodes.Ldc_I4_1);
-                               ec.ig.Emit (OpCodes.Add);
-                               EmitStore (ec);
-                       }
-               }
+                       readonly Foreach for_each;
+                       readonly Statement statement;
 
-               protected class ArrayForeach : Statement
-               {
-                       Expression variable, expr, conv;
-                       Statement statement;
-                       Type array_type;
-                       Expression var_type;
+                       Expression conv;
                        TemporaryVariable[] lengths;
+                       Expression [] length_exprs;
                        ArrayCounter[] counter;
-                       int rank;
 
                        TemporaryVariable copy;
                        Expression access;
-                       Expression[] length_exprs;
 
-                       public ArrayForeach (Expression var_type, Expression var,
-                                            Expression expr, Statement stmt, Location l)
+                       public ArrayForeach (Foreach @foreach, int rank)
                        {
-                               this.var_type = var_type;
-                               this.variable = var;
-                               this.expr = expr;
-                               statement = stmt;
-                               loc = l;
+                               for_each = @foreach;
+                               statement = for_each.statement;
+                               loc = @foreach.loc;
+
+                               counter = new ArrayCounter [rank];
+                               length_exprs = new Expression [rank];
+
+                               //
+                               // Only use temporary length variables when dealing with
+                               // multi-dimensional arrays
+                               //
+                               if (rank > 1)
+                                       lengths = new TemporaryVariable [rank];
                        }
 
-                       public override bool Resolve (EmitContext ec)
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
                        {
-                               array_type = expr.Type;
-                               rank = array_type.GetArrayRank ();
+                               throw new NotImplementedException ();
+                       }
 
-                               copy = new TemporaryVariable (array_type, loc);
+                       public override bool Resolve (EmitContext ec)
+                       {
+                               copy = new TemporaryVariable (for_each.expr.Type, loc);
                                copy.Resolve (ec);
 
-                               counter = new ArrayCounter [rank];
-                               lengths = new TemporaryVariable [rank];
-                               length_exprs = new Expression [rank];
-
+                               int rank = length_exprs.Length;
                                ArrayList list = new ArrayList (rank);
                                for (int i = 0; i < rank; i++) {
                                        counter [i] = new ArrayCounter (loc);
-                                       counter [i].Resolve (ec);
-
-                                       lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc);
-                                       lengths [i].Resolve (ec);
+                                       counter [i].ResolveIncrement (ec);                                      
 
                                        if (rank == 1) {
                                                length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec);
                                        } else {
+                                               lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc);
+                                               lengths [i].Resolve (ec);
+
                                                ArrayList args = new ArrayList (1);
                                                args.Add (new Argument (new IntConstant (i, loc)));
                                                length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec);
@@ -5138,6 +5173,7 @@ namespace Mono.CSharp {
                                if (access == null)
                                        return false;
 
+                               Expression var_type = for_each.type;
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
                                        // Infer implicitly typed local variable from foreach array type
@@ -5157,8 +5193,8 @@ namespace Mono.CSharp {
                                ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc);
                                ec.CurrentBranching.CreateSibling ();
 
-                               variable = variable.ResolveLValue (ec, conv, loc);
-                               if (variable == null)
+                               for_each.variable = for_each.variable.ResolveLValue (ec, conv, loc);
+                               if (for_each.variable == null)
                                        ok = false;
 
                                ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc);
@@ -5178,8 +5214,9 @@ namespace Mono.CSharp {
                        {
                                ILGenerator ig = ec.ig;
 
-                               copy.Store (ec, expr);
+                               copy.EmitAssign (ec, for_each.expr);
 
+                               int rank = length_exprs.Length;
                                Label[] test = new Label [rank];
                                Label[] loop = new Label [rank];
 
@@ -5187,37 +5224,115 @@ namespace Mono.CSharp {
                                        test [i] = ig.DefineLabel ();
                                        loop [i] = ig.DefineLabel ();
 
-                                       lengths [i].Store (ec, length_exprs [i]);
+                                       if (lengths != null)
+                                               lengths [i].EmitAssign (ec, length_exprs [i]);
                                }
 
+                               IntConstant zero = new IntConstant (0, loc);
                                for (int i = 0; i < rank; i++) {
-                                       counter [i].Initialize (ec);
+                                       counter [i].EmitAssign (ec, zero);
 
                                        ig.Emit (OpCodes.Br, test [i]);
                                        ig.MarkLabel (loop [i]);
                                }
 
-                               ((IAssignMethod) variable).EmitAssign (ec, conv, false, false);
+                               ((IAssignMethod) for_each.variable).EmitAssign (ec, conv, false, false);
 
                                statement.Emit (ec);
 
                                ig.MarkLabel (ec.LoopBegin);
 
                                for (int i = rank - 1; i >= 0; i--){
-                                       counter [i].Increment (ec);
+                                       counter [i].EmitIncrement (ec);
 
                                        ig.MarkLabel (test [i]);
                                        counter [i].Emit (ec);
-                                       lengths [i].Emit (ec);
+
+                                       if (lengths != null)
+                                               lengths [i].Emit (ec);
+                                       else
+                                               length_exprs [i].Emit (ec);
+
                                        ig.Emit (OpCodes.Blt, loop [i]);
                                }
 
                                ig.MarkLabel (ec.LoopEnd);
                        }
+
+                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                       {
+                               for_each.expr.MutateHoistedGenericType (storey);
+
+                               copy.MutateHoistedGenericType (storey);
+                               conv.MutateHoistedGenericType (storey);
+                               statement.MutateHoistedGenericType (storey);
+
+                               for (int i = 0; i < counter.Length; i++) {
+                                       counter [i].MutateHoistedGenericType (storey);
+                                       if (lengths != null)
+                                               lengths [i].MutateHoistedGenericType (storey);
+                               }
+                       }
                }
 
-               protected class CollectionForeach : Statement
+               sealed class CollectionForeach : Statement
                {
+                       class CollectionForeachStatement : Statement
+                       {
+                               Type type;
+                               Expression variable, current, conv;
+                               Statement statement;
+                               Assign assign;
+
+                               public CollectionForeachStatement (Type type, Expression variable,
+                                                                  Expression current, Statement statement,
+                                                                  Location loc)
+                               {
+                                       this.type = type;
+                                       this.variable = variable;
+                                       this.current = current;
+                                       this.statement = statement;
+                                       this.loc = loc;
+                               }
+
+                               protected override void CloneTo (CloneContext clonectx, Statement target)
+                               {
+                                       throw new NotImplementedException ();
+                               }
+
+                               public override bool Resolve (EmitContext ec)
+                               {
+                                       current = current.Resolve (ec);
+                                       if (current == null)
+                                               return false;
+
+                                       conv = Convert.ExplicitConversion (ec, current, type, loc);
+                                       if (conv == null)
+                                               return false;
+
+                                       assign = new SimpleAssign (variable, conv, loc);
+                                       if (assign.Resolve (ec) == null)
+                                               return false;
+
+                                       if (!statement.Resolve (ec))
+                                               return false;
+
+                                       return true;
+                               }
+
+                               protected override void DoEmit (EmitContext ec)
+                               {
+                                       assign.EmitStatement (ec);
+                                       statement.Emit (ec);
+                               }
+
+                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                               {
+                                       assign.MutateHoistedGenericType (storey);
+                                       statement.MutateHoistedGenericType (storey);
+                               }
+                       }
+
                        Expression variable, expr;
                        Statement statement;
 
@@ -5243,27 +5358,22 @@ namespace Mono.CSharp {
                                loc = l;
                        }
 
+                       protected override void CloneTo (CloneContext clonectx, Statement target)
+                       {
+                               throw new NotImplementedException ();
+                       }
+
                        bool GetEnumeratorFilter (EmitContext ec, MethodInfo mi)
                        {
                                Type return_type = mi.ReturnType;
 
-                               if ((return_type == TypeManager.ienumerator_type) && (mi.DeclaringType == TypeManager.string_type))
-                                       //
-                                       // Apply the same optimization as MS: skip the GetEnumerator
-                                       // returning an IEnumerator, and use the one returning a 
-                                       // CharEnumerator instead. This allows us to avoid the 
-                                       // try-finally block and the boxing.
-                                       //
-                                       return false;
-
                                //
                                // Ok, we can access it, now make sure that we can do something
                                // with this `GetEnumerator'
                                //
 
                                if (return_type == TypeManager.ienumerator_type ||
-                                   TypeManager.ienumerator_type.IsAssignableFrom (return_type) ||
-                                   (!RootContext.StdLib && TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type))) {
+                                       TypeManager.ImplementsInterface (return_type, TypeManager.ienumerator_type)) {
                                        //
                                        // If it is not an interface, lets try to find the methods ourselves.
                                        // For example, if we have:
@@ -5288,11 +5398,10 @@ namespace Mono.CSharp {
                                                        TypeManager.ienumerator_type, "Current", loc, TypeManager.object_type);
                                        }
 
-#if GMCS_SOURCE
                                        //
                                        // Prefer a generic enumerator over a non-generic one.
                                        //
-                                       if (return_type.IsInterface && return_type.IsGenericType) {
+                                       if (return_type.IsInterface && TypeManager.IsGenericType (return_type)) {
                                                enumerator_type = return_type;
                                                if (!FetchGetCurrent (ec, return_type))
                                                        get_current = new PropertyExpr (
@@ -5301,7 +5410,6 @@ namespace Mono.CSharp {
                                                        move_next = TypeManager.bool_movenext_void;
                                                return true;
                                        }
-#endif
 
                                        if (return_type.IsInterface ||
                                            !FetchMoveNext (return_type) ||
@@ -5335,14 +5443,10 @@ namespace Mono.CSharp {
                        //
                        bool FetchMoveNext (Type t)
                        {
-                               MemberList move_next_list;
-
-                               move_next_list = TypeContainer.FindMembers (
-                                       t, MemberTypes.Method,
+                               MemberInfo[] move_next_list = TypeManager.MemberLookup (null, null, t,
+                                       MemberTypes.Method,
                                        BindingFlags.Public | BindingFlags.Instance,
-                                       Type.FilterName, "MoveNext");
-                               if (move_next_list.Count == 0)
-                                       return false;
+                                       "MoveNext", null);
 
                                foreach (MemberInfo m in move_next_list){
                                        MethodInfo mi = (MethodInfo) m;
@@ -5372,32 +5476,7 @@ namespace Mono.CSharp {
                                return true;
                        }
 
-                       // 
-                       // Retrieves a `public void Dispose ()' method from the Type `t'
-                       //
-                       static MethodInfo FetchMethodDispose (Type t)
-                       {
-                               MemberList dispose_list;
-
-                               dispose_list = TypeContainer.FindMembers (
-                                       t, MemberTypes.Method,
-                                       BindingFlags.Public | BindingFlags.Instance,
-                                       Type.FilterName, "Dispose");
-                               if (dispose_list.Count == 0)
-                                       return null;
-
-                               foreach (MemberInfo m in dispose_list){
-                                       MethodInfo mi = (MethodInfo) m;
-
-                                       if (TypeManager.GetParameterData (mi).Count == 0){
-                                               if (mi.ReturnType == TypeManager.void_type)
-                                                       return mi;
-                                       }
-                               }
-                               return null;
-                       }
-
-                       public void Error_Enumerator ()
+                       void Error_Enumerator ()
                        {
                                if (enumerator_found) {
                                        return;
@@ -5539,9 +5618,6 @@ namespace Mono.CSharp {
                                        return false;
                                }
 
-                               bool is_disposable = !enumerator_type.IsSealed ||
-                                       TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type);
-
                                VarExpr ve = var_type as VarExpr;
                                if (ve != null) {
                                        // Infer implicitly typed local variable from foreach enumerable type
@@ -5576,9 +5652,14 @@ namespace Mono.CSharp {
 
                                loop = new While (move_next_expr, block, loc);
 
-                               wrapper = is_disposable ?
-                                       (Statement) new DisposableWrapper (this) :
-                                       (Statement) new NonDisposableWrapper (this);
+
+                               bool implements_idisposable = TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type);
+                               if (implements_idisposable || !enumerator_type.IsSealed) {
+                                       wrapper = new DisposableWrapper (this, implements_idisposable);
+                               } else {
+                                       wrapper = new NonDisposableWrapper (this);
+                               }
+
                                return wrapper.Resolve (ec);
                        }
 
@@ -5595,6 +5676,11 @@ namespace Mono.CSharp {
                                        this.parent = parent;
                                }
 
+                               protected override void CloneTo (CloneContext clonectx, Statement target)
+                               {
+                                       throw new NotSupportedException ();
+                               }
+
                                public override bool Resolve (EmitContext ec)
                                {
                                        return parent.ResolveLoop (ec);
@@ -5605,14 +5691,27 @@ namespace Mono.CSharp {
                                        parent.EmitLoopInit (ec);
                                        parent.EmitLoopBody (ec);
                                }
+
+                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                               {
+                                       throw new NotSupportedException ();
+                               }
                        }
 
-                       class DisposableWrapper : ExceptionStatement {
+                       sealed class DisposableWrapper : ExceptionStatement
+                       {
                                CollectionForeach parent;
+                               bool implements_idisposable;
 
-                               internal DisposableWrapper (CollectionForeach parent)
+                               internal DisposableWrapper (CollectionForeach parent, bool implements)
                                {
                                        this.parent = parent;
+                                       this.implements_idisposable = implements;
+                               }
+
+                               protected override void CloneTo (CloneContext clonectx, Statement target)
+                               {
+                                       throw new NotSupportedException ();
                                }
 
                                public override bool Resolve (EmitContext ec)
@@ -5647,7 +5746,35 @@ namespace Mono.CSharp {
 
                                protected override void EmitFinallyBody (EmitContext ec)
                                {
-                                       parent.EmitFinallyBody (ec);
+                                       Expression instance = parent.enumerator;
+                                       if (!TypeManager.IsValueType (parent.enumerator_type)) {
+                                               ILGenerator ig = ec.ig;
+
+                                               parent.enumerator.Emit (ec);
+
+                                               Label call_dispose = ig.DefineLabel ();
+
+                                               if (!implements_idisposable) {
+                                                       ec.ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
+                                                       LocalTemporary temp = new LocalTemporary (TypeManager.idisposable_type);
+                                                       temp.Store (ec);
+                                                       temp.Emit (ec);
+                                                       instance = temp;
+                                               }
+                                               
+                                               ig.Emit (OpCodes.Brtrue_S, call_dispose);
+
+                                               // using 'endfinally' to empty the evaluation stack
+                                               ig.Emit (OpCodes.Endfinally);
+                                               ig.MarkLabel (call_dispose);
+                                       }
+
+                                       Invocation.EmitCall (ec, false, instance, TypeManager.void_dispose_void, new ArrayList (0), loc);
+                               }
+
+                               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+                               {
+                                       throw new NotSupportedException ();
                                }
                        }
 
@@ -5658,7 +5785,7 @@ namespace Mono.CSharp {
 
                        void EmitLoopInit (EmitContext ec)
                        {
-                               enumerator.Store (ec, init);
+                               enumerator.EmitAssign (ec, init);
                        }
 
                        void EmitLoopBody (EmitContext ec)
@@ -5666,81 +5793,73 @@ namespace Mono.CSharp {
                                loop.Emit (ec);
                        }
 
-                       void EmitFinallyBody (EmitContext ec)
+                       public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
                        {
-                               ILGenerator ig = ec.ig;
-
-                               if (enumerator_type.IsValueType) {
-                                       MethodInfo mi = FetchMethodDispose (enumerator_type);
-                                       if (mi != null) {
-                                               enumerator.EmitLoadAddress (ec);
-                                               ig.Emit (OpCodes.Call, mi);
-                                       } else {
-                                               enumerator.Emit (ec);
-                                               ig.Emit (OpCodes.Box, enumerator_type);
-                                               ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                                       }
-                               } else {
-                                       Label call_dispose = ig.DefineLabel ();
+                               enumerator_type = storey.MutateType (enumerator_type);
+                               init.MutateHoistedGenericType (storey);
+                               loop.MutateHoistedGenericType (storey);
+                       }
+               }
 
-                                       enumerator.Emit (ec);
-                                       ig.Emit (OpCodes.Isinst, TypeManager.idisposable_type);
-                                       ig.Emit (OpCodes.Dup);
-                                       ig.Emit (OpCodes.Brtrue_S, call_dispose);
+               Expression type;
+               Expression variable;
+               Expression expr;
+               Statement statement;
 
-                                       // 'endfinally' empties the evaluation stack, and can appear anywhere inside a finally block
-                                       // (Partition III, Section 3.35)
-                                       ig.Emit (OpCodes.Endfinally);
+               public Foreach (Expression type, LocalVariableReference var, Expression expr,
+                               Statement stmt, Location l)
+               {
+                       this.type = type;
+                       this.variable = var;
+                       this.expr = expr;
+                       statement = stmt;
+                       loc = l;
+               }
 
-                                       ig.MarkLabel (call_dispose);
-                                       ig.Emit (OpCodes.Callvirt, TypeManager.void_dispose_void);
-                               }
-                       }
+               public Statement Statement {
+                       get { return statement; }
                }
 
-               protected class CollectionForeachStatement : Statement
+               public override bool Resolve (EmitContext ec)
                {
-                       Type type;
-                       Expression variable, current, conv;
-                       Statement statement;
-                       Assign assign;
+                       expr = expr.Resolve (ec);
+                       if (expr == null)
+                               return false;
 
-                       public CollectionForeachStatement (Type type, Expression variable,
-                                                          Expression current, Statement statement,
-                                                          Location loc)
-                       {
-                               this.type = type;
-                               this.variable = variable;
-                               this.current = current;
-                               this.statement = statement;
-                               this.loc = loc;
+                       if (expr.IsNull) {
+                               Report.Error (186, loc, "Use of null is not valid in this context");
+                               return false;
                        }
 
-                       public override bool Resolve (EmitContext ec)
-                       {
-                               current = current.Resolve (ec);
-                               if (current == null)
+                       if (expr.Type == TypeManager.string_type) {
+                               statement = new ArrayForeach (this, 1);
+                       } else if (expr.Type.IsArray) {
+                               statement = new ArrayForeach (this, expr.Type.GetArrayRank ());
+                       } else {
+                               if (expr.eclass == ExprClass.MethodGroup || expr is AnonymousMethodExpression) {
+                                       Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
+                                               expr.ExprClassName);
                                        return false;
+                               }
 
-                               conv = Convert.ExplicitConversion (ec, current, type, loc);
-                               if (conv == null)
-                                       return false;
+                               statement = new CollectionForeach (type, variable, expr, statement, loc);
+                       }
 
-                               assign = new SimpleAssign (variable, conv, loc);
-                               if (assign.Resolve (ec) == null)
-                                       return false;
+                       return statement.Resolve (ec);
+               }
 
-                               if (!statement.Resolve (ec))
-                                       return false;
+               protected override void DoEmit (EmitContext ec)
+               {
+                       ILGenerator ig = ec.ig;
 
-                               return true;
-                       }
+                       Label old_begin = ec.LoopBegin, old_end = ec.LoopEnd;
+                       ec.LoopBegin = ig.DefineLabel ();
+                       ec.LoopEnd = ig.DefineLabel ();
 
-                       protected override void DoEmit (EmitContext ec)
-                       {
-                               assign.EmitStatement (ec);
-                               statement.Emit (ec);
-                       }
+                       statement.Emit (ec);
+
+                       ec.LoopBegin = old_begin;
+                       ec.LoopEnd = old_end;
                }
 
                protected override void CloneTo (CloneContext clonectx, Statement t)
@@ -5752,5 +5871,10 @@ namespace Mono.CSharp {
                        target.expr = expr.Clone (clonectx);
                        target.statement = statement.Clone (clonectx);
                }
+
+               public override void MutateHoistedGenericType (AnonymousMethodStorey storey)
+               {
+                       statement.MutateHoistedGenericType (storey);
+               }
        }
 }