Patch #33.
authorMartin Baulig <martin@novell.com>
Mon, 14 Aug 2006 13:22:31 +0000 (13:22 -0000)
committerMartin Baulig <martin@novell.com>
Mon, 14 Aug 2006 13:22:31 +0000 (13:22 -0000)
svn path=/trunk/mcs/; revision=63718

mcs/gmcs/anonymous-methods.diff

index 8e488521bd8407b9809a74471a4d60db69f3ff51..8642d1d2f0ee8143b0d52d032165e78f77550f2b 100644 (file)
@@ -57,7 +57,125 @@ Index: parameter.cs
 ===================================================================
 --- parameter.cs       (revision 63019)
 +++ parameter.cs       (working copy)
-@@ -665,7 +665,7 @@
+@@ -212,6 +212,11 @@
+               protected Type parameter_type;
+               public readonly Location Location;
++              Variable var;
++              public Variable Variable {
++                      get { return var; }
++              }
++
+               IResolveContext resolve_context;
+               
+               public Parameter (Expression type, string name, Modifier mod, Attributes attrs, Location loc)
+@@ -335,6 +340,15 @@
+                       return true;
+               }
++              public void ResolveVariable (EmitContext ec, int idx)
++              {
++                      Report.Debug (64, "PARAMETER RESOLVE VARIABLE", ParameterType, Name, Location);
++                      var = ec.GetCapturedParameter (this);
++                      Report.Debug (64, "PARAMETER RESOLVE VARIABLE #1", var);
++                      if (var == null)
++                              var = new ParameterVariable (this, idx);
++              }
++
+               public Type ExternalType ()
+               {
+                       if ((ModFlags & Parameter.Modifier.ISBYREF) != 0)
+@@ -452,6 +466,74 @@
+                               return attribute_targets;
+                       }
+               }
++
++              protected class ParameterVariable : Variable
++              {
++                      public readonly Parameter Parameter;
++                      public readonly int Idx;
++                      public readonly bool IsRef;
++
++                      public ParameterVariable (Parameter par, int idx)
++                      {
++                              this.Parameter = par;
++                              this.Idx = idx;
++                              this.IsRef = (par.ModFlags & Parameter.Modifier.ISBYREF) != 0;
++                      }
++
++                      public override Type Type {
++                              get { return Parameter.ParameterType; }
++                      }
++
++                      public override bool NeedsTemporary {
++                              get { return false; }
++                      }
++
++                      public override void EmitInstance (EmitContext ec)
++                      {
++                      }
++
++                      public override void Emit (EmitContext ec)
++                      {
++                              int arg_idx = Idx;
++                              if (!ec.MethodIsStatic)
++                                      arg_idx++;
++
++                              ParameterReference.EmitLdArg (ec.ig, arg_idx);
++                      }
++
++                      public override void EmitAssign (EmitContext ec)
++                      {
++                              int arg_idx = Idx;
++                              if (!ec.MethodIsStatic)
++                                      arg_idx++;
++
++                              if (arg_idx <= 255)
++                                      ec.ig.Emit (OpCodes.Starg_S, (byte) arg_idx);
++                              else
++                                      ec.ig.Emit (OpCodes.Starg, arg_idx);
++                      }
++
++                      public override void EmitAddressOf (EmitContext ec)
++                      {
++                              int arg_idx = Idx;
++
++                              if (!ec.MethodIsStatic)
++                                      arg_idx++;
++
++                              if (IsRef) {
++                                      if (arg_idx <= 255)
++                                              ec.ig.Emit (OpCodes.Ldarg_S, (byte) arg_idx);
++                                      else
++                                              ec.ig.Emit (OpCodes.Ldarg, arg_idx);
++                              } else {
++                                      if (arg_idx <= 255)
++                                              ec.ig.Emit (OpCodes.Ldarga_S, (byte) arg_idx);
++                                      else
++                                              ec.ig.Emit (OpCodes.Ldarga, arg_idx);
++                              }
++                      }
++              }
++
+       }
+       /// <summary>
+@@ -607,6 +689,14 @@
+                       return ok;
+               }
++              public void ResolveVariable (EmitContext ec)
++              {
++                      for (int i = 0; i < FixedParameters.Length; ++i) {
++                              Parameter p = FixedParameters [i];
++                              p.ResolveVariable (ec, i);
++                      }
++              }
++
+               public CallingConventions CallingConvention
+               {
+                       get {
+@@ -665,7 +755,7 @@
                        }
                }
  
@@ -2165,7 +2283,7 @@ Index: anonymous.cs
        }
  
        //
-@@ -573,52 +888,112 @@
+@@ -573,52 +888,91 @@
                
                public override void Emit (EmitContext ec)
                {
@@ -2208,7 +2326,8 @@ Index: anonymous.cs
 -                              this.am = am;
 -                              eclass = ExprClass.Value;
 -                      }
-+      class CapturedParameter {
++      class CapturedParameter : Variable {
++              public readonly ScopeInfo Scope;
 +              public readonly Parameter Parameter;
 +              public readonly Field Field;
 +              public readonly int Idx;
@@ -2222,91 +2341,70 @@ Index: anonymous.cs
 -                      {
 -                              am.aec.EmitMethodHostInstance (ec, am);
 -                      }
++              public FieldExpr FieldInstance;
++
 +              public CapturedParameter (ScopeInfo scope, Parameter par, int idx)
 +              {
++                      this.Scope = scope;
 +                      this.Parameter = par;
-+                      Idx = idx;
++                      this.Idx = idx;
 +                      Field = scope.HelperClass.CaptureVariable (
 +                              "<p:" + par.Name + ">", par.ParameterType);
                }
-       }
+-      }
  
 -      class CapturedParameter {
 -              public Type Type;
 -              public FieldBuilder FieldBuilder;
 -              public int Idx;
-+      public class CapturedParameterReference : Expression, IAssignMethod, IMemoryLocation, IVariable
-+      {
-+              ScopeInfo scope;
-+              CapturedParameter cp;
-+              VariableInfo vi;
-+              bool prepared;
++              public override Type Type {
++                      get { return Field.MemberType; }
++              }
  
 -              public CapturedParameter (Type type, int idx)
-+              internal CapturedParameterReference (ScopeInfo scope, CapturedParameter cp,
-+                                                   Location loc)
++              public override bool NeedsTemporary {
++                      get { return true; }
++              }
++
++              public override void EmitInstance (EmitContext ec)
                {
 -                      Type = type;
 -                      Idx = idx;
-+                      this.scope = scope;
-+                      this.cp = cp;
-+                      this.loc = loc;
-+
-+                      type = cp.Field.MemberType;
-+                      eclass = ExprClass.Variable;
++                      ec.capture_context.EmitParameterInstance (ec, Parameter);
                }
 +
-+              public VariableInfo VariableInfo {
-+                      get { return vi; }
-+              }
-+
-+              public override Expression DoResolve (EmitContext ec)
-+              {
-+                      // We are born fully resolved.
-+                      return this;
-+              }
-+
-+              public override Expression DoResolveLValue (EmitContext ec, Expression right_side)
-+              {
-+                      // We are born fully resolved.
-+                      return this;
-+              }
-+
-+              LocalTemporary temp;
-+
 +              public override void Emit (EmitContext ec)
 +              {
-+                      Emit (ec, false);
++                      if (ec.capture_context == Scope.CaptureContext)
++                              ec.ig.Emit (OpCodes.Ldfld, FieldInstance.FieldInfo);
++                      else
++                              ec.ig.Emit (OpCodes.Ldfld, Field.FieldBuilder);
 +              }
 +
-+              public void Emit (EmitContext ec, bool leave_copy)
++              public override void EmitAssign (EmitContext ec)
 +              {
-+                      scope.CaptureContext.EmitParameter (
-+                              ec, cp.Parameter.Name, leave_copy, prepared, ref temp);
-+              }
-+
-+              public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
-+                                      bool prepare_for_load)
-+              {
-+                      prepared = prepare_for_load;
-+                      scope.CaptureContext.EmitAssignParameter (
-+                              ec, cp.Parameter.Name, source, leave_copy, prepare_for_load, ref temp);
++                      if (ec.capture_context == Scope.CaptureContext)
++                              ec.ig.Emit (OpCodes.Stfld, FieldInstance.FieldInfo);
++                      else
++                              ec.ig.Emit (OpCodes.Stfld, Field.FieldBuilder);
 +              }
 +
-+              public void AddressOf (EmitContext ec, AddressOp mode)
++              public override void EmitAddressOf (EmitContext ec)
 +              {
-+                      scope.CaptureContext.EmitAddressOfParameter (ec, cp.Parameter.Name);
++                      if (ec.capture_context == Scope.CaptureContext)
++                              ec.ig.Emit (OpCodes.Ldflda, FieldInstance.FieldInfo);
++                      else
++                              ec.ig.Emit (OpCodes.Ldflda, Field.FieldBuilder);
 +              }
 +
-+              public bool VerifyFixed ()
++              public override string ToString ()
 +              {
-+                      // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
-+                      return cp.Parameter.ModFlags == Parameter.Modifier.NONE;
++                      return String.Format ("{0} ({1})", GetType (), Field);
 +              }
        }
  
        //
-@@ -629,13 +1004,11 @@
+@@ -629,13 +983,11 @@
                public CaptureContext CaptureContext;
                public ScopeInfo ParentScope;
                public Block ScopeBlock;
@@ -2320,7 +2418,7 @@ Index: anonymous.cs
                
                ArrayList locals = new ArrayList ();
                ArrayList children = new ArrayList ();
-@@ -643,40 +1016,39 @@
+@@ -643,40 +995,39 @@
                //
                // The types and fields generated
                //
@@ -2379,7 +2477,7 @@ Index: anonymous.cs
                internal void AddChild (ScopeInfo si)
                {
                        if (children.Contains (si))
-@@ -719,8 +1091,6 @@
+@@ -719,8 +1070,6 @@
                        Pad ();
                        Console.WriteLine ("START");
                        indent++;
@@ -2388,7 +2486,7 @@ Index: anonymous.cs
                        foreach (LocalInfo li in locals){
                                Pad ();
                                Console.WriteLine ("var {0}", MakeFieldName (li.Name));
-@@ -733,147 +1103,81 @@
+@@ -733,147 +1082,81 @@
                        Console.WriteLine ("END");
                }
  
@@ -2583,7 +2681,7 @@ Index: anonymous.cs
                                        //
                                        // This is needed if someone overwrites the Emit method
                                        // of Statement and manually calls Block.Emit without
-@@ -882,16 +1186,9 @@
+@@ -882,16 +1165,9 @@
                                        //   ec.EmitScopeInitFromBlock (The_Block);
                                        //   The_Block.Emit (ec);
                                        // 
@@ -2602,7 +2700,7 @@ Index: anonymous.cs
                        }
                }
  
-@@ -935,6 +1232,303 @@
+@@ -935,6 +1211,268 @@
  
                        return sb.ToString ();
                }
@@ -2632,7 +2730,8 @@ Index: anonymous.cs
 +
 +                      public override void EmitInstance (EmitContext ec)
 +                      {
-+                              ec.EmitCapturedVariableInstance (Local);
++                              ec.capture_context.EmitCapturedVariableInstance (
++                                      ec, Local.Block, ec.CurrentAnonymousMethod);
 +                      }
 +
 +                      public override void Emit (EmitContext ec)
@@ -2660,46 +2759,6 @@ Index: anonymous.cs
 +                      }
 +              }
 +
-+#if FIXME
-+              protected class CapturedLocalInstance : Variable
-+              {
-+                      public readonly LocalInfo LocalInfo;
-+
-+                      public CapturedLocalInstance (LocalInfo local)
-+                      {
-+                              this.LocalInfo = local;
-+                      }
-+
-+                      public override Type Type {
-+                              get { return LocalInfo.TheField.Type; }
-+                      }
-+
-+                      public override bool NeedsTemporary {
-+                              get { return true; }
-+                      }
-+
-+                      public override void EmitInstance (EmitContext ec)
-+                      {
-+                              ec.EmitCapturedVariableInstance (LocalInfo);
-+                      }
-+
-+                      public override void Emit (EmitContext ec)
-+                      {
-+                              ec.ig.Emit (OpCodes.Ldfld, LocalInfo.TheField.FieldInfo);
-+                      }
-+
-+                      public override void EmitAssign (EmitContext ec)
-+                      {
-+                              ec.ig.Emit (OpCodes.Stfld, LocalInfo.TheField.FieldInfo);
-+                      }
-+
-+                      public override void EmitAddressOf (EmitContext ec)
-+                      {
-+                              ec.ig.Emit (OpCodes.Ldflda, LocalInfo.TheField.FieldInfo);
-+                      }
-+              }
-+#endif
-+
 +              protected sealed class ScopeInitializer : ExpressionStatement
 +              {
 +                      ScopeInfo scope;
@@ -2803,6 +2862,9 @@ Index: anonymous.cs
 +                                                      throw new InternalErrorException ();
 +
 +                                              captured_params.Add (cp.Idx + extra, fe);
++
++                                              fe.InstanceExpression = this;
++                                              cp.FieldInstance = fe;
 +                                      }
 +                              }
 +
@@ -2828,6 +2890,7 @@ Index: anonymous.cs
 +                                              ec.ig.Emit (OpCodes.Neg);
 +                                              ec.ig.Emit (OpCodes.Not);
 +                                              ec.ig.Emit (OpCodes.Neg);
++                                              throw;
 +                                      }
 +                              }
 +                      }
@@ -2906,7 +2969,7 @@ Index: anonymous.cs
        }
  
        //
-@@ -965,7 +1559,6 @@
+@@ -965,25 +1503,24 @@
                ArrayList roots = new ArrayList ();
                
                bool have_captured_vars = false;
@@ -2914,12 +2977,13 @@ Index: anonymous.cs
  
                //
                // Captured fields
-@@ -973,17 +1566,17 @@
+               //
                Hashtable captured_fields = new Hashtable ();
                Hashtable captured_variables = new Hashtable ();
-               public Hashtable captured_parameters = new Hashtable ();
+-              public Hashtable captured_parameters = new Hashtable ();
 -              public AnonymousContainer Host;
 -              
++              internal Hashtable captured_parameters = new Hashtable ();
 +              public IAnonymousContainer Host;
 +
                public CaptureContext (ToplevelBlock toplevel_owner, Location loc,
@@ -2937,7 +3001,7 @@ Index: anonymous.cs
                }
  
                void DoPath (StringBuilder sb, CaptureContext cc)
-@@ -1005,7 +1598,7 @@
+@@ -1005,7 +1542,7 @@
                                cc.Host = new_host;
                        }
                }
@@ -2946,7 +3010,7 @@ Index: anonymous.cs
                public override string ToString ()
                {
                        StringBuilder sb = new StringBuilder ();
-@@ -1029,41 +1622,67 @@
+@@ -1029,91 +1566,122 @@
                        }
                }
  
@@ -3028,27 +3092,55 @@ Index: anonymous.cs
                }
  
                //
-@@ -1093,27 +1712,32 @@
+               // Retursn the CaptureContext for the block that defines the parameter `name'
+               //
+-              static CaptureContext _ContextForParameter (ToplevelBlock current, string name)
++              static CaptureContext _ContextForParameter (ToplevelBlock current, Parameter par)
+               {
+                       ToplevelBlock container = current.Container;
+                       if (container != null){
+-                              CaptureContext cc = _ContextForParameter (container, name);
++                              CaptureContext cc = _ContextForParameter (container, par);
+                               if (cc != null)
+                                       return cc;
+                       }
+-                      if (current.IsParameterReference (name))
++                      if (current.IsParameterReference (par.Name))
+                               return current.ToplevelBlockCaptureContext;
+                       return null;
+               }
+-              static CaptureContext ContextForParameter (ToplevelBlock current, string name)
++              static CaptureContext ContextForParameter (ToplevelBlock current, Parameter par)
+               {
+-                      CaptureContext cc = _ContextForParameter (current, name);
++                      CaptureContext cc = _ContextForParameter (current, par);
+                       if (cc == null)
+-                              throw new Exception (String.Format ("request for parameteter {0} failed: not found", name));
++                              throw new InternalErrorException (
++                                      "Request for parameteter {0} failed: not found", par.Name);
+                       return cc;
+               }
+               
                //
                // Records the captured parameter at the appropriate CaptureContext
                //
 -              public void AddParameter (EmitContext ec, AnonymousContainer am,
 -                                        string name, Type t, int idx)
-+              public Expression AddParameter (EmitContext ec, Parameter par, int idx, Location loc)
++              public Variable AddParameter (EmitContext ec, Parameter par, int idx)
                {
 -                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
 -
 -                      cc.AddParameterToContext (am, name, t, idx);
-+                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par.Name);
-+                      return cc.AddParameterToContext (ec.CurrentAnonymousMethod, par, idx, loc);
++                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par);
++                      return cc.AddParameterToContext (ec.CurrentAnonymousMethod, par, idx);
                }
  
                //
                // Records the parameters in the context
                //
 -              public void AddParameterToContext (AnonymousContainer am, string name, Type t, int idx)
-+              public Expression AddParameterToContext (AnonymousContainer am, Parameter par,
-+                                                       int idx, Location loc)
++              public Variable AddParameterToContext (AnonymousContainer am, Parameter par, int idx)
                {
                        if (captured_parameters == null)
                                captured_parameters = new Hashtable ();
@@ -3059,17 +3151,17 @@ Index: anonymous.cs
                        scope.HostsParameters = true;
                        am.RegisterScope (scope);
 +
-+                      CapturedParameter cp = (CapturedParameter) captured_parameters [par.Name];
++                      CapturedParameter cp = (CapturedParameter) captured_parameters [par];
 +                      if (cp == null) {
 +                              cp = new CapturedParameter (scope, par, idx);
-+                              captured_parameters.Add (par.Name, cp);
++                              captured_parameters.Add (par, cp);
 +                      }
 +
-+                      return new CapturedParameterReference (scope, cp, loc);
++                      return cp;
                }
  
                //
-@@ -1137,16 +1761,15 @@
+@@ -1137,16 +1705,15 @@
                public void CaptureThis (AnonymousContainer am)
                {
                        if (am == null)
@@ -3089,7 +3181,7 @@ Index: anonymous.cs
                }
  
                public bool HaveCapturedVariables {
-@@ -1164,13 +1787,9 @@
+@@ -1164,21 +1731,23 @@
                        }
                }
  
@@ -3104,8 +3196,23 @@ Index: anonymous.cs
 +                      return (Variable) captured_variables [local];
                }
  
++              public Variable GetCapturedParameter (Parameter par)
++              {
++                      return (Variable) captured_parameters [par];
++              }
++
                //
-@@ -1188,45 +1807,23 @@
+               // Returns whether the parameter is captured
+               //
+               public bool IsParameterCaptured (string name)
+               {
+-                      if (ParentCaptureContext != null && ParentCaptureContext.IsParameterCaptured (name))
++                      if ((ParentCaptureContext != null) &&
++                          ParentCaptureContext.IsParameterCaptured (name))
+                               return true;
+                       
+                       if (captured_parameters != null)
+@@ -1188,86 +1757,65 @@
  
                public void EmitAnonymousHelperClasses (EmitContext ec)
                {
@@ -3160,50 +3267,91 @@ Index: anonymous.cs
                }
                
                //
-@@ -1239,12 +1836,18 @@
+               // Emits the opcodes necessary to load the instance of the captured
+               // variable in `li'
+               //
+-              public void EmitCapturedVariableInstance (EmitContext ec, LocalInfo li,
++              public void EmitCapturedVariableInstance (EmitContext ec, Block block,
+                                                         AnonymousContainer am)
+               {
                        ILGenerator ig = ec.ig;
                        ScopeInfo si;
  
-+                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE", this, li.Name,
-+                                    am, li.Block.Toplevel, toplevel_owner);
-+
-                       if (li.Block.Toplevel == toplevel_owner){
-                               si = (ScopeInfo) scopes [li.Block.ID];
+-                      if (li.Block.Toplevel == toplevel_owner){
+-                              si = (ScopeInfo) scopes [li.Block.ID];
 -                              si.EmitScopeInstance (ig);
++                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE", this,
++                                    am, block, block.Toplevel, toplevel_owner);
++
++                      if (block.Toplevel == toplevel_owner){
++                              si = (ScopeInfo) scopes [block.ID];
 +                              si.EmitScopeInstance (ec);
                                return;
                        }
  
-+                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #1", this, li.Name,
-+                                    am, am.IsIterator, li.Block.Toplevel, toplevel_owner, am.Scope);
++                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #1", this,
++                                    am, am.IsIterator, block.Toplevel, toplevel_owner, am.Scope);
 +
                        si = am.Scope;
                        ig.Emit (OpCodes.Ldarg_0);
                        if (si != null){
-@@ -1252,15 +1855,19 @@
+-                              if (am.IsIterator && (si.ScopeBlock.Toplevel == li.Block.Toplevel)) {
++                              if (am.IsIterator && (si.ScopeBlock.Toplevel == block.Toplevel)) {
                                        return;
                                }
  
-+                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #2", this, li.Name,
-+                                    si, si.ParentLink, si.ScopeBlock, li.Block);
+-                              while (si.ScopeBlock.ID != li.Block.ID){
++                      Report.Debug (64, "EMIT CAPTURED VARIABLE INSTANCE #2", this,
++                                    si, si.ParentLink, si.ScopeBlock, block);
 +
-                               while (si.ScopeBlock.ID != li.Block.ID){
++                              while (si.ScopeBlock.ID != block.ID){
                                        if (si.ParentLink != null)
 -                                              ig.Emit (OpCodes.Ldfld, si.ParentLink);
 +                                              ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
                                        si = si.ParentScope;
-                                       if (si == null) {
-                                               si = am.Scope;
+-                                      if (si == null) {
+-                                              si = am.Scope;
 -                                              Console.WriteLine ("Target: {0} {1}", li.Block.ID, li.Name);
-+                                              Console.WriteLine ("Target: {0} {1}", li.Block, li.Name);
-                                               while (si.ScopeBlock.ID != li.Block.ID){
+-                                              while (si.ScopeBlock.ID != li.Block.ID){
 -                                                      Console.WriteLine ("Trying: {0}", si.ScopeBlock.ID);
-+                                                      Console.WriteLine ("Trying: {0} {1}",
-+                                                                         si, si.ScopeBlock);
-                                                       si = si.ParentScope;
-                                               }
+-                                                      si = si.ParentScope;
+-                                              }
+-
+-                                              throw new Exception (
+-                                                           String.Format ("Never found block {0} starting at {1} while looking up {2}",
+-                                                                          li.Block.ID, am.Scope.ScopeBlock.ID, li.Name));
+-                                      }
++                                      if (si == null)
++                                              throw new InternalErrorException (
++                                                      "Never found block {0} starting at {1}",
++                                                      block.ID, am.Scope.ScopeBlock.ID);
+                               }
+                       }
+               }
+@@ -1275,132 +1823,32 @@
+               //
+               // Internal routine that loads the instance to reach parameter `name'
+               //
+-              void EmitParameterInstance (EmitContext ec, string name)
++              public void EmitParameterInstance (EmitContext ec, Parameter par)
+               {
+-                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
++                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, par);
+                       if (cc != this){
+-                              cc.EmitParameterInstance (ec, name);
++                              cc.EmitParameterInstance (ec, par);
+                               return;
+                       }
  
-@@ -1295,7 +1902,7 @@
+-                      CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+-                      if (par_info != null){
+-                              // 
+-                              // FIXME: implementing this.
+-                              //
+-                      }
+-                      ILGenerator ig = ec.ig;
+-
+                       ScopeInfo si;
  
                        if (ec.CurrentBlock.Toplevel == toplevel_owner) {
                                si = (ScopeInfo) scopes [toplevel_owner.ID];
@@ -3211,51 +3359,92 @@ Index: anonymous.cs
 +                              si.EmitScopeInstance (ec);
                        } else {
                                si = ec.CurrentAnonymousMethod.Scope;
-                               ig.Emit (OpCodes.Ldarg_0);
-@@ -1303,7 +1910,7 @@
+-                              ig.Emit (OpCodes.Ldarg_0);
++                              ec.ig.Emit (OpCodes.Ldarg_0);
+                       }
  
-                       if (si != null){
+-                      if (si != null){
++                      if (si != null) {
                                while (si.ParentLink != null) {
 -                                      ig.Emit (OpCodes.Ldfld, si.ParentLink);
-+                                      ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
++                                      ec.ig.Emit (OpCodes.Ldfld, si.ParentLink.FieldBuilder);
                                        si = si.ParentScope;
                                } 
                        }
-@@ -1328,11 +1935,11 @@
-                               // FIXME: implementing this.
-                               //
-                       }
--                      ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
-+                      ec.ig.Emit (OpCodes.Ldfld, par_info.Field.FieldBuilder);
+               }
  
-                       if (leave_copy){
-                               ec.ig.Emit (OpCodes.Dup);
+-              //
+-              // Emits the code necessary to load the parameter named `name' within
+-              // an anonymous method.
+-              //
+-              public void EmitParameter (EmitContext ec, string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
+-              {
+-                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+-                      if (cc != this){
+-                              cc.EmitParameter (ec, name, leave_copy, prepared, ref temp);
+-                              return;
+-                      }
+-                      if (!prepared)
+-                              EmitParameterInstance (ec, name);
+-                      CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+-                      if (par_info != null){
+-                              // 
+-                              // FIXME: implementing this.
+-                              //
+-                      }
+-                      ec.ig.Emit (OpCodes.Ldfld, par_info.FieldBuilder);
+-
+-                      if (leave_copy){
+-                              ec.ig.Emit (OpCodes.Dup);
 -                              temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-+                              temp = new LocalTemporary (par_info.Field.MemberType);
-                               temp.Store (ec);
-                       }
-               }
-@@ -1357,10 +1964,10 @@
-                       source.Emit (ec);
-                       if (leave_copy){
-                               ig.Emit (OpCodes.Dup);
+-                              temp.Store (ec);
+-                      }
+-              }
+-
+-              //
+-              // Implements the assignment of `source' to the paramenter named `name' within
+-              // an anonymous method.
+-              //
+-              public void EmitAssignParameter (EmitContext ec, string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary temp)
+-              {
+-                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+-                      if (cc != this){
+-                              cc.EmitAssignParameter (ec, name, source, leave_copy, prepare_for_load, ref temp);
+-                              return;
+-                      }
+-                      ILGenerator ig = ec.ig;
+-                      CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+-
+-                      EmitParameterInstance (ec, name);
+-                      if (prepare_for_load)
+-                              ig.Emit (OpCodes.Dup);
+-                      source.Emit (ec);
+-                      if (leave_copy){
+-                              ig.Emit (OpCodes.Dup);
 -                              temp = new LocalTemporary (par_info.FieldBuilder.FieldType);
-+                              temp = new LocalTemporary (par_info.Field.MemberType);
-                               temp.Store (ec);
-                       }
+-                              temp.Store (ec);
+-                      }
 -                      ig.Emit (OpCodes.Stfld, par_info.FieldBuilder);
-+                      ig.Emit (OpCodes.Stfld, par_info.Field.FieldBuilder);
-                       if (temp != null)
-                               temp.Emit (ec);
-               }
-@@ -1378,29 +1985,9 @@
-                       }
-                       EmitParameterInstance (ec, name);
-                       CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
+-                      if (temp != null)
+-                              temp.Emit (ec);
+-              }
+-
+-              //
+-              // Emits the address for the parameter named `name' within
+-              // an anonymous method.
+-              //
+-              public void EmitAddressOfParameter (EmitContext ec, string name)
+-              {
+-                      CaptureContext cc = ContextForParameter (ec.CurrentBlock.Toplevel, name);
+-                      if (cc != this){
+-                              cc.EmitAddressOfParameter (ec, name);
+-                              return;
+-                      }
+-                      EmitParameterInstance (ec, name);
+-                      CapturedParameter par_info = (CapturedParameter) captured_parameters [name];
 -                      ec.ig.Emit (OpCodes.Ldflda, par_info.FieldBuilder);
-+                      ec.ig.Emit (OpCodes.Ldflda, par_info.Field.FieldBuilder);
-               }
+-              }
+-
 -              //
 -              // The following methods are only invoked on the host for the
 -              // anonymous method.
@@ -3279,7 +3468,7 @@ Index: anonymous.cs
                public void RegisterCaptureContext ()
                {
                        toplevel_owner.RegisterCaptureContext (this);
-@@ -1474,7 +2061,7 @@
+@@ -1474,7 +1922,7 @@
                        }
                        return parent;
                }
@@ -3288,7 +3477,7 @@ Index: anonymous.cs
                //
                // Links all the scopes
                //
-@@ -1483,7 +2070,9 @@
+@@ -1483,7 +1931,9 @@
                {
                        if (linked)
                                return;
@@ -3299,7 +3488,7 @@ Index: anonymous.cs
                        linked = true;
                        if (ParentCaptureContext != null)
                                ParentCaptureContext.LinkScopes ();
-@@ -1492,9 +2081,14 @@
+@@ -1492,9 +1942,14 @@
                        ScopeInfo [] scope_list = new ScopeInfo [scope_count];
                        scopes.Values.CopyTo (scope_list, 0);
  
@@ -3314,7 +3503,7 @@ Index: anonymous.cs
                                if (parent == null){
                                        roots.Add (scope_list [i]);
                                        continue;
-@@ -1504,17 +2098,28 @@
+@@ -1504,17 +1959,28 @@
                                parent.AddChild (scope_list [i]);
                        }
  
@@ -3503,7 +3692,26 @@ Index: expression.cs
                }
  
                public override string ToString ()
-@@ -3636,15 +3600,6 @@
+@@ -3562,6 +3526,7 @@
+               }
+               LocalTemporary temp;
++              Variable variable;
+               
+               public ParameterReference (Parameter par, Block block, int idx, Location loc)
+               {
+@@ -3577,6 +3542,10 @@
+                       get { return vi; }
+               }
++              public Variable Variable {
++                      get { return variable != null ? variable : par.Variable; }
++              }
++
+               public bool VerifyFixed ()
+               {
+                       // A parameter is fixed if it's a value parameter (i.e., no modifier like out, ref, param).
+@@ -3636,15 +3605,6 @@
                                                par.Name);
                                        return false;
                                }
@@ -3519,27 +3727,105 @@ Index: expression.cs
                        }
  
                        return true;
-@@ -3684,6 +3639,9 @@
-                       if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
+@@ -3681,9 +3641,15 @@
+                       if (!DoResolveBase (ec))
+                               return null;
+-                      if (is_out && ec.DoFlowAnalysis && (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
++                      if (is_out && ec.DoFlowAnalysis &&
++                          (!ec.OmitStructFlowAnalysis || !vi.TypeInfo.IsStruct) && !IsAssigned (ec, loc))
                                return null;
  
-+                      if (ec.MustCaptureParameter (block, name))
-+                              return ec.capture_context.AddParameter (ec, par, idx, loc);
++                      if (ec.MustCaptureParameter (block, name)) {
++                              variable = ec.CaptureParameter (par, idx);
++                              type = variable.Type;
++                      }
 +
                        return this;
                }
  
-@@ -3694,6 +3652,9 @@
+@@ -3694,6 +3660,11 @@
  
                        SetAssigned (ec);
  
-+                      if (ec.MustCaptureParameter (block, name))
-+                              return ec.capture_context.AddParameter (ec, par, idx, loc);
++                      if (ec.MustCaptureParameter (block, name)) {
++                              variable = ec.CaptureParameter (par, idx);
++                              type = variable.Type;
++                      }
 +
                        return this;
                }
  
-@@ -3742,8 +3703,11 @@
+@@ -3731,7 +3702,68 @@
+                       // FIXME: Review for anonymous methods
+                       //
+               }
++
++              public override void Emit (EmitContext ec)
++              {
++                      Emit (ec, false);
++              }
+               
++              public void Emit (EmitContext ec, bool leave_copy)
++              {
++                      if (!prepared)
++                              Variable.EmitInstance (ec);
++                      Variable.Emit (ec);
++
++                      if (is_ref) {
++                              if (prepared)
++                                      ec.ig.Emit (OpCodes.Dup);
++      
++                              //
++                              // If we are a reference, we loaded on the stack a pointer
++                              // Now lets load the real value
++                              //
++                              LoadFromPtr (ec.ig, type);
++                      }
++
++                      if (leave_copy) {
++                              ec.ig.Emit (OpCodes.Dup);
++
++                              if (is_ref || Variable.NeedsTemporary) {
++                                      temp = new LocalTemporary (Type);
++                                      temp.Store (ec);
++                              }
++                      }
++              }
++
++              public void EmitAssign (EmitContext ec, Expression source, bool leave_copy,
++                                      bool prepare_for_load)
++              {
++                      ILGenerator ig = ec.ig;
++                      prepared = prepare_for_load;
++
++                      Variable.EmitInstance (ec);
++                      if (prepare_for_load)
++                              ig.Emit (OpCodes.Dup);
++                      source.Emit (ec);
++                      if (leave_copy) {
++                              ig.Emit (OpCodes.Dup);
++                              if (Variable.NeedsTemporary) {
++                                      temp = new LocalTemporary (Type);
++                                      temp.Store (ec);
++                              }
++                      }
++                      Variable.EmitAssign (ec);
++                      if (temp != null)
++                              temp.Emit (ec);
++              }
++              
++              public void AddressOf (EmitContext ec, AddressOp mode)
++              {
++                      Variable.EmitInstance (ec);
++                      Variable.EmitAddressOf (ec);
++              }
++
++#if FIXME
+               public override void Emit (EmitContext ec)
+               {
+                       Emit (ec, false);
+@@ -3742,8 +3774,11 @@
                        ILGenerator ig = ec.ig;
                        int arg_idx = idx;
  
@@ -3553,7 +3839,13 @@ Index: expression.cs
                                return;
                        }
  
-@@ -3777,15 +3741,14 @@
+@@ -3772,20 +3807,19 @@
+                               }
+                       }
+               }
+-              
++
+               public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load)
                {
                        prepared = prepare_for_load;
                        if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
@@ -3572,7 +3864,7 @@ Index: expression.cs
                        if (!ec.MethodIsStatic)
                                arg_idx++;
  
-@@ -3818,7 +3781,7 @@
+@@ -3818,7 +3852,7 @@
                public void AddressOf (EmitContext ec, AddressOp mode)
                {
                        if (ec.HaveCaptureInfo && ec.IsParameterCaptured (name)){
@@ -3581,6 +3873,14 @@ Index: expression.cs
                                return;
                        }
                        
+@@ -3839,6 +3873,7 @@
+                                       ec.ig.Emit (OpCodes.Ldarga, arg_idx);
+                       }
+               }
++#endif
+               public override string ToString ()
+               {
 Index: codegen.cs
 ===================================================================
 --- codegen.cs (revision 63019)
@@ -3616,7 +3916,7 @@ Index: codegen.cs
                // <summary>
                //   Starts a new code branching.  This inherits the state of all local
                //   variables and parameters from the current branching.
-@@ -618,23 +611,17 @@
+@@ -618,23 +611,22 @@
                        current_flow_branching = current_flow_branching.Parent;
                }
  
@@ -3629,10 +3929,12 @@ Index: codegen.cs
                }
  
 -              public void CaptureParameter (string name, Type t, int idx)
--              {
++              public Variable CaptureParameter (Parameter par, int idx)
+               {
 -                      capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
--              }
--
++                      return capture_context.AddParameter (this, par, idx);
+               }
                public void CaptureThis ()
                {
                        capture_context.CaptureThis (CurrentAnonymousMethod);
@@ -3643,37 +3945,42 @@ Index: codegen.cs
                //
                // Use to register a field as captured
                //
-@@ -664,25 +651,14 @@
+@@ -664,25 +656,21 @@
                }
  
                //
 -              // Emits the instance pointer for the host method
--              //
++              // Returns whether the `local' variable has been captured by an anonymous
++              // method
+               //
 -              public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
--              {
--                      if (capture_context != null)
++              public Variable GetCapturedVariable (LocalInfo local)
+               {
+                       if (capture_context != null)
 -                              capture_context.EmitMethodHostInstance (target, am);
 -                      else if (IsStatic)
 -                              target.ig.Emit (OpCodes.Ldnull);
 -                      else
 -                              target.ig.Emit (OpCodes.Ldarg_0);
--              }
--
++                              return capture_context.GetCapturedVariable (local);
++                      return null;
+               }
+-              //
+-              // Returns whether the `local' variable has been captured by an anonymous
+-              // method
 -              //
-               // Returns whether the `local' variable has been captured by an anonymous
-               // method
-               //
 -              public bool IsCaptured (LocalInfo local)
-+              public Variable GetCapturedVariable (LocalInfo local)
++              public Variable GetCapturedParameter (Parameter par)
                {
 -                      return capture_context.IsCaptured (local);
 +                      if (capture_context != null)
-+                              return capture_context.GetCapturedVariable (local);
++                              return capture_context.GetCapturedParameter (par);
 +                      return null;
                }
  
                public bool IsParameterCaptured (string name)
-@@ -691,6 +667,25 @@
+@@ -691,6 +679,25 @@
                                return capture_context.IsParameterCaptured (name);
                        return false;
                }
@@ -3699,7 +4006,7 @@ Index: codegen.cs
                
                public void EmitMeta (ToplevelBlock b)
                {
-@@ -783,12 +778,14 @@
+@@ -783,12 +790,14 @@
                                        return false;
                                } else if (!CurrentAnonymousMethod.IsIterator) {
                                        Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
@@ -3716,7 +4023,7 @@ Index: codegen.cs
                        resolved = true;
                        return true;
                }
-@@ -829,12 +826,6 @@
+@@ -829,12 +838,6 @@
                                        ig.Emit (OpCodes.Ret);
                                }
                        }
@@ -3729,7 +4036,7 @@ Index: codegen.cs
                }
  
                /// <summary>
-@@ -995,6 +986,8 @@
+@@ -995,6 +998,8 @@
                                HasReturnLabel = true;
                }
  
@@ -3738,7 +4045,7 @@ Index: codegen.cs
                //
                // Emits the proper object to address fields on a remapped
                // variable/parameter to field in anonymous-method/iterator proxy classes.
-@@ -1004,14 +997,22 @@
+@@ -1004,14 +1009,22 @@
                        ig.Emit (OpCodes.Ldarg_0);
                        if (capture_context != null && CurrentAnonymousMethod != null){
                                ScopeInfo si = CurrentAnonymousMethod.Scope;
@@ -3765,10 +4072,21 @@ Index: codegen.cs
                                                break;
                                        }
                                        si = si.ParentScope;
-@@ -1030,21 +1031,6 @@
-                       
-                       capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
+@@ -1019,33 +1032,6 @@
+                       } 
                }
+-              //
+-              // Emits the code necessary to load the instance required
+-              // to access the captured LocalInfo
+-              //
+-              public void EmitCapturedVariableInstance (LocalInfo li)
+-              {
+-                      if (capture_context == null)
+-                              throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
+-                      
+-                      capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
+-              }
 -
 -              public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
 -              {
@@ -3784,9 +4102,10 @@ Index: codegen.cs
 -              {
 -                      capture_context.EmitAddressOfParameter (this, name);
 -              }
-               
+-              
                public Expression GetThis (Location loc)
                {
+                       This my_this;
 Index: statement.cs
 ===================================================================
 --- statement.cs       (revision 63019)
@@ -3944,9 +4263,12 @@ Index: statement.cs
                /// <summary>
                ///   Emits the variable declarations and labels.
                /// </summary>
-@@ -1793,37 +1854,17 @@
+@@ -1791,39 +1852,19 @@
                //
-               public void EmitMeta (EmitContext ec)
+               // Emits the local variable declarations for a block
+               //
+-              public void EmitMeta (EmitContext ec)
++              public virtual void EmitMeta (EmitContext ec)
                {
 -                      ILGenerator ig = ec.ig;
 -                      
@@ -4104,7 +4426,20 @@ Index: statement.cs
                        if (capture_context == null)
                                capture_context = new CaptureContext (this, loc, host);
                }
-@@ -3299,7 +3389,7 @@
+@@ -2294,6 +2384,12 @@
+                       return Report.Errors == errors;
+               }
++
++              public override void EmitMeta (EmitContext ec)
++              {
++                      base.EmitMeta (ec);
++                      parameters.ResolveVariable (ec);
++              }
+       }
+       
+       public class SwitchLabel {
+@@ -3299,7 +3395,7 @@
                        }
  
                        public abstract void Emit (EmitContext ec);
@@ -4113,7 +4448,7 @@ Index: statement.cs
                }
  
                class ExpressionEmitter : Emitter {
-@@ -3313,14 +3403,14 @@
+@@ -3313,14 +3409,14 @@
                                // Store pointer in pinned location
                                //
                                converted.Emit (ec);
@@ -4133,7 +4468,7 @@ Index: statement.cs
                        }
                }
  
-@@ -3350,13 +3440,13 @@
+@@ -3350,13 +3446,13 @@
                                        return;
  
                                converted.Emit (ec);
@@ -4151,7 +4486,7 @@ Index: statement.cs
                        }
                }
  
-@@ -3554,13 +3644,11 @@
+@@ -3554,13 +3650,11 @@
                        if (has_ret)
                                return;
  
@@ -4166,7 +4501,7 @@ Index: statement.cs
                        }
                }
        }
-@@ -3772,22 +3860,24 @@
+@@ -3772,22 +3866,24 @@
                                
                                ig.BeginCatchBlock (c.CatchType);
  
@@ -4196,7 +4531,7 @@ Index: statement.cs
                                } else
                                        ig.Emit (OpCodes.Pop);
  
-@@ -4164,7 +4254,7 @@
+@@ -4164,7 +4260,7 @@
  
                        Type var_type = texpr.Type;
  
@@ -4205,7 +4540,7 @@ Index: statement.cs
                                Report.Error (446, expr.Location, "Foreach statement cannot operate on a `{0}'",
                                        expr.ExprClassName);
                                return false;
-@@ -4220,7 +4310,7 @@
+@@ -4220,7 +4316,7 @@
                        {
                                EmitThis (ec);
                                ec.ig.Emit (OpCodes.Ldc_I4_0);
@@ -4214,7 +4549,7 @@ Index: statement.cs
                        }
  
                        public void Increment (EmitContext ec)
-@@ -4229,7 +4319,7 @@
+@@ -4229,7 +4325,7 @@
                                Emit (ec);
                                ec.ig.Emit (OpCodes.Ldc_I4_1);
                                ec.ig.Emit (OpCodes.Add);
@@ -4223,7 +4558,7 @@ Index: statement.cs
                        }
                }
  
-@@ -4323,7 +4413,7 @@
+@@ -4323,7 +4419,7 @@
  
                                        lengths [i].EmitThis (ec);
                                        ((ArrayAccess) access).EmitGetLength (ec, i);